opensl.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070
  1. /*
  2. * Copyright (C) 2011 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /* This is an OpenAL backend for Android using the native audio APIs based on
  17. * OpenSL ES 1.0.1. It is based on source code for the native-audio sample app
  18. * bundled with NDK.
  19. */
  20. #include "config.h"
  21. #include <stdlib.h>
  22. #include <jni.h>
  23. #include "alMain.h"
  24. #include "alu.h"
  25. #include "ringbuffer.h"
  26. #include "threads.h"
  27. #include "compat.h"
  28. #include "backends/base.h"
  29. #include <SLES/OpenSLES.h>
  30. #include <SLES/OpenSLES_Android.h>
  31. #include <SLES/OpenSLES_AndroidConfiguration.h>
  32. /* Helper macros */
  33. #define VCALL(obj, func) ((*(obj))->func((obj), EXTRACT_VCALL_ARGS
  34. #define VCALL0(obj, func) ((*(obj))->func((obj) EXTRACT_VCALL_ARGS
  35. static const ALCchar opensl_device[] = "OpenSL";
  36. static SLuint32 GetChannelMask(enum DevFmtChannels chans)
  37. {
  38. switch(chans)
  39. {
  40. case DevFmtMono: return SL_SPEAKER_FRONT_CENTER;
  41. case DevFmtStereo: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT;
  42. case DevFmtQuad: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
  43. SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT;
  44. case DevFmtX51: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
  45. SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
  46. SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
  47. case DevFmtX51Rear: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
  48. SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
  49. SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT;
  50. case DevFmtX61: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
  51. SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
  52. SL_SPEAKER_BACK_CENTER|
  53. SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
  54. case DevFmtX71: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
  55. SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
  56. SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT|
  57. SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
  58. case DevFmtAmbi3D:
  59. break;
  60. }
  61. return 0;
  62. }
  63. #ifdef SL_DATAFORMAT_PCM_EX
  64. static SLuint32 GetTypeRepresentation(enum DevFmtType type)
  65. {
  66. switch(type)
  67. {
  68. case DevFmtUByte:
  69. case DevFmtUShort:
  70. case DevFmtUInt:
  71. return SL_PCM_REPRESENTATION_UNSIGNED_INT;
  72. case DevFmtByte:
  73. case DevFmtShort:
  74. case DevFmtInt:
  75. return SL_PCM_REPRESENTATION_SIGNED_INT;
  76. case DevFmtFloat:
  77. return SL_PCM_REPRESENTATION_FLOAT;
  78. }
  79. return 0;
  80. }
  81. #endif
  82. static const char *res_str(SLresult result)
  83. {
  84. switch(result)
  85. {
  86. case SL_RESULT_SUCCESS: return "Success";
  87. case SL_RESULT_PRECONDITIONS_VIOLATED: return "Preconditions violated";
  88. case SL_RESULT_PARAMETER_INVALID: return "Parameter invalid";
  89. case SL_RESULT_MEMORY_FAILURE: return "Memory failure";
  90. case SL_RESULT_RESOURCE_ERROR: return "Resource error";
  91. case SL_RESULT_RESOURCE_LOST: return "Resource lost";
  92. case SL_RESULT_IO_ERROR: return "I/O error";
  93. case SL_RESULT_BUFFER_INSUFFICIENT: return "Buffer insufficient";
  94. case SL_RESULT_CONTENT_CORRUPTED: return "Content corrupted";
  95. case SL_RESULT_CONTENT_UNSUPPORTED: return "Content unsupported";
  96. case SL_RESULT_CONTENT_NOT_FOUND: return "Content not found";
  97. case SL_RESULT_PERMISSION_DENIED: return "Permission denied";
  98. case SL_RESULT_FEATURE_UNSUPPORTED: return "Feature unsupported";
  99. case SL_RESULT_INTERNAL_ERROR: return "Internal error";
  100. case SL_RESULT_UNKNOWN_ERROR: return "Unknown error";
  101. case SL_RESULT_OPERATION_ABORTED: return "Operation aborted";
  102. case SL_RESULT_CONTROL_LOST: return "Control lost";
  103. #ifdef SL_RESULT_READONLY
  104. case SL_RESULT_READONLY: return "ReadOnly";
  105. #endif
  106. #ifdef SL_RESULT_ENGINEOPTION_UNSUPPORTED
  107. case SL_RESULT_ENGINEOPTION_UNSUPPORTED: return "Engine option unsupported";
  108. #endif
  109. #ifdef SL_RESULT_SOURCE_SINK_INCOMPATIBLE
  110. case SL_RESULT_SOURCE_SINK_INCOMPATIBLE: return "Source/Sink incompatible";
  111. #endif
  112. }
  113. return "Unknown error code";
  114. }
  115. #define PRINTERR(x, s) do { \
  116. if((x) != SL_RESULT_SUCCESS) \
  117. ERR("%s: %s\n", (s), res_str((x))); \
  118. } while(0)
  119. typedef struct ALCopenslPlayback {
  120. DERIVE_FROM_TYPE(ALCbackend);
  121. /* engine interfaces */
  122. SLObjectItf mEngineObj;
  123. SLEngineItf mEngine;
  124. /* output mix interfaces */
  125. SLObjectItf mOutputMix;
  126. /* buffer queue player interfaces */
  127. SLObjectItf mBufferQueueObj;
  128. ll_ringbuffer_t *mRing;
  129. alsem_t mSem;
  130. ALsizei mFrameSize;
  131. ATOMIC(ALenum) mKillNow;
  132. althrd_t mThread;
  133. } ALCopenslPlayback;
  134. static void ALCopenslPlayback_process(SLAndroidSimpleBufferQueueItf bq, void *context);
  135. static int ALCopenslPlayback_mixerProc(void *arg);
  136. static void ALCopenslPlayback_Construct(ALCopenslPlayback *self, ALCdevice *device);
  137. static void ALCopenslPlayback_Destruct(ALCopenslPlayback *self);
  138. static ALCenum ALCopenslPlayback_open(ALCopenslPlayback *self, const ALCchar *name);
  139. static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self);
  140. static ALCboolean ALCopenslPlayback_start(ALCopenslPlayback *self);
  141. static void ALCopenslPlayback_stop(ALCopenslPlayback *self);
  142. static DECLARE_FORWARD2(ALCopenslPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
  143. static DECLARE_FORWARD(ALCopenslPlayback, ALCbackend, ALCuint, availableSamples)
  144. static ClockLatency ALCopenslPlayback_getClockLatency(ALCopenslPlayback *self);
  145. static DECLARE_FORWARD(ALCopenslPlayback, ALCbackend, void, lock)
  146. static DECLARE_FORWARD(ALCopenslPlayback, ALCbackend, void, unlock)
  147. DECLARE_DEFAULT_ALLOCATORS(ALCopenslPlayback)
  148. DEFINE_ALCBACKEND_VTABLE(ALCopenslPlayback);
  149. static void ALCopenslPlayback_Construct(ALCopenslPlayback *self, ALCdevice *device)
  150. {
  151. ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
  152. SET_VTABLE2(ALCopenslPlayback, ALCbackend, self);
  153. self->mEngineObj = NULL;
  154. self->mEngine = NULL;
  155. self->mOutputMix = NULL;
  156. self->mBufferQueueObj = NULL;
  157. self->mRing = NULL;
  158. alsem_init(&self->mSem, 0);
  159. self->mFrameSize = 0;
  160. ATOMIC_INIT(&self->mKillNow, AL_FALSE);
  161. }
  162. static void ALCopenslPlayback_Destruct(ALCopenslPlayback* self)
  163. {
  164. if(self->mBufferQueueObj != NULL)
  165. VCALL0(self->mBufferQueueObj,Destroy)();
  166. self->mBufferQueueObj = NULL;
  167. if(self->mOutputMix)
  168. VCALL0(self->mOutputMix,Destroy)();
  169. self->mOutputMix = NULL;
  170. if(self->mEngineObj)
  171. VCALL0(self->mEngineObj,Destroy)();
  172. self->mEngineObj = NULL;
  173. self->mEngine = NULL;
  174. ll_ringbuffer_free(self->mRing);
  175. self->mRing = NULL;
  176. alsem_destroy(&self->mSem);
  177. ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
  178. }
  179. /* this callback handler is called every time a buffer finishes playing */
  180. static void ALCopenslPlayback_process(SLAndroidSimpleBufferQueueItf UNUSED(bq), void *context)
  181. {
  182. ALCopenslPlayback *self = context;
  183. /* A note on the ringbuffer usage: The buffer queue seems to hold on to the
  184. * pointer passed to the Enqueue method, rather than copying the audio.
  185. * Consequently, the ringbuffer contains the audio that is currently queued
  186. * and waiting to play. This process() callback is called when a buffer is
  187. * finished, so we simply move the read pointer up to indicate the space is
  188. * available for writing again, and wake up the mixer thread to mix and
  189. * queue more audio.
  190. */
  191. ll_ringbuffer_read_advance(self->mRing, 1);
  192. alsem_post(&self->mSem);
  193. }
  194. static int ALCopenslPlayback_mixerProc(void *arg)
  195. {
  196. ALCopenslPlayback *self = arg;
  197. ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
  198. SLAndroidSimpleBufferQueueItf bufferQueue;
  199. ll_ringbuffer_data_t data[2];
  200. SLPlayItf player;
  201. SLresult result;
  202. SetRTPriority();
  203. althrd_setname(althrd_current(), MIXER_THREAD_NAME);
  204. result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
  205. &bufferQueue);
  206. PRINTERR(result, "bufferQueue->GetInterface SL_IID_ANDROIDSIMPLEBUFFERQUEUE");
  207. if(SL_RESULT_SUCCESS == result)
  208. {
  209. result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player);
  210. PRINTERR(result, "bufferQueue->GetInterface SL_IID_PLAY");
  211. }
  212. ALCopenslPlayback_lock(self);
  213. if(SL_RESULT_SUCCESS != result)
  214. aluHandleDisconnect(device, "Failed to get playback buffer: 0x%08x", result);
  215. while(SL_RESULT_SUCCESS == result &&
  216. !ATOMIC_LOAD(&self->mKillNow, almemory_order_acquire) &&
  217. ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
  218. {
  219. size_t todo;
  220. if(ll_ringbuffer_write_space(self->mRing) == 0)
  221. {
  222. SLuint32 state = 0;
  223. result = VCALL(player,GetPlayState)(&state);
  224. PRINTERR(result, "player->GetPlayState");
  225. if(SL_RESULT_SUCCESS == result && state != SL_PLAYSTATE_PLAYING)
  226. {
  227. result = VCALL(player,SetPlayState)(SL_PLAYSTATE_PLAYING);
  228. PRINTERR(result, "player->SetPlayState");
  229. }
  230. if(SL_RESULT_SUCCESS != result)
  231. {
  232. aluHandleDisconnect(device, "Failed to start platback: 0x%08x", result);
  233. break;
  234. }
  235. if(ll_ringbuffer_write_space(self->mRing) == 0)
  236. {
  237. ALCopenslPlayback_unlock(self);
  238. alsem_wait(&self->mSem);
  239. ALCopenslPlayback_lock(self);
  240. continue;
  241. }
  242. }
  243. ll_ringbuffer_get_write_vector(self->mRing, data);
  244. aluMixData(device, data[0].buf, data[0].len*device->UpdateSize);
  245. if(data[1].len > 0)
  246. aluMixData(device, data[1].buf, data[1].len*device->UpdateSize);
  247. todo = data[0].len+data[1].len;
  248. ll_ringbuffer_write_advance(self->mRing, todo);
  249. for(size_t i = 0;i < todo;i++)
  250. {
  251. if(!data[0].len)
  252. {
  253. data[0] = data[1];
  254. data[1].buf = NULL;
  255. data[1].len = 0;
  256. }
  257. result = VCALL(bufferQueue,Enqueue)(data[0].buf, device->UpdateSize*self->mFrameSize);
  258. PRINTERR(result, "bufferQueue->Enqueue");
  259. if(SL_RESULT_SUCCESS != result)
  260. {
  261. aluHandleDisconnect(device, "Failed to queue audio: 0x%08x", result);
  262. break;
  263. }
  264. data[0].len--;
  265. data[0].buf += device->UpdateSize*self->mFrameSize;
  266. }
  267. }
  268. ALCopenslPlayback_unlock(self);
  269. return 0;
  270. }
  271. static ALCenum ALCopenslPlayback_open(ALCopenslPlayback *self, const ALCchar *name)
  272. {
  273. ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
  274. SLresult result;
  275. if(!name)
  276. name = opensl_device;
  277. else if(strcmp(name, opensl_device) != 0)
  278. return ALC_INVALID_VALUE;
  279. // create engine
  280. result = slCreateEngine(&self->mEngineObj, 0, NULL, 0, NULL, NULL);
  281. PRINTERR(result, "slCreateEngine");
  282. if(SL_RESULT_SUCCESS == result)
  283. {
  284. result = VCALL(self->mEngineObj,Realize)(SL_BOOLEAN_FALSE);
  285. PRINTERR(result, "engine->Realize");
  286. }
  287. if(SL_RESULT_SUCCESS == result)
  288. {
  289. result = VCALL(self->mEngineObj,GetInterface)(SL_IID_ENGINE, &self->mEngine);
  290. PRINTERR(result, "engine->GetInterface");
  291. }
  292. if(SL_RESULT_SUCCESS == result)
  293. {
  294. result = VCALL(self->mEngine,CreateOutputMix)(&self->mOutputMix, 0, NULL, NULL);
  295. PRINTERR(result, "engine->CreateOutputMix");
  296. }
  297. if(SL_RESULT_SUCCESS == result)
  298. {
  299. result = VCALL(self->mOutputMix,Realize)(SL_BOOLEAN_FALSE);
  300. PRINTERR(result, "outputMix->Realize");
  301. }
  302. if(SL_RESULT_SUCCESS != result)
  303. {
  304. if(self->mOutputMix != NULL)
  305. VCALL0(self->mOutputMix,Destroy)();
  306. self->mOutputMix = NULL;
  307. if(self->mEngineObj != NULL)
  308. VCALL0(self->mEngineObj,Destroy)();
  309. self->mEngineObj = NULL;
  310. self->mEngine = NULL;
  311. return ALC_INVALID_VALUE;
  312. }
  313. alstr_copy_cstr(&device->DeviceName, name);
  314. return ALC_NO_ERROR;
  315. }
  316. static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self)
  317. {
  318. ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
  319. SLDataLocator_AndroidSimpleBufferQueue loc_bufq;
  320. SLDataLocator_OutputMix loc_outmix;
  321. SLDataSource audioSrc;
  322. SLDataSink audioSnk;
  323. ALuint sampleRate;
  324. SLInterfaceID ids[2];
  325. SLboolean reqs[2];
  326. SLresult result;
  327. if(self->mBufferQueueObj != NULL)
  328. VCALL0(self->mBufferQueueObj,Destroy)();
  329. self->mBufferQueueObj = NULL;
  330. ll_ringbuffer_free(self->mRing);
  331. self->mRing = NULL;
  332. sampleRate = device->Frequency;
  333. #if 0
  334. if(!(device->Flags&DEVICE_FREQUENCY_REQUEST))
  335. {
  336. /* FIXME: Disabled until I figure out how to get the Context needed for
  337. * the getSystemService call.
  338. */
  339. JNIEnv *env = Android_GetJNIEnv();
  340. jobject jctx = Android_GetContext();
  341. /* Get necessary stuff for using java.lang.Integer,
  342. * android.content.Context, and android.media.AudioManager.
  343. */
  344. jclass int_cls = JCALL(env,FindClass)("java/lang/Integer");
  345. jmethodID int_parseint = JCALL(env,GetStaticMethodID)(int_cls,
  346. "parseInt", "(Ljava/lang/String;)I"
  347. );
  348. TRACE("Integer: %p, parseInt: %p\n", int_cls, int_parseint);
  349. jclass ctx_cls = JCALL(env,FindClass)("android/content/Context");
  350. jfieldID ctx_audsvc = JCALL(env,GetStaticFieldID)(ctx_cls,
  351. "AUDIO_SERVICE", "Ljava/lang/String;"
  352. );
  353. jmethodID ctx_getSysSvc = JCALL(env,GetMethodID)(ctx_cls,
  354. "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"
  355. );
  356. TRACE("Context: %p, AUDIO_SERVICE: %p, getSystemService: %p\n",
  357. ctx_cls, ctx_audsvc, ctx_getSysSvc);
  358. jclass audmgr_cls = JCALL(env,FindClass)("android/media/AudioManager");
  359. jfieldID audmgr_prop_out_srate = JCALL(env,GetStaticFieldID)(audmgr_cls,
  360. "PROPERTY_OUTPUT_SAMPLE_RATE", "Ljava/lang/String;"
  361. );
  362. jmethodID audmgr_getproperty = JCALL(env,GetMethodID)(audmgr_cls,
  363. "getProperty", "(Ljava/lang/String;)Ljava/lang/String;"
  364. );
  365. TRACE("AudioManager: %p, PROPERTY_OUTPUT_SAMPLE_RATE: %p, getProperty: %p\n",
  366. audmgr_cls, audmgr_prop_out_srate, audmgr_getproperty);
  367. const char *strchars;
  368. jstring strobj;
  369. /* Now make the calls. */
  370. //AudioManager audMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
  371. strobj = JCALL(env,GetStaticObjectField)(ctx_cls, ctx_audsvc);
  372. jobject audMgr = JCALL(env,CallObjectMethod)(jctx, ctx_getSysSvc, strobj);
  373. strchars = JCALL(env,GetStringUTFChars)(strobj, NULL);
  374. TRACE("Context.getSystemService(%s) = %p\n", strchars, audMgr);
  375. JCALL(env,ReleaseStringUTFChars)(strobj, strchars);
  376. //String srateStr = audMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
  377. strobj = JCALL(env,GetStaticObjectField)(audmgr_cls, audmgr_prop_out_srate);
  378. jstring srateStr = JCALL(env,CallObjectMethod)(audMgr, audmgr_getproperty, strobj);
  379. strchars = JCALL(env,GetStringUTFChars)(strobj, NULL);
  380. TRACE("audMgr.getProperty(%s) = %p\n", strchars, srateStr);
  381. JCALL(env,ReleaseStringUTFChars)(strobj, strchars);
  382. //int sampleRate = Integer.parseInt(srateStr);
  383. sampleRate = JCALL(env,CallStaticIntMethod)(int_cls, int_parseint, srateStr);
  384. strchars = JCALL(env,GetStringUTFChars)(srateStr, NULL);
  385. TRACE("Got system sample rate %uhz (%s)\n", sampleRate, strchars);
  386. JCALL(env,ReleaseStringUTFChars)(srateStr, strchars);
  387. if(!sampleRate) sampleRate = device->Frequency;
  388. else sampleRate = maxu(sampleRate, MIN_OUTPUT_RATE);
  389. }
  390. #endif
  391. if(sampleRate != device->Frequency)
  392. {
  393. device->NumUpdates = (device->NumUpdates*sampleRate + (device->Frequency>>1)) /
  394. device->Frequency;
  395. device->NumUpdates = maxu(device->NumUpdates, 2);
  396. device->Frequency = sampleRate;
  397. }
  398. device->FmtChans = DevFmtStereo;
  399. device->FmtType = DevFmtShort;
  400. SetDefaultWFXChannelOrder(device);
  401. self->mFrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
  402. loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
  403. loc_bufq.numBuffers = device->NumUpdates;
  404. #ifdef SL_DATAFORMAT_PCM_EX
  405. SLDataFormat_PCM_EX format_pcm;
  406. format_pcm.formatType = SL_DATAFORMAT_PCM_EX;
  407. format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
  408. format_pcm.sampleRate = device->Frequency * 1000;
  409. format_pcm.bitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
  410. format_pcm.containerSize = format_pcm.bitsPerSample;
  411. format_pcm.channelMask = GetChannelMask(device->FmtChans);
  412. format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN :
  413. SL_BYTEORDER_BIGENDIAN;
  414. format_pcm.representation = GetTypeRepresentation(device->FmtType);
  415. #else
  416. SLDataFormat_PCM format_pcm;
  417. format_pcm.formatType = SL_DATAFORMAT_PCM;
  418. format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
  419. format_pcm.samplesPerSec = device->Frequency * 1000;
  420. format_pcm.bitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
  421. format_pcm.containerSize = format_pcm.bitsPerSample;
  422. format_pcm.channelMask = GetChannelMask(device->FmtChans);
  423. format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN :
  424. SL_BYTEORDER_BIGENDIAN;
  425. #endif
  426. audioSrc.pLocator = &loc_bufq;
  427. audioSrc.pFormat = &format_pcm;
  428. loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
  429. loc_outmix.outputMix = self->mOutputMix;
  430. audioSnk.pLocator = &loc_outmix;
  431. audioSnk.pFormat = NULL;
  432. ids[0] = SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
  433. reqs[0] = SL_BOOLEAN_TRUE;
  434. ids[1] = SL_IID_ANDROIDCONFIGURATION;
  435. reqs[1] = SL_BOOLEAN_FALSE;
  436. result = VCALL(self->mEngine,CreateAudioPlayer)(&self->mBufferQueueObj,
  437. &audioSrc, &audioSnk, COUNTOF(ids), ids, reqs
  438. );
  439. PRINTERR(result, "engine->CreateAudioPlayer");
  440. if(SL_RESULT_SUCCESS == result)
  441. {
  442. /* Set the stream type to "media" (games, music, etc), if possible. */
  443. SLAndroidConfigurationItf config;
  444. result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDCONFIGURATION, &config);
  445. PRINTERR(result, "bufferQueue->GetInterface SL_IID_ANDROIDCONFIGURATION");
  446. if(SL_RESULT_SUCCESS == result)
  447. {
  448. SLint32 streamType = SL_ANDROID_STREAM_MEDIA;
  449. result = VCALL(config,SetConfiguration)(SL_ANDROID_KEY_STREAM_TYPE,
  450. &streamType, sizeof(streamType)
  451. );
  452. PRINTERR(result, "config->SetConfiguration");
  453. }
  454. /* Clear any error since this was optional. */
  455. result = SL_RESULT_SUCCESS;
  456. }
  457. if(SL_RESULT_SUCCESS == result)
  458. {
  459. result = VCALL(self->mBufferQueueObj,Realize)(SL_BOOLEAN_FALSE);
  460. PRINTERR(result, "bufferQueue->Realize");
  461. }
  462. if(SL_RESULT_SUCCESS == result)
  463. {
  464. self->mRing = ll_ringbuffer_create(device->NumUpdates,
  465. self->mFrameSize*device->UpdateSize, true
  466. );
  467. if(!self->mRing)
  468. {
  469. ERR("Out of memory allocating ring buffer %ux%u %u\n", device->UpdateSize,
  470. device->NumUpdates, self->mFrameSize);
  471. result = SL_RESULT_MEMORY_FAILURE;
  472. }
  473. }
  474. if(SL_RESULT_SUCCESS != result)
  475. {
  476. if(self->mBufferQueueObj != NULL)
  477. VCALL0(self->mBufferQueueObj,Destroy)();
  478. self->mBufferQueueObj = NULL;
  479. return ALC_FALSE;
  480. }
  481. return ALC_TRUE;
  482. }
  483. static ALCboolean ALCopenslPlayback_start(ALCopenslPlayback *self)
  484. {
  485. SLAndroidSimpleBufferQueueItf bufferQueue;
  486. SLresult result;
  487. ll_ringbuffer_reset(self->mRing);
  488. result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
  489. &bufferQueue);
  490. PRINTERR(result, "bufferQueue->GetInterface");
  491. if(SL_RESULT_SUCCESS != result)
  492. return ALC_FALSE;
  493. result = VCALL(bufferQueue,RegisterCallback)(ALCopenslPlayback_process, self);
  494. PRINTERR(result, "bufferQueue->RegisterCallback");
  495. if(SL_RESULT_SUCCESS != result)
  496. return ALC_FALSE;
  497. ATOMIC_STORE_SEQ(&self->mKillNow, AL_FALSE);
  498. if(althrd_create(&self->mThread, ALCopenslPlayback_mixerProc, self) != althrd_success)
  499. {
  500. ERR("Failed to start mixer thread\n");
  501. return ALC_FALSE;
  502. }
  503. return ALC_TRUE;
  504. }
  505. static void ALCopenslPlayback_stop(ALCopenslPlayback *self)
  506. {
  507. SLAndroidSimpleBufferQueueItf bufferQueue;
  508. SLPlayItf player;
  509. SLresult result;
  510. int res;
  511. if(ATOMIC_EXCHANGE_SEQ(&self->mKillNow, AL_TRUE))
  512. return;
  513. alsem_post(&self->mSem);
  514. althrd_join(self->mThread, &res);
  515. result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player);
  516. PRINTERR(result, "bufferQueue->GetInterface");
  517. if(SL_RESULT_SUCCESS == result)
  518. {
  519. result = VCALL(player,SetPlayState)(SL_PLAYSTATE_STOPPED);
  520. PRINTERR(result, "player->SetPlayState");
  521. }
  522. result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
  523. &bufferQueue);
  524. PRINTERR(result, "bufferQueue->GetInterface");
  525. if(SL_RESULT_SUCCESS == result)
  526. {
  527. result = VCALL0(bufferQueue,Clear)();
  528. PRINTERR(result, "bufferQueue->Clear");
  529. }
  530. if(SL_RESULT_SUCCESS == result)
  531. {
  532. result = VCALL(bufferQueue,RegisterCallback)(NULL, NULL);
  533. PRINTERR(result, "bufferQueue->RegisterCallback");
  534. }
  535. if(SL_RESULT_SUCCESS == result)
  536. {
  537. SLAndroidSimpleBufferQueueState state;
  538. do {
  539. althrd_yield();
  540. result = VCALL(bufferQueue,GetState)(&state);
  541. } while(SL_RESULT_SUCCESS == result && state.count > 0);
  542. PRINTERR(result, "bufferQueue->GetState");
  543. }
  544. }
  545. static ClockLatency ALCopenslPlayback_getClockLatency(ALCopenslPlayback *self)
  546. {
  547. ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
  548. ClockLatency ret;
  549. ALCopenslPlayback_lock(self);
  550. ret.ClockTime = GetDeviceClockTime(device);
  551. ret.Latency = ll_ringbuffer_read_space(self->mRing)*device->UpdateSize *
  552. DEVICE_CLOCK_RES / device->Frequency;
  553. ALCopenslPlayback_unlock(self);
  554. return ret;
  555. }
  556. typedef struct ALCopenslCapture {
  557. DERIVE_FROM_TYPE(ALCbackend);
  558. /* engine interfaces */
  559. SLObjectItf mEngineObj;
  560. SLEngineItf mEngine;
  561. /* recording interfaces */
  562. SLObjectItf mRecordObj;
  563. ll_ringbuffer_t *mRing;
  564. ALCuint mSplOffset;
  565. ALsizei mFrameSize;
  566. } ALCopenslCapture;
  567. static void ALCopenslCapture_process(SLAndroidSimpleBufferQueueItf bq, void *context);
  568. static void ALCopenslCapture_Construct(ALCopenslCapture *self, ALCdevice *device);
  569. static void ALCopenslCapture_Destruct(ALCopenslCapture *self);
  570. static ALCenum ALCopenslCapture_open(ALCopenslCapture *self, const ALCchar *name);
  571. static DECLARE_FORWARD(ALCopenslCapture, ALCbackend, ALCboolean, reset)
  572. static ALCboolean ALCopenslCapture_start(ALCopenslCapture *self);
  573. static void ALCopenslCapture_stop(ALCopenslCapture *self);
  574. static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid *buffer, ALCuint samples);
  575. static ALCuint ALCopenslCapture_availableSamples(ALCopenslCapture *self);
  576. static DECLARE_FORWARD(ALCopenslCapture, ALCbackend, ClockLatency, getClockLatency)
  577. static DECLARE_FORWARD(ALCopenslCapture, ALCbackend, void, lock)
  578. static DECLARE_FORWARD(ALCopenslCapture, ALCbackend, void, unlock)
  579. DECLARE_DEFAULT_ALLOCATORS(ALCopenslCapture)
  580. DEFINE_ALCBACKEND_VTABLE(ALCopenslCapture);
  581. static void ALCopenslCapture_process(SLAndroidSimpleBufferQueueItf UNUSED(bq), void *context)
  582. {
  583. ALCopenslCapture *self = context;
  584. /* A new chunk has been written into the ring buffer, advance it. */
  585. ll_ringbuffer_write_advance(self->mRing, 1);
  586. }
  587. static void ALCopenslCapture_Construct(ALCopenslCapture *self, ALCdevice *device)
  588. {
  589. ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
  590. SET_VTABLE2(ALCopenslCapture, ALCbackend, self);
  591. self->mEngineObj = NULL;
  592. self->mEngine = NULL;
  593. self->mRecordObj = NULL;
  594. self->mRing = NULL;
  595. self->mSplOffset = 0;
  596. self->mFrameSize = 0;
  597. }
  598. static void ALCopenslCapture_Destruct(ALCopenslCapture *self)
  599. {
  600. if(self->mRecordObj != NULL)
  601. VCALL0(self->mRecordObj,Destroy)();
  602. self->mRecordObj = NULL;
  603. if(self->mEngineObj != NULL)
  604. VCALL0(self->mEngineObj,Destroy)();
  605. self->mEngineObj = NULL;
  606. self->mEngine = NULL;
  607. ll_ringbuffer_free(self->mRing);
  608. self->mRing = NULL;
  609. ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
  610. }
  611. static ALCenum ALCopenslCapture_open(ALCopenslCapture *self, const ALCchar *name)
  612. {
  613. ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
  614. SLDataLocator_AndroidSimpleBufferQueue loc_bq;
  615. SLAndroidSimpleBufferQueueItf bufferQueue;
  616. SLDataLocator_IODevice loc_dev;
  617. SLDataSource audioSrc;
  618. SLDataSink audioSnk;
  619. SLresult result;
  620. if(!name)
  621. name = opensl_device;
  622. else if(strcmp(name, opensl_device) != 0)
  623. return ALC_INVALID_VALUE;
  624. result = slCreateEngine(&self->mEngineObj, 0, NULL, 0, NULL, NULL);
  625. PRINTERR(result, "slCreateEngine");
  626. if(SL_RESULT_SUCCESS == result)
  627. {
  628. result = VCALL(self->mEngineObj,Realize)(SL_BOOLEAN_FALSE);
  629. PRINTERR(result, "engine->Realize");
  630. }
  631. if(SL_RESULT_SUCCESS == result)
  632. {
  633. result = VCALL(self->mEngineObj,GetInterface)(SL_IID_ENGINE, &self->mEngine);
  634. PRINTERR(result, "engine->GetInterface");
  635. }
  636. if(SL_RESULT_SUCCESS == result)
  637. {
  638. /* Ensure the total length is at least 100ms */
  639. ALsizei length = maxi(device->NumUpdates * device->UpdateSize,
  640. device->Frequency / 10);
  641. /* Ensure the per-chunk length is at least 10ms, and no more than 50ms. */
  642. ALsizei update_len = clampi(device->NumUpdates*device->UpdateSize / 3,
  643. device->Frequency / 100,
  644. device->Frequency / 100 * 5);
  645. device->UpdateSize = update_len;
  646. device->NumUpdates = (length+update_len-1) / update_len;
  647. self->mFrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
  648. }
  649. loc_dev.locatorType = SL_DATALOCATOR_IODEVICE;
  650. loc_dev.deviceType = SL_IODEVICE_AUDIOINPUT;
  651. loc_dev.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT;
  652. loc_dev.device = NULL;
  653. audioSrc.pLocator = &loc_dev;
  654. audioSrc.pFormat = NULL;
  655. loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
  656. loc_bq.numBuffers = device->NumUpdates;
  657. #ifdef SL_DATAFORMAT_PCM_EX
  658. SLDataFormat_PCM_EX format_pcm;
  659. format_pcm.formatType = SL_DATAFORMAT_PCM_EX;
  660. format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
  661. format_pcm.sampleRate = device->Frequency * 1000;
  662. format_pcm.bitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
  663. format_pcm.containerSize = format_pcm.bitsPerSample;
  664. format_pcm.channelMask = GetChannelMask(device->FmtChans);
  665. format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN :
  666. SL_BYTEORDER_BIGENDIAN;
  667. format_pcm.representation = GetTypeRepresentation(device->FmtType);
  668. #else
  669. SLDataFormat_PCM format_pcm;
  670. format_pcm.formatType = SL_DATAFORMAT_PCM;
  671. format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
  672. format_pcm.samplesPerSec = device->Frequency * 1000;
  673. format_pcm.bitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
  674. format_pcm.containerSize = format_pcm.bitsPerSample;
  675. format_pcm.channelMask = GetChannelMask(device->FmtChans);
  676. format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN :
  677. SL_BYTEORDER_BIGENDIAN;
  678. #endif
  679. audioSnk.pLocator = &loc_bq;
  680. audioSnk.pFormat = &format_pcm;
  681. if(SL_RESULT_SUCCESS == result)
  682. {
  683. const SLInterfaceID ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION };
  684. const SLboolean reqs[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE };
  685. result = VCALL(self->mEngine,CreateAudioRecorder)(&self->mRecordObj,
  686. &audioSrc, &audioSnk, COUNTOF(ids), ids, reqs
  687. );
  688. PRINTERR(result, "engine->CreateAudioRecorder");
  689. }
  690. if(SL_RESULT_SUCCESS == result)
  691. {
  692. /* Set the record preset to "generic", if possible. */
  693. SLAndroidConfigurationItf config;
  694. result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDCONFIGURATION, &config);
  695. PRINTERR(result, "recordObj->GetInterface SL_IID_ANDROIDCONFIGURATION");
  696. if(SL_RESULT_SUCCESS == result)
  697. {
  698. SLuint32 preset = SL_ANDROID_RECORDING_PRESET_GENERIC;
  699. result = VCALL(config,SetConfiguration)(SL_ANDROID_KEY_RECORDING_PRESET,
  700. &preset, sizeof(preset)
  701. );
  702. PRINTERR(result, "config->SetConfiguration");
  703. }
  704. /* Clear any error since this was optional. */
  705. result = SL_RESULT_SUCCESS;
  706. }
  707. if(SL_RESULT_SUCCESS == result)
  708. {
  709. result = VCALL(self->mRecordObj,Realize)(SL_BOOLEAN_FALSE);
  710. PRINTERR(result, "recordObj->Realize");
  711. }
  712. if(SL_RESULT_SUCCESS == result)
  713. {
  714. self->mRing = ll_ringbuffer_create(device->NumUpdates,
  715. device->UpdateSize*self->mFrameSize, false
  716. );
  717. result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
  718. &bufferQueue);
  719. PRINTERR(result, "recordObj->GetInterface");
  720. }
  721. if(SL_RESULT_SUCCESS == result)
  722. {
  723. result = VCALL(bufferQueue,RegisterCallback)(ALCopenslCapture_process, self);
  724. PRINTERR(result, "bufferQueue->RegisterCallback");
  725. }
  726. if(SL_RESULT_SUCCESS == result)
  727. {
  728. ALsizei chunk_size = device->UpdateSize * self->mFrameSize;
  729. ll_ringbuffer_data_t data[2];
  730. size_t i;
  731. ll_ringbuffer_get_write_vector(self->mRing, data);
  732. for(i = 0;i < data[0].len && SL_RESULT_SUCCESS == result;i++)
  733. {
  734. result = VCALL(bufferQueue,Enqueue)(data[0].buf + chunk_size*i, chunk_size);
  735. PRINTERR(result, "bufferQueue->Enqueue");
  736. }
  737. for(i = 0;i < data[1].len && SL_RESULT_SUCCESS == result;i++)
  738. {
  739. result = VCALL(bufferQueue,Enqueue)(data[1].buf + chunk_size*i, chunk_size);
  740. PRINTERR(result, "bufferQueue->Enqueue");
  741. }
  742. }
  743. if(SL_RESULT_SUCCESS != result)
  744. {
  745. if(self->mRecordObj != NULL)
  746. VCALL0(self->mRecordObj,Destroy)();
  747. self->mRecordObj = NULL;
  748. if(self->mEngineObj != NULL)
  749. VCALL0(self->mEngineObj,Destroy)();
  750. self->mEngineObj = NULL;
  751. self->mEngine = NULL;
  752. return ALC_INVALID_VALUE;
  753. }
  754. alstr_copy_cstr(&device->DeviceName, name);
  755. return ALC_NO_ERROR;
  756. }
  757. static ALCboolean ALCopenslCapture_start(ALCopenslCapture *self)
  758. {
  759. SLRecordItf record;
  760. SLresult result;
  761. result = VCALL(self->mRecordObj,GetInterface)(SL_IID_RECORD, &record);
  762. PRINTERR(result, "recordObj->GetInterface");
  763. if(SL_RESULT_SUCCESS == result)
  764. {
  765. result = VCALL(record,SetRecordState)(SL_RECORDSTATE_RECORDING);
  766. PRINTERR(result, "record->SetRecordState");
  767. }
  768. if(SL_RESULT_SUCCESS != result)
  769. {
  770. ALCopenslCapture_lock(self);
  771. aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice,
  772. "Failed to start capture: 0x%08x", result);
  773. ALCopenslCapture_unlock(self);
  774. return ALC_FALSE;
  775. }
  776. return ALC_TRUE;
  777. }
  778. static void ALCopenslCapture_stop(ALCopenslCapture *self)
  779. {
  780. SLRecordItf record;
  781. SLresult result;
  782. result = VCALL(self->mRecordObj,GetInterface)(SL_IID_RECORD, &record);
  783. PRINTERR(result, "recordObj->GetInterface");
  784. if(SL_RESULT_SUCCESS == result)
  785. {
  786. result = VCALL(record,SetRecordState)(SL_RECORDSTATE_PAUSED);
  787. PRINTERR(result, "record->SetRecordState");
  788. }
  789. }
  790. static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid *buffer, ALCuint samples)
  791. {
  792. ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
  793. ALsizei chunk_size = device->UpdateSize * self->mFrameSize;
  794. SLAndroidSimpleBufferQueueItf bufferQueue;
  795. ll_ringbuffer_data_t data[2];
  796. SLresult result;
  797. ALCuint i;
  798. result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
  799. &bufferQueue);
  800. PRINTERR(result, "recordObj->GetInterface");
  801. /* Read the desired samples from the ring buffer then advance its read
  802. * pointer.
  803. */
  804. ll_ringbuffer_get_read_vector(self->mRing, data);
  805. for(i = 0;i < samples;)
  806. {
  807. ALCuint rem = minu(samples - i, device->UpdateSize - self->mSplOffset);
  808. memcpy((ALCbyte*)buffer + i*self->mFrameSize,
  809. data[0].buf + self->mSplOffset*self->mFrameSize,
  810. rem * self->mFrameSize);
  811. self->mSplOffset += rem;
  812. if(self->mSplOffset == device->UpdateSize)
  813. {
  814. /* Finished a chunk, reset the offset and advance the read pointer. */
  815. self->mSplOffset = 0;
  816. ll_ringbuffer_read_advance(self->mRing, 1);
  817. result = VCALL(bufferQueue,Enqueue)(data[0].buf, chunk_size);
  818. PRINTERR(result, "bufferQueue->Enqueue");
  819. if(SL_RESULT_SUCCESS != result) break;
  820. data[0].len--;
  821. if(!data[0].len)
  822. data[0] = data[1];
  823. else
  824. data[0].buf += chunk_size;
  825. }
  826. i += rem;
  827. }
  828. if(SL_RESULT_SUCCESS != result)
  829. {
  830. ALCopenslCapture_lock(self);
  831. aluHandleDisconnect(device, "Failed to update capture buffer: 0x%08x", result);
  832. ALCopenslCapture_unlock(self);
  833. return ALC_INVALID_DEVICE;
  834. }
  835. return ALC_NO_ERROR;
  836. }
  837. static ALCuint ALCopenslCapture_availableSamples(ALCopenslCapture *self)
  838. {
  839. ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
  840. return ll_ringbuffer_read_space(self->mRing) * device->UpdateSize;
  841. }
  842. typedef struct ALCopenslBackendFactory {
  843. DERIVE_FROM_TYPE(ALCbackendFactory);
  844. } ALCopenslBackendFactory;
  845. #define ALCOPENSLBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCopenslBackendFactory, ALCbackendFactory) } }
  846. static ALCboolean ALCopenslBackendFactory_init(ALCopenslBackendFactory* UNUSED(self))
  847. {
  848. return ALC_TRUE;
  849. }
  850. static void ALCopenslBackendFactory_deinit(ALCopenslBackendFactory* UNUSED(self))
  851. {
  852. }
  853. static ALCboolean ALCopenslBackendFactory_querySupport(ALCopenslBackendFactory* UNUSED(self), ALCbackend_Type type)
  854. {
  855. if(type == ALCbackend_Playback || type == ALCbackend_Capture)
  856. return ALC_TRUE;
  857. return ALC_FALSE;
  858. }
  859. static void ALCopenslBackendFactory_probe(ALCopenslBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames)
  860. {
  861. switch(type)
  862. {
  863. case ALL_DEVICE_PROBE:
  864. case CAPTURE_DEVICE_PROBE:
  865. alstr_append_range(outnames, opensl_device, opensl_device+sizeof(opensl_device));
  866. break;
  867. }
  868. }
  869. static ALCbackend* ALCopenslBackendFactory_createBackend(ALCopenslBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
  870. {
  871. if(type == ALCbackend_Playback)
  872. {
  873. ALCopenslPlayback *backend;
  874. NEW_OBJ(backend, ALCopenslPlayback)(device);
  875. if(!backend) return NULL;
  876. return STATIC_CAST(ALCbackend, backend);
  877. }
  878. if(type == ALCbackend_Capture)
  879. {
  880. ALCopenslCapture *backend;
  881. NEW_OBJ(backend, ALCopenslCapture)(device);
  882. if(!backend) return NULL;
  883. return STATIC_CAST(ALCbackend, backend);
  884. }
  885. return NULL;
  886. }
  887. DEFINE_ALCBACKENDFACTORY_VTABLE(ALCopenslBackendFactory);
  888. ALCbackendFactory *ALCopenslBackendFactory_getFactory(void)
  889. {
  890. static ALCopenslBackendFactory factory = ALCOPENSLBACKENDFACTORY_INITIALIZER;
  891. return STATIC_CAST(ALCbackendFactory, &factory);
  892. }