portaudio.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  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 "compat.h"
  27. #include "backends/base.h"
  28. #include <portaudio.h>
  29. static const ALCchar pa_device[] = "PortAudio Default";
  30. #ifdef HAVE_DYNLOAD
  31. static void *pa_handle;
  32. #define MAKE_FUNC(x) static __typeof(x) * p##x
  33. MAKE_FUNC(Pa_Initialize);
  34. MAKE_FUNC(Pa_Terminate);
  35. MAKE_FUNC(Pa_GetErrorText);
  36. MAKE_FUNC(Pa_StartStream);
  37. MAKE_FUNC(Pa_StopStream);
  38. MAKE_FUNC(Pa_OpenStream);
  39. MAKE_FUNC(Pa_CloseStream);
  40. MAKE_FUNC(Pa_GetDefaultOutputDevice);
  41. MAKE_FUNC(Pa_GetDefaultInputDevice);
  42. MAKE_FUNC(Pa_GetStreamInfo);
  43. #undef MAKE_FUNC
  44. #define Pa_Initialize pPa_Initialize
  45. #define Pa_Terminate pPa_Terminate
  46. #define Pa_GetErrorText pPa_GetErrorText
  47. #define Pa_StartStream pPa_StartStream
  48. #define Pa_StopStream pPa_StopStream
  49. #define Pa_OpenStream pPa_OpenStream
  50. #define Pa_CloseStream pPa_CloseStream
  51. #define Pa_GetDefaultOutputDevice pPa_GetDefaultOutputDevice
  52. #define Pa_GetDefaultInputDevice pPa_GetDefaultInputDevice
  53. #define Pa_GetStreamInfo pPa_GetStreamInfo
  54. #endif
  55. static ALCboolean pa_load(void)
  56. {
  57. PaError err;
  58. #ifdef HAVE_DYNLOAD
  59. if(!pa_handle)
  60. {
  61. #ifdef _WIN32
  62. # define PALIB "portaudio.dll"
  63. #elif defined(__APPLE__) && defined(__MACH__)
  64. # define PALIB "libportaudio.2.dylib"
  65. #elif defined(__OpenBSD__)
  66. # define PALIB "libportaudio.so"
  67. #else
  68. # define PALIB "libportaudio.so.2"
  69. #endif
  70. pa_handle = LoadLib(PALIB);
  71. if(!pa_handle)
  72. return ALC_FALSE;
  73. #define LOAD_FUNC(f) do { \
  74. p##f = GetSymbol(pa_handle, #f); \
  75. if(p##f == NULL) \
  76. { \
  77. CloseLib(pa_handle); \
  78. pa_handle = NULL; \
  79. return ALC_FALSE; \
  80. } \
  81. } while(0)
  82. LOAD_FUNC(Pa_Initialize);
  83. LOAD_FUNC(Pa_Terminate);
  84. LOAD_FUNC(Pa_GetErrorText);
  85. LOAD_FUNC(Pa_StartStream);
  86. LOAD_FUNC(Pa_StopStream);
  87. LOAD_FUNC(Pa_OpenStream);
  88. LOAD_FUNC(Pa_CloseStream);
  89. LOAD_FUNC(Pa_GetDefaultOutputDevice);
  90. LOAD_FUNC(Pa_GetDefaultInputDevice);
  91. LOAD_FUNC(Pa_GetStreamInfo);
  92. #undef LOAD_FUNC
  93. if((err=Pa_Initialize()) != paNoError)
  94. {
  95. ERR("Pa_Initialize() returned an error: %s\n", Pa_GetErrorText(err));
  96. CloseLib(pa_handle);
  97. pa_handle = NULL;
  98. return ALC_FALSE;
  99. }
  100. }
  101. #else
  102. if((err=Pa_Initialize()) != paNoError)
  103. {
  104. ERR("Pa_Initialize() returned an error: %s\n", Pa_GetErrorText(err));
  105. return ALC_FALSE;
  106. }
  107. #endif
  108. return ALC_TRUE;
  109. }
  110. typedef struct ALCportPlayback {
  111. DERIVE_FROM_TYPE(ALCbackend);
  112. PaStream *stream;
  113. PaStreamParameters params;
  114. ALuint update_size;
  115. } ALCportPlayback;
  116. static int ALCportPlayback_WriteCallback(const void *inputBuffer, void *outputBuffer,
  117. unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
  118. const PaStreamCallbackFlags statusFlags, void *userData);
  119. static void ALCportPlayback_Construct(ALCportPlayback *self, ALCdevice *device);
  120. static void ALCportPlayback_Destruct(ALCportPlayback *self);
  121. static ALCenum ALCportPlayback_open(ALCportPlayback *self, const ALCchar *name);
  122. static void ALCportPlayback_close(ALCportPlayback *self);
  123. static ALCboolean ALCportPlayback_reset(ALCportPlayback *self);
  124. static ALCboolean ALCportPlayback_start(ALCportPlayback *self);
  125. static void ALCportPlayback_stop(ALCportPlayback *self);
  126. static DECLARE_FORWARD2(ALCportPlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint)
  127. static DECLARE_FORWARD(ALCportPlayback, ALCbackend, ALCuint, availableSamples)
  128. static DECLARE_FORWARD(ALCportPlayback, ALCbackend, ClockLatency, getClockLatency)
  129. static DECLARE_FORWARD(ALCportPlayback, ALCbackend, void, lock)
  130. static DECLARE_FORWARD(ALCportPlayback, ALCbackend, void, unlock)
  131. DECLARE_DEFAULT_ALLOCATORS(ALCportPlayback)
  132. DEFINE_ALCBACKEND_VTABLE(ALCportPlayback);
  133. static void ALCportPlayback_Construct(ALCportPlayback *self, ALCdevice *device)
  134. {
  135. ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
  136. SET_VTABLE2(ALCportPlayback, ALCbackend, self);
  137. self->stream = NULL;
  138. }
  139. static void ALCportPlayback_Destruct(ALCportPlayback *self)
  140. {
  141. if(self->stream)
  142. Pa_CloseStream(self->stream);
  143. self->stream = NULL;
  144. ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
  145. }
  146. static int ALCportPlayback_WriteCallback(const void *UNUSED(inputBuffer), void *outputBuffer,
  147. unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *UNUSED(timeInfo),
  148. const PaStreamCallbackFlags UNUSED(statusFlags), void *userData)
  149. {
  150. ALCportPlayback *self = userData;
  151. aluMixData(STATIC_CAST(ALCbackend, self)->mDevice, outputBuffer, framesPerBuffer);
  152. return 0;
  153. }
  154. static ALCenum ALCportPlayback_open(ALCportPlayback *self, const ALCchar *name)
  155. {
  156. ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
  157. PaError err;
  158. if(!name)
  159. name = pa_device;
  160. else if(strcmp(name, pa_device) != 0)
  161. return ALC_INVALID_VALUE;
  162. self->update_size = device->UpdateSize;
  163. self->params.device = -1;
  164. if(!ConfigValueInt(NULL, "port", "device", &self->params.device) ||
  165. self->params.device < 0)
  166. self->params.device = Pa_GetDefaultOutputDevice();
  167. self->params.suggestedLatency = (device->UpdateSize*device->NumUpdates) /
  168. (float)device->Frequency;
  169. self->params.hostApiSpecificStreamInfo = NULL;
  170. self->params.channelCount = ((device->FmtChans == DevFmtMono) ? 1 : 2);
  171. switch(device->FmtType)
  172. {
  173. case DevFmtByte:
  174. self->params.sampleFormat = paInt8;
  175. break;
  176. case DevFmtUByte:
  177. self->params.sampleFormat = paUInt8;
  178. break;
  179. case DevFmtUShort:
  180. /* fall-through */
  181. case DevFmtShort:
  182. self->params.sampleFormat = paInt16;
  183. break;
  184. case DevFmtUInt:
  185. /* fall-through */
  186. case DevFmtInt:
  187. self->params.sampleFormat = paInt32;
  188. break;
  189. case DevFmtFloat:
  190. self->params.sampleFormat = paFloat32;
  191. break;
  192. }
  193. retry_open:
  194. err = Pa_OpenStream(&self->stream, NULL, &self->params,
  195. device->Frequency, device->UpdateSize, paNoFlag,
  196. ALCportPlayback_WriteCallback, self
  197. );
  198. if(err != paNoError)
  199. {
  200. if(self->params.sampleFormat == paFloat32)
  201. {
  202. self->params.sampleFormat = paInt16;
  203. goto retry_open;
  204. }
  205. ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
  206. return ALC_INVALID_VALUE;
  207. }
  208. al_string_copy_cstr(&device->DeviceName, name);
  209. return ALC_NO_ERROR;
  210. }
  211. static void ALCportPlayback_close(ALCportPlayback *self)
  212. {
  213. PaError err = Pa_CloseStream(self->stream);
  214. if(err != paNoError)
  215. ERR("Error closing stream: %s\n", Pa_GetErrorText(err));
  216. self->stream = NULL;
  217. }
  218. static ALCboolean ALCportPlayback_reset(ALCportPlayback *self)
  219. {
  220. ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
  221. const PaStreamInfo *streamInfo;
  222. streamInfo = Pa_GetStreamInfo(self->stream);
  223. device->Frequency = streamInfo->sampleRate;
  224. device->UpdateSize = self->update_size;
  225. if(self->params.sampleFormat == paInt8)
  226. device->FmtType = DevFmtByte;
  227. else if(self->params.sampleFormat == paUInt8)
  228. device->FmtType = DevFmtUByte;
  229. else if(self->params.sampleFormat == paInt16)
  230. device->FmtType = DevFmtShort;
  231. else if(self->params.sampleFormat == paInt32)
  232. device->FmtType = DevFmtInt;
  233. else if(self->params.sampleFormat == paFloat32)
  234. device->FmtType = DevFmtFloat;
  235. else
  236. {
  237. ERR("Unexpected sample format: 0x%lx\n", self->params.sampleFormat);
  238. return ALC_FALSE;
  239. }
  240. if(self->params.channelCount == 2)
  241. device->FmtChans = DevFmtStereo;
  242. else if(self->params.channelCount == 1)
  243. device->FmtChans = DevFmtMono;
  244. else
  245. {
  246. ERR("Unexpected channel count: %u\n", self->params.channelCount);
  247. return ALC_FALSE;
  248. }
  249. SetDefaultChannelOrder(device);
  250. return ALC_TRUE;
  251. }
  252. static ALCboolean ALCportPlayback_start(ALCportPlayback *self)
  253. {
  254. PaError err;
  255. err = Pa_StartStream(self->stream);
  256. if(err != paNoError)
  257. {
  258. ERR("Pa_StartStream() returned an error: %s\n", Pa_GetErrorText(err));
  259. return ALC_FALSE;
  260. }
  261. return ALC_TRUE;
  262. }
  263. static void ALCportPlayback_stop(ALCportPlayback *self)
  264. {
  265. PaError err = Pa_StopStream(self->stream);
  266. if(err != paNoError)
  267. ERR("Error stopping stream: %s\n", Pa_GetErrorText(err));
  268. }
  269. typedef struct ALCportCapture {
  270. DERIVE_FROM_TYPE(ALCbackend);
  271. PaStream *stream;
  272. PaStreamParameters params;
  273. ll_ringbuffer_t *ring;
  274. } ALCportCapture;
  275. static int ALCportCapture_ReadCallback(const void *inputBuffer, void *outputBuffer,
  276. unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
  277. const PaStreamCallbackFlags statusFlags, void *userData);
  278. static void ALCportCapture_Construct(ALCportCapture *self, ALCdevice *device);
  279. static void ALCportCapture_Destruct(ALCportCapture *self);
  280. static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name);
  281. static void ALCportCapture_close(ALCportCapture *self);
  282. static DECLARE_FORWARD(ALCportCapture, ALCbackend, ALCboolean, reset)
  283. static ALCboolean ALCportCapture_start(ALCportCapture *self);
  284. static void ALCportCapture_stop(ALCportCapture *self);
  285. static ALCenum ALCportCapture_captureSamples(ALCportCapture *self, ALCvoid *buffer, ALCuint samples);
  286. static ALCuint ALCportCapture_availableSamples(ALCportCapture *self);
  287. static DECLARE_FORWARD(ALCportCapture, ALCbackend, ClockLatency, getClockLatency)
  288. static DECLARE_FORWARD(ALCportCapture, ALCbackend, void, lock)
  289. static DECLARE_FORWARD(ALCportCapture, ALCbackend, void, unlock)
  290. DECLARE_DEFAULT_ALLOCATORS(ALCportCapture)
  291. DEFINE_ALCBACKEND_VTABLE(ALCportCapture);
  292. static void ALCportCapture_Construct(ALCportCapture *self, ALCdevice *device)
  293. {
  294. ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
  295. SET_VTABLE2(ALCportCapture, ALCbackend, self);
  296. self->stream = NULL;
  297. }
  298. static void ALCportCapture_Destruct(ALCportCapture *self)
  299. {
  300. if(self->stream)
  301. Pa_CloseStream(self->stream);
  302. self->stream = NULL;
  303. if(self->ring)
  304. ll_ringbuffer_free(self->ring);
  305. self->ring = NULL;
  306. ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
  307. }
  308. static int ALCportCapture_ReadCallback(const void *inputBuffer, void *UNUSED(outputBuffer),
  309. unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *UNUSED(timeInfo),
  310. const PaStreamCallbackFlags UNUSED(statusFlags), void *userData)
  311. {
  312. ALCportCapture *self = userData;
  313. size_t writable = ll_ringbuffer_write_space(self->ring);
  314. if(framesPerBuffer > writable)
  315. framesPerBuffer = writable;
  316. ll_ringbuffer_write(self->ring, inputBuffer, framesPerBuffer);
  317. return 0;
  318. }
  319. static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name)
  320. {
  321. ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
  322. ALuint samples, frame_size;
  323. PaError err;
  324. if(!name)
  325. name = pa_device;
  326. else if(strcmp(name, pa_device) != 0)
  327. return ALC_INVALID_VALUE;
  328. samples = device->UpdateSize * device->NumUpdates;
  329. samples = maxu(samples, 100 * device->Frequency / 1000);
  330. frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
  331. self->ring = ll_ringbuffer_create(samples, frame_size);
  332. if(self->ring == NULL) return ALC_INVALID_VALUE;
  333. self->params.device = -1;
  334. if(!ConfigValueInt(NULL, "port", "capture", &self->params.device) ||
  335. self->params.device < 0)
  336. self->params.device = Pa_GetDefaultInputDevice();
  337. self->params.suggestedLatency = 0.0f;
  338. self->params.hostApiSpecificStreamInfo = NULL;
  339. switch(device->FmtType)
  340. {
  341. case DevFmtByte:
  342. self->params.sampleFormat = paInt8;
  343. break;
  344. case DevFmtUByte:
  345. self->params.sampleFormat = paUInt8;
  346. break;
  347. case DevFmtShort:
  348. self->params.sampleFormat = paInt16;
  349. break;
  350. case DevFmtInt:
  351. self->params.sampleFormat = paInt32;
  352. break;
  353. case DevFmtFloat:
  354. self->params.sampleFormat = paFloat32;
  355. break;
  356. case DevFmtUInt:
  357. case DevFmtUShort:
  358. ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType));
  359. return ALC_INVALID_VALUE;
  360. }
  361. self->params.channelCount = ChannelsFromDevFmt(device->FmtChans);
  362. err = Pa_OpenStream(&self->stream, &self->params, NULL,
  363. device->Frequency, paFramesPerBufferUnspecified, paNoFlag,
  364. ALCportCapture_ReadCallback, self
  365. );
  366. if(err != paNoError)
  367. {
  368. ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
  369. return ALC_INVALID_VALUE;
  370. }
  371. al_string_copy_cstr(&device->DeviceName, name);
  372. return ALC_NO_ERROR;
  373. }
  374. static void ALCportCapture_close(ALCportCapture *self)
  375. {
  376. PaError err = Pa_CloseStream(self->stream);
  377. if(err != paNoError)
  378. ERR("Error closing stream: %s\n", Pa_GetErrorText(err));
  379. self->stream = NULL;
  380. ll_ringbuffer_free(self->ring);
  381. self->ring = NULL;
  382. }
  383. static ALCboolean ALCportCapture_start(ALCportCapture *self)
  384. {
  385. PaError err = Pa_StartStream(self->stream);
  386. if(err != paNoError)
  387. {
  388. ERR("Error starting stream: %s\n", Pa_GetErrorText(err));
  389. return ALC_FALSE;
  390. }
  391. return ALC_TRUE;
  392. }
  393. static void ALCportCapture_stop(ALCportCapture *self)
  394. {
  395. PaError err = Pa_StopStream(self->stream);
  396. if(err != paNoError)
  397. ERR("Error stopping stream: %s\n", Pa_GetErrorText(err));
  398. }
  399. static ALCuint ALCportCapture_availableSamples(ALCportCapture *self)
  400. {
  401. return ll_ringbuffer_read_space(self->ring);
  402. }
  403. static ALCenum ALCportCapture_captureSamples(ALCportCapture *self, ALCvoid *buffer, ALCuint samples)
  404. {
  405. ll_ringbuffer_read(self->ring, buffer, samples);
  406. return ALC_NO_ERROR;
  407. }
  408. typedef struct ALCportBackendFactory {
  409. DERIVE_FROM_TYPE(ALCbackendFactory);
  410. } ALCportBackendFactory;
  411. #define ALCPORTBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCportBackendFactory, ALCbackendFactory) } }
  412. static ALCboolean ALCportBackendFactory_init(ALCportBackendFactory *self);
  413. static void ALCportBackendFactory_deinit(ALCportBackendFactory *self);
  414. static ALCboolean ALCportBackendFactory_querySupport(ALCportBackendFactory *self, ALCbackend_Type type);
  415. static void ALCportBackendFactory_probe(ALCportBackendFactory *self, enum DevProbe type);
  416. static ALCbackend* ALCportBackendFactory_createBackend(ALCportBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
  417. DEFINE_ALCBACKENDFACTORY_VTABLE(ALCportBackendFactory);
  418. static ALCboolean ALCportBackendFactory_init(ALCportBackendFactory* UNUSED(self))
  419. {
  420. if(!pa_load())
  421. return ALC_FALSE;
  422. return ALC_TRUE;
  423. }
  424. static void ALCportBackendFactory_deinit(ALCportBackendFactory* UNUSED(self))
  425. {
  426. #ifdef HAVE_DYNLOAD
  427. if(pa_handle)
  428. {
  429. Pa_Terminate();
  430. CloseLib(pa_handle);
  431. pa_handle = NULL;
  432. }
  433. #else
  434. Pa_Terminate();
  435. #endif
  436. }
  437. static ALCboolean ALCportBackendFactory_querySupport(ALCportBackendFactory* UNUSED(self), ALCbackend_Type type)
  438. {
  439. if(type == ALCbackend_Playback || type == ALCbackend_Capture)
  440. return ALC_TRUE;
  441. return ALC_FALSE;
  442. }
  443. static void ALCportBackendFactory_probe(ALCportBackendFactory* UNUSED(self), enum DevProbe type)
  444. {
  445. switch(type)
  446. {
  447. case ALL_DEVICE_PROBE:
  448. AppendAllDevicesList(pa_device);
  449. break;
  450. case CAPTURE_DEVICE_PROBE:
  451. AppendCaptureDeviceList(pa_device);
  452. break;
  453. }
  454. }
  455. static ALCbackend* ALCportBackendFactory_createBackend(ALCportBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
  456. {
  457. if(type == ALCbackend_Playback)
  458. {
  459. ALCportPlayback *backend;
  460. NEW_OBJ(backend, ALCportPlayback)(device);
  461. if(!backend) return NULL;
  462. return STATIC_CAST(ALCbackend, backend);
  463. }
  464. if(type == ALCbackend_Capture)
  465. {
  466. ALCportCapture *backend;
  467. NEW_OBJ(backend, ALCportCapture)(device);
  468. if(!backend) return NULL;
  469. return STATIC_CAST(ALCbackend, backend);
  470. }
  471. return NULL;
  472. }
  473. ALCbackendFactory *ALCportBackendFactory_getFactory(void)
  474. {
  475. static ALCportBackendFactory factory = ALCPORTBACKENDFACTORY_INITIALIZER;
  476. return STATIC_CAST(ALCbackendFactory, &factory);
  477. }