alsa.c 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298
  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., 59 Temple Place - Suite 330,
  17. * Boston, MA 02111-1307, USA.
  18. * Or go to http://www.gnu.org/copyleft/lgpl.html
  19. */
  20. #include "config.h"
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <memory.h>
  24. #include "alMain.h"
  25. #include <alsa/asoundlib.h>
  26. static const ALCchar alsaDevice[] = "ALSA Default";
  27. #ifdef HAVE_DYNLOAD
  28. static void *alsa_handle;
  29. #define MAKE_FUNC(f) static typeof(f) * p##f
  30. MAKE_FUNC(snd_strerror);
  31. MAKE_FUNC(snd_pcm_open);
  32. MAKE_FUNC(snd_pcm_close);
  33. MAKE_FUNC(snd_pcm_nonblock);
  34. MAKE_FUNC(snd_pcm_frames_to_bytes);
  35. MAKE_FUNC(snd_pcm_bytes_to_frames);
  36. MAKE_FUNC(snd_pcm_hw_params_malloc);
  37. MAKE_FUNC(snd_pcm_hw_params_free);
  38. MAKE_FUNC(snd_pcm_hw_params_any);
  39. MAKE_FUNC(snd_pcm_hw_params_current);
  40. MAKE_FUNC(snd_pcm_hw_params_set_access);
  41. MAKE_FUNC(snd_pcm_hw_params_set_format);
  42. MAKE_FUNC(snd_pcm_hw_params_set_channels);
  43. MAKE_FUNC(snd_pcm_hw_params_set_periods_near);
  44. MAKE_FUNC(snd_pcm_hw_params_set_rate_near);
  45. MAKE_FUNC(snd_pcm_hw_params_set_rate);
  46. MAKE_FUNC(snd_pcm_hw_params_set_rate_resample);
  47. MAKE_FUNC(snd_pcm_hw_params_set_buffer_time_near);
  48. MAKE_FUNC(snd_pcm_hw_params_set_period_time_near);
  49. MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_near);
  50. MAKE_FUNC(snd_pcm_hw_params_set_period_size_near);
  51. MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_min);
  52. MAKE_FUNC(snd_pcm_hw_params_get_buffer_size);
  53. MAKE_FUNC(snd_pcm_hw_params_get_period_size);
  54. MAKE_FUNC(snd_pcm_hw_params_get_access);
  55. MAKE_FUNC(snd_pcm_hw_params_get_periods);
  56. MAKE_FUNC(snd_pcm_hw_params_test_format);
  57. MAKE_FUNC(snd_pcm_hw_params_test_channels);
  58. MAKE_FUNC(snd_pcm_hw_params);
  59. MAKE_FUNC(snd_pcm_sw_params_malloc);
  60. MAKE_FUNC(snd_pcm_sw_params_current);
  61. MAKE_FUNC(snd_pcm_sw_params_set_avail_min);
  62. MAKE_FUNC(snd_pcm_sw_params_set_stop_threshold);
  63. MAKE_FUNC(snd_pcm_sw_params);
  64. MAKE_FUNC(snd_pcm_sw_params_free);
  65. MAKE_FUNC(snd_pcm_prepare);
  66. MAKE_FUNC(snd_pcm_start);
  67. MAKE_FUNC(snd_pcm_resume);
  68. MAKE_FUNC(snd_pcm_reset);
  69. MAKE_FUNC(snd_pcm_wait);
  70. MAKE_FUNC(snd_pcm_state);
  71. MAKE_FUNC(snd_pcm_avail_update);
  72. MAKE_FUNC(snd_pcm_areas_silence);
  73. MAKE_FUNC(snd_pcm_mmap_begin);
  74. MAKE_FUNC(snd_pcm_mmap_commit);
  75. MAKE_FUNC(snd_pcm_readi);
  76. MAKE_FUNC(snd_pcm_writei);
  77. MAKE_FUNC(snd_pcm_drain);
  78. MAKE_FUNC(snd_pcm_drop);
  79. MAKE_FUNC(snd_pcm_recover);
  80. MAKE_FUNC(snd_pcm_info_malloc);
  81. MAKE_FUNC(snd_pcm_info_free);
  82. MAKE_FUNC(snd_pcm_info_set_device);
  83. MAKE_FUNC(snd_pcm_info_set_subdevice);
  84. MAKE_FUNC(snd_pcm_info_set_stream);
  85. MAKE_FUNC(snd_pcm_info_get_name);
  86. MAKE_FUNC(snd_ctl_pcm_next_device);
  87. MAKE_FUNC(snd_ctl_pcm_info);
  88. MAKE_FUNC(snd_ctl_open);
  89. MAKE_FUNC(snd_ctl_close);
  90. MAKE_FUNC(snd_ctl_card_info_malloc);
  91. MAKE_FUNC(snd_ctl_card_info_free);
  92. MAKE_FUNC(snd_ctl_card_info);
  93. MAKE_FUNC(snd_ctl_card_info_get_name);
  94. MAKE_FUNC(snd_ctl_card_info_get_id);
  95. MAKE_FUNC(snd_card_next);
  96. #undef MAKE_FUNC
  97. #define snd_strerror psnd_strerror
  98. #define snd_pcm_open psnd_pcm_open
  99. #define snd_pcm_close psnd_pcm_close
  100. #define snd_pcm_nonblock psnd_pcm_nonblock
  101. #define snd_pcm_frames_to_bytes psnd_pcm_frames_to_bytes
  102. #define snd_pcm_bytes_to_frames psnd_pcm_bytes_to_frames
  103. #define snd_pcm_hw_params_malloc psnd_pcm_hw_params_malloc
  104. #define snd_pcm_hw_params_free psnd_pcm_hw_params_free
  105. #define snd_pcm_hw_params_any psnd_pcm_hw_params_any
  106. #define snd_pcm_hw_params_current psnd_pcm_hw_params_current
  107. #define snd_pcm_hw_params_set_access psnd_pcm_hw_params_set_access
  108. #define snd_pcm_hw_params_set_format psnd_pcm_hw_params_set_format
  109. #define snd_pcm_hw_params_set_channels psnd_pcm_hw_params_set_channels
  110. #define snd_pcm_hw_params_set_periods_near psnd_pcm_hw_params_set_periods_near
  111. #define snd_pcm_hw_params_set_rate_near psnd_pcm_hw_params_set_rate_near
  112. #define snd_pcm_hw_params_set_rate psnd_pcm_hw_params_set_rate
  113. #define snd_pcm_hw_params_set_rate_resample psnd_pcm_hw_params_set_rate_resample
  114. #define snd_pcm_hw_params_set_buffer_time_near psnd_pcm_hw_params_set_buffer_time_near
  115. #define snd_pcm_hw_params_set_period_time_near psnd_pcm_hw_params_set_period_time_near
  116. #define snd_pcm_hw_params_set_buffer_size_near psnd_pcm_hw_params_set_buffer_size_near
  117. #define snd_pcm_hw_params_set_period_size_near psnd_pcm_hw_params_set_period_size_near
  118. #define snd_pcm_hw_params_set_buffer_size_min psnd_pcm_hw_params_set_buffer_size_min
  119. #define snd_pcm_hw_params_get_buffer_size psnd_pcm_hw_params_get_buffer_size
  120. #define snd_pcm_hw_params_get_period_size psnd_pcm_hw_params_get_period_size
  121. #define snd_pcm_hw_params_get_access psnd_pcm_hw_params_get_access
  122. #define snd_pcm_hw_params_get_periods psnd_pcm_hw_params_get_periods
  123. #define snd_pcm_hw_params_test_format psnd_pcm_hw_params_test_format
  124. #define snd_pcm_hw_params_test_channels psnd_pcm_hw_params_test_channels
  125. #define snd_pcm_hw_params psnd_pcm_hw_params
  126. #define snd_pcm_sw_params_malloc psnd_pcm_sw_params_malloc
  127. #define snd_pcm_sw_params_current psnd_pcm_sw_params_current
  128. #define snd_pcm_sw_params_set_avail_min psnd_pcm_sw_params_set_avail_min
  129. #define snd_pcm_sw_params_set_stop_threshold psnd_pcm_sw_params_set_stop_threshold
  130. #define snd_pcm_sw_params psnd_pcm_sw_params
  131. #define snd_pcm_sw_params_free psnd_pcm_sw_params_free
  132. #define snd_pcm_prepare psnd_pcm_prepare
  133. #define snd_pcm_start psnd_pcm_start
  134. #define snd_pcm_resume psnd_pcm_resume
  135. #define snd_pcm_reset psnd_pcm_reset
  136. #define snd_pcm_wait psnd_pcm_wait
  137. #define snd_pcm_state psnd_pcm_state
  138. #define snd_pcm_avail_update psnd_pcm_avail_update
  139. #define snd_pcm_areas_silence psnd_pcm_areas_silence
  140. #define snd_pcm_mmap_begin psnd_pcm_mmap_begin
  141. #define snd_pcm_mmap_commit psnd_pcm_mmap_commit
  142. #define snd_pcm_readi psnd_pcm_readi
  143. #define snd_pcm_writei psnd_pcm_writei
  144. #define snd_pcm_drain psnd_pcm_drain
  145. #define snd_pcm_drop psnd_pcm_drop
  146. #define snd_pcm_recover psnd_pcm_recover
  147. #define snd_pcm_info_malloc psnd_pcm_info_malloc
  148. #define snd_pcm_info_free psnd_pcm_info_free
  149. #define snd_pcm_info_set_device psnd_pcm_info_set_device
  150. #define snd_pcm_info_set_subdevice psnd_pcm_info_set_subdevice
  151. #define snd_pcm_info_set_stream psnd_pcm_info_set_stream
  152. #define snd_pcm_info_get_name psnd_pcm_info_get_name
  153. #define snd_ctl_pcm_next_device psnd_ctl_pcm_next_device
  154. #define snd_ctl_pcm_info psnd_ctl_pcm_info
  155. #define snd_ctl_open psnd_ctl_open
  156. #define snd_ctl_close psnd_ctl_close
  157. #define snd_ctl_card_info_malloc psnd_ctl_card_info_malloc
  158. #define snd_ctl_card_info_free psnd_ctl_card_info_free
  159. #define snd_ctl_card_info psnd_ctl_card_info
  160. #define snd_ctl_card_info_get_name psnd_ctl_card_info_get_name
  161. #define snd_ctl_card_info_get_id psnd_ctl_card_info_get_id
  162. #define snd_card_next psnd_card_next
  163. #endif
  164. static ALCboolean alsa_load(void)
  165. {
  166. #ifdef HAVE_DYNLOAD
  167. if(!alsa_handle)
  168. {
  169. alsa_handle = LoadLib("libasound.so.2");
  170. if(!alsa_handle)
  171. return ALC_FALSE;
  172. #define LOAD_FUNC(f) do { \
  173. p##f = GetSymbol(alsa_handle, #f); \
  174. if(p##f == NULL) { \
  175. CloseLib(alsa_handle); \
  176. alsa_handle = NULL; \
  177. return ALC_FALSE; \
  178. } \
  179. } while(0)
  180. LOAD_FUNC(snd_strerror);
  181. LOAD_FUNC(snd_pcm_open);
  182. LOAD_FUNC(snd_pcm_close);
  183. LOAD_FUNC(snd_pcm_nonblock);
  184. LOAD_FUNC(snd_pcm_frames_to_bytes);
  185. LOAD_FUNC(snd_pcm_bytes_to_frames);
  186. LOAD_FUNC(snd_pcm_hw_params_malloc);
  187. LOAD_FUNC(snd_pcm_hw_params_free);
  188. LOAD_FUNC(snd_pcm_hw_params_any);
  189. LOAD_FUNC(snd_pcm_hw_params_current);
  190. LOAD_FUNC(snd_pcm_hw_params_set_access);
  191. LOAD_FUNC(snd_pcm_hw_params_set_format);
  192. LOAD_FUNC(snd_pcm_hw_params_set_channels);
  193. LOAD_FUNC(snd_pcm_hw_params_set_periods_near);
  194. LOAD_FUNC(snd_pcm_hw_params_set_rate_near);
  195. LOAD_FUNC(snd_pcm_hw_params_set_rate);
  196. LOAD_FUNC(snd_pcm_hw_params_set_rate_resample);
  197. LOAD_FUNC(snd_pcm_hw_params_set_buffer_time_near);
  198. LOAD_FUNC(snd_pcm_hw_params_set_period_time_near);
  199. LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_near);
  200. LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_min);
  201. LOAD_FUNC(snd_pcm_hw_params_set_period_size_near);
  202. LOAD_FUNC(snd_pcm_hw_params_get_buffer_size);
  203. LOAD_FUNC(snd_pcm_hw_params_get_period_size);
  204. LOAD_FUNC(snd_pcm_hw_params_get_access);
  205. LOAD_FUNC(snd_pcm_hw_params_get_periods);
  206. LOAD_FUNC(snd_pcm_hw_params_test_format);
  207. LOAD_FUNC(snd_pcm_hw_params_test_channels);
  208. LOAD_FUNC(snd_pcm_hw_params);
  209. LOAD_FUNC(snd_pcm_sw_params_malloc);
  210. LOAD_FUNC(snd_pcm_sw_params_current);
  211. LOAD_FUNC(snd_pcm_sw_params_set_avail_min);
  212. LOAD_FUNC(snd_pcm_sw_params_set_stop_threshold);
  213. LOAD_FUNC(snd_pcm_sw_params);
  214. LOAD_FUNC(snd_pcm_sw_params_free);
  215. LOAD_FUNC(snd_pcm_prepare);
  216. LOAD_FUNC(snd_pcm_start);
  217. LOAD_FUNC(snd_pcm_resume);
  218. LOAD_FUNC(snd_pcm_reset);
  219. LOAD_FUNC(snd_pcm_wait);
  220. LOAD_FUNC(snd_pcm_state);
  221. LOAD_FUNC(snd_pcm_avail_update);
  222. LOAD_FUNC(snd_pcm_areas_silence);
  223. LOAD_FUNC(snd_pcm_mmap_begin);
  224. LOAD_FUNC(snd_pcm_mmap_commit);
  225. LOAD_FUNC(snd_pcm_readi);
  226. LOAD_FUNC(snd_pcm_writei);
  227. LOAD_FUNC(snd_pcm_drain);
  228. LOAD_FUNC(snd_pcm_drop);
  229. LOAD_FUNC(snd_pcm_recover);
  230. LOAD_FUNC(snd_pcm_info_malloc);
  231. LOAD_FUNC(snd_pcm_info_free);
  232. LOAD_FUNC(snd_pcm_info_set_device);
  233. LOAD_FUNC(snd_pcm_info_set_subdevice);
  234. LOAD_FUNC(snd_pcm_info_set_stream);
  235. LOAD_FUNC(snd_pcm_info_get_name);
  236. LOAD_FUNC(snd_ctl_pcm_next_device);
  237. LOAD_FUNC(snd_ctl_pcm_info);
  238. LOAD_FUNC(snd_ctl_open);
  239. LOAD_FUNC(snd_ctl_close);
  240. LOAD_FUNC(snd_ctl_card_info_malloc);
  241. LOAD_FUNC(snd_ctl_card_info_free);
  242. LOAD_FUNC(snd_ctl_card_info);
  243. LOAD_FUNC(snd_ctl_card_info_get_name);
  244. LOAD_FUNC(snd_ctl_card_info_get_id);
  245. LOAD_FUNC(snd_card_next);
  246. #undef LOAD_FUNC
  247. }
  248. #endif
  249. return ALC_TRUE;
  250. }
  251. typedef struct {
  252. snd_pcm_t *pcmHandle;
  253. ALvoid *buffer;
  254. ALsizei size;
  255. ALboolean doCapture;
  256. RingBuffer *ring;
  257. snd_pcm_sframes_t last_avail;
  258. volatile int killNow;
  259. ALvoid *thread;
  260. } alsa_data;
  261. typedef struct {
  262. ALCchar *name;
  263. char *device;
  264. } DevMap;
  265. static DevMap *allDevNameMap;
  266. static ALuint numDevNames;
  267. static DevMap *allCaptureDevNameMap;
  268. static ALuint numCaptureDevNames;
  269. static const char *prefix_name(snd_pcm_stream_t stream)
  270. {
  271. assert(stream == SND_PCM_STREAM_PLAYBACK || stream == SND_PCM_STREAM_CAPTURE);
  272. return (stream==SND_PCM_STREAM_PLAYBACK) ? "device-prefix" : "capture-prefix";
  273. }
  274. static DevMap *probe_devices(snd_pcm_stream_t stream, ALuint *count)
  275. {
  276. const char *main_prefix = "plughw:";
  277. snd_ctl_t *handle;
  278. int card, err, dev, idx;
  279. snd_ctl_card_info_t *info;
  280. snd_pcm_info_t *pcminfo;
  281. DevMap *DevList;
  282. snd_ctl_card_info_malloc(&info);
  283. snd_pcm_info_malloc(&pcminfo);
  284. DevList = malloc(sizeof(DevMap) * 1);
  285. DevList[0].name = strdup(alsaDevice);
  286. DevList[0].device = strdup(GetConfigValue("alsa", (stream==SND_PCM_STREAM_PLAYBACK) ?
  287. "device" : "capture", "default"));
  288. idx = 1;
  289. card = -1;
  290. if((err=snd_card_next(&card)) < 0)
  291. ERR("Failed to find a card: %s\n", snd_strerror(err));
  292. ConfigValueStr("alsa", prefix_name(stream), &main_prefix);
  293. while(card >= 0)
  294. {
  295. const char *card_prefix = main_prefix;
  296. const char *cardname, *cardid;
  297. char name[256];
  298. snprintf(name, sizeof(name), "hw:%d", card);
  299. if((err = snd_ctl_open(&handle, name, 0)) < 0)
  300. {
  301. ERR("control open (hw:%d): %s\n", card, snd_strerror(err));
  302. goto next_card;
  303. }
  304. if((err = snd_ctl_card_info(handle, info)) < 0)
  305. {
  306. ERR("control hardware info (hw:%d): %s\n", card, snd_strerror(err));
  307. snd_ctl_close(handle);
  308. goto next_card;
  309. }
  310. cardname = snd_ctl_card_info_get_name(info);
  311. cardid = snd_ctl_card_info_get_id(info);
  312. snprintf(name, sizeof(name), "%s-%s", prefix_name(stream), cardid);
  313. ConfigValueStr("alsa", name, &card_prefix);
  314. dev = -1;
  315. while(1)
  316. {
  317. const char *devname;
  318. void *temp;
  319. if(snd_ctl_pcm_next_device(handle, &dev) < 0)
  320. ERR("snd_ctl_pcm_next_device failed\n");
  321. if(dev < 0)
  322. break;
  323. snd_pcm_info_set_device(pcminfo, dev);
  324. snd_pcm_info_set_subdevice(pcminfo, 0);
  325. snd_pcm_info_set_stream(pcminfo, stream);
  326. if((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
  327. if(err != -ENOENT)
  328. ERR("control digital audio info (hw:%d): %s\n", card, snd_strerror(err));
  329. continue;
  330. }
  331. temp = realloc(DevList, sizeof(DevMap) * (idx+1));
  332. if(temp)
  333. {
  334. const char *device_prefix = card_prefix;
  335. char device[128];
  336. DevList = temp;
  337. devname = snd_pcm_info_get_name(pcminfo);
  338. snprintf(name, sizeof(name), "%s-%s-%d", prefix_name(stream), cardid, dev);
  339. ConfigValueStr("alsa", name, &device_prefix);
  340. snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)",
  341. cardname, devname, cardid, dev);
  342. snprintf(device, sizeof(device), "%sCARD=%s,DEV=%d",
  343. device_prefix, cardid, dev);
  344. TRACE("Got device \"%s\", \"%s\"\n", name, device);
  345. DevList[idx].name = strdup(name);
  346. DevList[idx].device = strdup(device);
  347. idx++;
  348. }
  349. }
  350. snd_ctl_close(handle);
  351. next_card:
  352. if(snd_card_next(&card) < 0) {
  353. ERR("snd_card_next failed\n");
  354. break;
  355. }
  356. }
  357. snd_pcm_info_free(pcminfo);
  358. snd_ctl_card_info_free(info);
  359. *count = idx;
  360. return DevList;
  361. }
  362. static int verify_state(snd_pcm_t *handle)
  363. {
  364. snd_pcm_state_t state = snd_pcm_state(handle);
  365. int err;
  366. switch(state)
  367. {
  368. case SND_PCM_STATE_OPEN:
  369. case SND_PCM_STATE_SETUP:
  370. case SND_PCM_STATE_PREPARED:
  371. case SND_PCM_STATE_RUNNING:
  372. case SND_PCM_STATE_DRAINING:
  373. case SND_PCM_STATE_PAUSED:
  374. /* All Okay */
  375. break;
  376. case SND_PCM_STATE_XRUN:
  377. if((err=snd_pcm_recover(handle, -EPIPE, 1)) < 0)
  378. return err;
  379. break;
  380. case SND_PCM_STATE_SUSPENDED:
  381. if((err=snd_pcm_recover(handle, -ESTRPIPE, 1)) < 0)
  382. return err;
  383. break;
  384. case SND_PCM_STATE_DISCONNECTED:
  385. return -ENODEV;
  386. }
  387. return state;
  388. }
  389. static ALuint ALSAProc(ALvoid *ptr)
  390. {
  391. ALCdevice *pDevice = (ALCdevice*)ptr;
  392. alsa_data *data = (alsa_data*)pDevice->ExtraData;
  393. const snd_pcm_channel_area_t *areas = NULL;
  394. snd_pcm_uframes_t update_size, num_updates;
  395. snd_pcm_sframes_t avail, commitres;
  396. snd_pcm_uframes_t offset, frames;
  397. char *WritePtr;
  398. int err;
  399. SetRTPriority();
  400. update_size = pDevice->UpdateSize;
  401. num_updates = pDevice->NumUpdates;
  402. while(!data->killNow)
  403. {
  404. int state = verify_state(data->pcmHandle);
  405. if(state < 0)
  406. {
  407. ERR("Invalid state detected: %s\n", snd_strerror(state));
  408. aluHandleDisconnect(pDevice);
  409. break;
  410. }
  411. avail = snd_pcm_avail_update(data->pcmHandle);
  412. if(avail < 0)
  413. {
  414. ERR("available update failed: %s\n", snd_strerror(avail));
  415. continue;
  416. }
  417. if((snd_pcm_uframes_t)avail > update_size*(num_updates+1))
  418. {
  419. WARN("available samples exceeds the buffer size\n");
  420. snd_pcm_reset(data->pcmHandle);
  421. continue;
  422. }
  423. // make sure there's frames to process
  424. if((snd_pcm_uframes_t)avail < update_size)
  425. {
  426. if(state != SND_PCM_STATE_RUNNING)
  427. {
  428. err = snd_pcm_start(data->pcmHandle);
  429. if(err < 0)
  430. {
  431. ERR("start failed: %s\n", snd_strerror(err));
  432. continue;
  433. }
  434. }
  435. if(snd_pcm_wait(data->pcmHandle, 1000) == 0)
  436. ERR("Wait timeout... buffer size too low?\n");
  437. continue;
  438. }
  439. avail -= avail%update_size;
  440. // it is possible that contiguous areas are smaller, thus we use a loop
  441. while(avail > 0)
  442. {
  443. frames = avail;
  444. err = snd_pcm_mmap_begin(data->pcmHandle, &areas, &offset, &frames);
  445. if(err < 0)
  446. {
  447. ERR("mmap begin error: %s\n", snd_strerror(err));
  448. break;
  449. }
  450. WritePtr = (char*)areas->addr + (offset * areas->step / 8);
  451. aluMixData(pDevice, WritePtr, frames);
  452. commitres = snd_pcm_mmap_commit(data->pcmHandle, offset, frames);
  453. if(commitres < 0 || (commitres-frames) != 0)
  454. {
  455. ERR("mmap commit error: %s\n",
  456. snd_strerror(commitres >= 0 ? -EPIPE : commitres));
  457. break;
  458. }
  459. avail -= frames;
  460. }
  461. }
  462. return 0;
  463. }
  464. static ALuint ALSANoMMapProc(ALvoid *ptr)
  465. {
  466. ALCdevice *pDevice = (ALCdevice*)ptr;
  467. alsa_data *data = (alsa_data*)pDevice->ExtraData;
  468. snd_pcm_sframes_t avail;
  469. char *WritePtr;
  470. SetRTPriority();
  471. while(!data->killNow)
  472. {
  473. int state = verify_state(data->pcmHandle);
  474. if(state < 0)
  475. {
  476. ERR("Invalid state detected: %s\n", snd_strerror(state));
  477. aluHandleDisconnect(pDevice);
  478. break;
  479. }
  480. WritePtr = data->buffer;
  481. avail = data->size / snd_pcm_frames_to_bytes(data->pcmHandle, 1);
  482. aluMixData(pDevice, WritePtr, avail);
  483. while(avail > 0)
  484. {
  485. int ret = snd_pcm_writei(data->pcmHandle, WritePtr, avail);
  486. switch (ret)
  487. {
  488. case -EAGAIN:
  489. continue;
  490. case -ESTRPIPE:
  491. case -EPIPE:
  492. case -EINTR:
  493. ret = snd_pcm_recover(data->pcmHandle, ret, 1);
  494. if(ret < 0)
  495. avail = 0;
  496. break;
  497. default:
  498. if (ret >= 0)
  499. {
  500. WritePtr += snd_pcm_frames_to_bytes(data->pcmHandle, ret);
  501. avail -= ret;
  502. }
  503. break;
  504. }
  505. if (ret < 0)
  506. {
  507. ret = snd_pcm_prepare(data->pcmHandle);
  508. if(ret < 0)
  509. break;
  510. }
  511. }
  512. }
  513. return 0;
  514. }
  515. static ALCenum alsa_open_playback(ALCdevice *device, const ALCchar *deviceName)
  516. {
  517. const char *driver = NULL;
  518. alsa_data *data;
  519. int err;
  520. if(deviceName)
  521. {
  522. size_t idx;
  523. if(!allDevNameMap)
  524. allDevNameMap = probe_devices(SND_PCM_STREAM_PLAYBACK, &numDevNames);
  525. for(idx = 0;idx < numDevNames;idx++)
  526. {
  527. if(strcmp(deviceName, allDevNameMap[idx].name) == 0)
  528. {
  529. driver = allDevNameMap[idx].device;
  530. break;
  531. }
  532. }
  533. if(idx == numDevNames)
  534. return ALC_INVALID_VALUE;
  535. }
  536. else
  537. {
  538. deviceName = alsaDevice;
  539. driver = GetConfigValue("alsa", "device", "default");
  540. }
  541. data = (alsa_data*)calloc(1, sizeof(alsa_data));
  542. err = snd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
  543. if(err >= 0)
  544. {
  545. err = snd_pcm_nonblock(data->pcmHandle, 0);
  546. if(err < 0) snd_pcm_close(data->pcmHandle);
  547. }
  548. if(err < 0)
  549. {
  550. free(data);
  551. ERR("Could not open playback device '%s': %s\n", driver, snd_strerror(err));
  552. return ALC_OUT_OF_MEMORY;
  553. }
  554. device->szDeviceName = strdup(deviceName);
  555. device->ExtraData = data;
  556. return ALC_NO_ERROR;
  557. }
  558. static void alsa_close_playback(ALCdevice *device)
  559. {
  560. alsa_data *data = (alsa_data*)device->ExtraData;
  561. snd_pcm_close(data->pcmHandle);
  562. free(data);
  563. device->ExtraData = NULL;
  564. }
  565. static ALCboolean alsa_reset_playback(ALCdevice *device)
  566. {
  567. alsa_data *data = (alsa_data*)device->ExtraData;
  568. snd_pcm_uframes_t periodSizeInFrames;
  569. unsigned int periodLen, bufferLen;
  570. snd_pcm_sw_params_t *sp = NULL;
  571. snd_pcm_hw_params_t *hp = NULL;
  572. snd_pcm_access_t access;
  573. snd_pcm_format_t format;
  574. unsigned int periods;
  575. unsigned int rate;
  576. const char *funcerr;
  577. int allowmmap;
  578. int err;
  579. format = -1;
  580. switch(device->FmtType)
  581. {
  582. case DevFmtByte:
  583. format = SND_PCM_FORMAT_S8;
  584. break;
  585. case DevFmtUByte:
  586. format = SND_PCM_FORMAT_U8;
  587. break;
  588. case DevFmtShort:
  589. format = SND_PCM_FORMAT_S16;
  590. break;
  591. case DevFmtUShort:
  592. format = SND_PCM_FORMAT_U16;
  593. break;
  594. case DevFmtInt:
  595. format = SND_PCM_FORMAT_S32;
  596. break;
  597. case DevFmtUInt:
  598. format = SND_PCM_FORMAT_U32;
  599. break;
  600. case DevFmtFloat:
  601. format = SND_PCM_FORMAT_FLOAT;
  602. break;
  603. }
  604. allowmmap = GetConfigValueBool("alsa", "mmap", 1);
  605. periods = device->NumUpdates;
  606. periodLen = (ALuint64)device->UpdateSize * 1000000 / device->Frequency;
  607. bufferLen = periodLen * periods;
  608. rate = device->Frequency;
  609. snd_pcm_hw_params_malloc(&hp);
  610. #define CHECK(x) if((funcerr=#x),(err=(x)) < 0) goto error
  611. CHECK(snd_pcm_hw_params_any(data->pcmHandle, hp));
  612. /* set interleaved access */
  613. if(!allowmmap || snd_pcm_hw_params_set_access(data->pcmHandle, hp, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0)
  614. {
  615. if(periods > 2)
  616. {
  617. periods--;
  618. bufferLen = periodLen * periods;
  619. }
  620. CHECK(snd_pcm_hw_params_set_access(data->pcmHandle, hp, SND_PCM_ACCESS_RW_INTERLEAVED));
  621. }
  622. /* test and set format (implicitly sets sample bits) */
  623. if(snd_pcm_hw_params_test_format(data->pcmHandle, hp, format) < 0)
  624. {
  625. static const struct {
  626. snd_pcm_format_t format;
  627. enum DevFmtType fmttype;
  628. } formatlist[] = {
  629. { SND_PCM_FORMAT_FLOAT, DevFmtFloat },
  630. { SND_PCM_FORMAT_S32, DevFmtInt },
  631. { SND_PCM_FORMAT_U32, DevFmtUInt },
  632. { SND_PCM_FORMAT_S16, DevFmtShort },
  633. { SND_PCM_FORMAT_U16, DevFmtUShort },
  634. { SND_PCM_FORMAT_S8, DevFmtByte },
  635. { SND_PCM_FORMAT_U8, DevFmtUByte },
  636. };
  637. size_t k;
  638. for(k = 0;k < COUNTOF(formatlist);k++)
  639. {
  640. format = formatlist[k].format;
  641. if(snd_pcm_hw_params_test_format(data->pcmHandle, hp, format) >= 0)
  642. {
  643. device->FmtType = formatlist[k].fmttype;
  644. break;
  645. }
  646. }
  647. }
  648. CHECK(snd_pcm_hw_params_set_format(data->pcmHandle, hp, format));
  649. /* test and set channels (implicitly sets frame bits) */
  650. if(snd_pcm_hw_params_test_channels(data->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans)) < 0)
  651. {
  652. static const enum DevFmtChannels channellist[] = {
  653. DevFmtStereo,
  654. DevFmtQuad,
  655. DevFmtX51,
  656. DevFmtX71,
  657. DevFmtMono,
  658. };
  659. size_t k;
  660. for(k = 0;k < COUNTOF(channellist);k++)
  661. {
  662. if(snd_pcm_hw_params_test_channels(data->pcmHandle, hp, ChannelsFromDevFmt(channellist[k])) >= 0)
  663. {
  664. device->FmtChans = channellist[k];
  665. break;
  666. }
  667. }
  668. }
  669. CHECK(snd_pcm_hw_params_set_channels(data->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans)));
  670. /* set rate (implicitly constrains period/buffer parameters) */
  671. if(snd_pcm_hw_params_set_rate_resample(data->pcmHandle, hp, 0) < 0)
  672. ERR("Failed to disable ALSA resampler\n");
  673. CHECK(snd_pcm_hw_params_set_rate_near(data->pcmHandle, hp, &rate, NULL));
  674. /* set buffer time (implicitly constrains period/buffer parameters) */
  675. CHECK(snd_pcm_hw_params_set_buffer_time_near(data->pcmHandle, hp, &bufferLen, NULL));
  676. /* set period time (implicitly sets buffer size/bytes/time and period size/bytes) */
  677. CHECK(snd_pcm_hw_params_set_period_time_near(data->pcmHandle, hp, &periodLen, NULL));
  678. /* install and prepare hardware configuration */
  679. CHECK(snd_pcm_hw_params(data->pcmHandle, hp));
  680. /* retrieve configuration info */
  681. CHECK(snd_pcm_hw_params_get_access(hp, &access));
  682. CHECK(snd_pcm_hw_params_get_period_size(hp, &periodSizeInFrames, NULL));
  683. CHECK(snd_pcm_hw_params_get_periods(hp, &periods, NULL));
  684. snd_pcm_hw_params_free(hp);
  685. hp = NULL;
  686. snd_pcm_sw_params_malloc(&sp);
  687. CHECK(snd_pcm_sw_params_current(data->pcmHandle, sp));
  688. CHECK(snd_pcm_sw_params_set_avail_min(data->pcmHandle, sp, periodSizeInFrames));
  689. CHECK(snd_pcm_sw_params_set_stop_threshold(data->pcmHandle, sp, periodSizeInFrames*periods));
  690. CHECK(snd_pcm_sw_params(data->pcmHandle, sp));
  691. #undef CHECK
  692. snd_pcm_sw_params_free(sp);
  693. sp = NULL;
  694. /* Increase periods by one, since the temp buffer counts as an extra
  695. * period */
  696. if(access == SND_PCM_ACCESS_RW_INTERLEAVED)
  697. device->NumUpdates = periods+1;
  698. else
  699. device->NumUpdates = periods;
  700. device->UpdateSize = periodSizeInFrames;
  701. device->Frequency = rate;
  702. SetDefaultChannelOrder(device);
  703. return ALC_TRUE;
  704. error:
  705. ERR("%s failed: %s\n", funcerr, snd_strerror(err));
  706. if(hp) snd_pcm_hw_params_free(hp);
  707. if(sp) snd_pcm_sw_params_free(sp);
  708. return ALC_FALSE;
  709. }
  710. static ALCboolean alsa_start_playback(ALCdevice *device)
  711. {
  712. alsa_data *data = (alsa_data*)device->ExtraData;
  713. snd_pcm_hw_params_t *hp = NULL;
  714. snd_pcm_access_t access;
  715. const char *funcerr;
  716. int err;
  717. snd_pcm_hw_params_malloc(&hp);
  718. #define CHECK(x) if((funcerr=#x),(err=(x)) < 0) goto error
  719. CHECK(snd_pcm_hw_params_current(data->pcmHandle, hp));
  720. /* retrieve configuration info */
  721. CHECK(snd_pcm_hw_params_get_access(hp, &access));
  722. #undef CHECK
  723. snd_pcm_hw_params_free(hp);
  724. hp = NULL;
  725. data->size = snd_pcm_frames_to_bytes(data->pcmHandle, device->UpdateSize);
  726. if(access == SND_PCM_ACCESS_RW_INTERLEAVED)
  727. {
  728. data->buffer = malloc(data->size);
  729. if(!data->buffer)
  730. {
  731. ERR("buffer malloc failed\n");
  732. return ALC_FALSE;
  733. }
  734. data->thread = StartThread(ALSANoMMapProc, device);
  735. }
  736. else
  737. {
  738. err = snd_pcm_prepare(data->pcmHandle);
  739. if(err < 0)
  740. {
  741. ERR("snd_pcm_prepare(data->pcmHandle) failed: %s\n", snd_strerror(err));
  742. return ALC_FALSE;
  743. }
  744. data->thread = StartThread(ALSAProc, device);
  745. }
  746. if(data->thread == NULL)
  747. {
  748. ERR("Could not create playback thread\n");
  749. free(data->buffer);
  750. data->buffer = NULL;
  751. return ALC_FALSE;
  752. }
  753. return ALC_TRUE;
  754. error:
  755. ERR("%s failed: %s\n", funcerr, snd_strerror(err));
  756. if(hp) snd_pcm_hw_params_free(hp);
  757. return ALC_FALSE;
  758. }
  759. static void alsa_stop_playback(ALCdevice *device)
  760. {
  761. alsa_data *data = (alsa_data*)device->ExtraData;
  762. if(data->thread)
  763. {
  764. data->killNow = 1;
  765. StopThread(data->thread);
  766. data->thread = NULL;
  767. }
  768. data->killNow = 0;
  769. free(data->buffer);
  770. data->buffer = NULL;
  771. }
  772. static ALCenum alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceName)
  773. {
  774. const char *driver = NULL;
  775. snd_pcm_hw_params_t *hp;
  776. snd_pcm_uframes_t bufferSizeInFrames;
  777. snd_pcm_uframes_t periodSizeInFrames;
  778. ALboolean needring = AL_FALSE;
  779. snd_pcm_format_t format;
  780. const char *funcerr;
  781. alsa_data *data;
  782. int err;
  783. if(deviceName)
  784. {
  785. size_t idx;
  786. if(!allCaptureDevNameMap)
  787. allCaptureDevNameMap = probe_devices(SND_PCM_STREAM_CAPTURE, &numCaptureDevNames);
  788. for(idx = 0;idx < numCaptureDevNames;idx++)
  789. {
  790. if(strcmp(deviceName, allCaptureDevNameMap[idx].name) == 0)
  791. {
  792. driver = allCaptureDevNameMap[idx].device;
  793. break;
  794. }
  795. }
  796. if(idx == numCaptureDevNames)
  797. return ALC_INVALID_VALUE;
  798. }
  799. else
  800. {
  801. deviceName = alsaDevice;
  802. driver = GetConfigValue("alsa", "capture", "default");
  803. }
  804. data = (alsa_data*)calloc(1, sizeof(alsa_data));
  805. err = snd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
  806. if(err < 0)
  807. {
  808. ERR("Could not open capture device '%s': %s\n", driver, snd_strerror(err));
  809. free(data);
  810. return ALC_INVALID_VALUE;
  811. }
  812. format = -1;
  813. switch(pDevice->FmtType)
  814. {
  815. case DevFmtByte:
  816. format = SND_PCM_FORMAT_S8;
  817. break;
  818. case DevFmtUByte:
  819. format = SND_PCM_FORMAT_U8;
  820. break;
  821. case DevFmtShort:
  822. format = SND_PCM_FORMAT_S16;
  823. break;
  824. case DevFmtUShort:
  825. format = SND_PCM_FORMAT_U16;
  826. break;
  827. case DevFmtInt:
  828. format = SND_PCM_FORMAT_S32;
  829. break;
  830. case DevFmtUInt:
  831. format = SND_PCM_FORMAT_U32;
  832. break;
  833. case DevFmtFloat:
  834. format = SND_PCM_FORMAT_FLOAT;
  835. break;
  836. }
  837. funcerr = NULL;
  838. bufferSizeInFrames = maxu(pDevice->UpdateSize*pDevice->NumUpdates,
  839. 100*pDevice->Frequency/1000);
  840. periodSizeInFrames = minu(bufferSizeInFrames, 25*pDevice->Frequency/1000);
  841. snd_pcm_hw_params_malloc(&hp);
  842. #define CHECK(x) if((funcerr=#x),(err=(x)) < 0) goto error
  843. CHECK(snd_pcm_hw_params_any(data->pcmHandle, hp));
  844. /* set interleaved access */
  845. CHECK(snd_pcm_hw_params_set_access(data->pcmHandle, hp, SND_PCM_ACCESS_RW_INTERLEAVED));
  846. /* set format (implicitly sets sample bits) */
  847. CHECK(snd_pcm_hw_params_set_format(data->pcmHandle, hp, format));
  848. /* set channels (implicitly sets frame bits) */
  849. CHECK(snd_pcm_hw_params_set_channels(data->pcmHandle, hp, ChannelsFromDevFmt(pDevice->FmtChans)));
  850. /* set rate (implicitly constrains period/buffer parameters) */
  851. CHECK(snd_pcm_hw_params_set_rate(data->pcmHandle, hp, pDevice->Frequency, 0));
  852. /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
  853. if(snd_pcm_hw_params_set_buffer_size_min(data->pcmHandle, hp, &bufferSizeInFrames) < 0)
  854. {
  855. TRACE("Buffer too large, using intermediate ring buffer\n");
  856. needring = AL_TRUE;
  857. CHECK(snd_pcm_hw_params_set_buffer_size_near(data->pcmHandle, hp, &bufferSizeInFrames));
  858. }
  859. /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
  860. CHECK(snd_pcm_hw_params_set_period_size_near(data->pcmHandle, hp, &periodSizeInFrames, NULL));
  861. /* install and prepare hardware configuration */
  862. CHECK(snd_pcm_hw_params(data->pcmHandle, hp));
  863. /* retrieve configuration info */
  864. CHECK(snd_pcm_hw_params_get_period_size(hp, &periodSizeInFrames, NULL));
  865. #undef CHECK
  866. snd_pcm_hw_params_free(hp);
  867. hp = NULL;
  868. if(needring)
  869. {
  870. data->ring = CreateRingBuffer(FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType),
  871. pDevice->UpdateSize*pDevice->NumUpdates);
  872. if(!data->ring)
  873. {
  874. ERR("ring buffer create failed\n");
  875. goto error2;
  876. }
  877. data->size = snd_pcm_frames_to_bytes(data->pcmHandle, periodSizeInFrames);
  878. data->buffer = malloc(data->size);
  879. if(!data->buffer)
  880. {
  881. ERR("buffer malloc failed\n");
  882. goto error2;
  883. }
  884. }
  885. pDevice->szDeviceName = strdup(deviceName);
  886. pDevice->ExtraData = data;
  887. return ALC_NO_ERROR;
  888. error:
  889. ERR("%s failed: %s\n", funcerr, snd_strerror(err));
  890. if(hp) snd_pcm_hw_params_free(hp);
  891. error2:
  892. free(data->buffer);
  893. DestroyRingBuffer(data->ring);
  894. snd_pcm_close(data->pcmHandle);
  895. free(data);
  896. pDevice->ExtraData = NULL;
  897. return ALC_INVALID_VALUE;
  898. }
  899. static void alsa_close_capture(ALCdevice *pDevice)
  900. {
  901. alsa_data *data = (alsa_data*)pDevice->ExtraData;
  902. snd_pcm_close(data->pcmHandle);
  903. DestroyRingBuffer(data->ring);
  904. free(data->buffer);
  905. free(data);
  906. pDevice->ExtraData = NULL;
  907. }
  908. static void alsa_start_capture(ALCdevice *Device)
  909. {
  910. alsa_data *data = (alsa_data*)Device->ExtraData;
  911. int err;
  912. err = snd_pcm_start(data->pcmHandle);
  913. if(err < 0)
  914. {
  915. ERR("start failed: %s\n", snd_strerror(err));
  916. aluHandleDisconnect(Device);
  917. }
  918. else
  919. data->doCapture = AL_TRUE;
  920. }
  921. static ALCenum alsa_capture_samples(ALCdevice *Device, ALCvoid *Buffer, ALCuint Samples)
  922. {
  923. alsa_data *data = (alsa_data*)Device->ExtraData;
  924. if(data->ring)
  925. {
  926. ReadRingBuffer(data->ring, Buffer, Samples);
  927. return ALC_NO_ERROR;
  928. }
  929. data->last_avail -= Samples;
  930. while(Device->Connected && Samples > 0)
  931. {
  932. snd_pcm_sframes_t amt = 0;
  933. if(data->size > 0)
  934. {
  935. /* First get any data stored from the last stop */
  936. amt = snd_pcm_bytes_to_frames(data->pcmHandle, data->size);
  937. if((snd_pcm_uframes_t)amt > Samples) amt = Samples;
  938. amt = snd_pcm_frames_to_bytes(data->pcmHandle, amt);
  939. memmove(Buffer, data->buffer, amt);
  940. if(data->size > amt)
  941. {
  942. memmove(data->buffer, data->buffer+amt, data->size - amt);
  943. data->size -= amt;
  944. }
  945. else
  946. {
  947. free(data->buffer);
  948. data->buffer = NULL;
  949. data->size = 0;
  950. }
  951. amt = snd_pcm_bytes_to_frames(data->pcmHandle, amt);
  952. }
  953. else if(data->doCapture)
  954. amt = snd_pcm_readi(data->pcmHandle, Buffer, Samples);
  955. if(amt < 0)
  956. {
  957. ERR("read error: %s\n", snd_strerror(amt));
  958. if(amt == -EAGAIN)
  959. continue;
  960. if((amt=snd_pcm_recover(data->pcmHandle, amt, 1)) >= 0)
  961. {
  962. amt = snd_pcm_start(data->pcmHandle);
  963. if(amt >= 0)
  964. amt = snd_pcm_avail_update(data->pcmHandle);
  965. }
  966. if(amt < 0)
  967. {
  968. ERR("restore error: %s\n", snd_strerror(amt));
  969. aluHandleDisconnect(Device);
  970. break;
  971. }
  972. /* If the amount available is less than what's asked, we lost it
  973. * during recovery. So just give silence instead. */
  974. if((snd_pcm_uframes_t)amt < Samples)
  975. break;
  976. continue;
  977. }
  978. Buffer = (ALbyte*)Buffer + amt;
  979. Samples -= amt;
  980. }
  981. if(Samples > 0)
  982. memset(Buffer, ((Device->FmtType == DevFmtUByte) ? 0x80 : 0),
  983. snd_pcm_frames_to_bytes(data->pcmHandle, Samples));
  984. return ALC_NO_ERROR;
  985. }
  986. static ALCuint alsa_available_samples(ALCdevice *Device)
  987. {
  988. alsa_data *data = (alsa_data*)Device->ExtraData;
  989. snd_pcm_sframes_t avail = 0;
  990. if(Device->Connected && data->doCapture)
  991. avail = snd_pcm_avail_update(data->pcmHandle);
  992. if(avail < 0)
  993. {
  994. ERR("avail update failed: %s\n", snd_strerror(avail));
  995. if((avail=snd_pcm_recover(data->pcmHandle, avail, 1)) >= 0)
  996. {
  997. if(data->doCapture)
  998. avail = snd_pcm_start(data->pcmHandle);
  999. if(avail >= 0)
  1000. avail = snd_pcm_avail_update(data->pcmHandle);
  1001. }
  1002. if(avail < 0)
  1003. {
  1004. ERR("restore error: %s\n", snd_strerror(avail));
  1005. aluHandleDisconnect(Device);
  1006. }
  1007. }
  1008. if(!data->ring)
  1009. {
  1010. if(avail < 0) avail = 0;
  1011. avail += snd_pcm_bytes_to_frames(data->pcmHandle, data->size);
  1012. if(avail > data->last_avail) data->last_avail = avail;
  1013. return data->last_avail;
  1014. }
  1015. while(avail > 0)
  1016. {
  1017. snd_pcm_sframes_t amt;
  1018. amt = snd_pcm_bytes_to_frames(data->pcmHandle, data->size);
  1019. if(avail < amt) amt = avail;
  1020. amt = snd_pcm_readi(data->pcmHandle, data->buffer, amt);
  1021. if(amt < 0)
  1022. {
  1023. ERR("read error: %s\n", snd_strerror(amt));
  1024. if(amt == -EAGAIN)
  1025. continue;
  1026. if((amt=snd_pcm_recover(data->pcmHandle, amt, 1)) >= 0)
  1027. {
  1028. if(data->doCapture)
  1029. amt = snd_pcm_start(data->pcmHandle);
  1030. if(amt >= 0)
  1031. amt = snd_pcm_avail_update(data->pcmHandle);
  1032. }
  1033. if(amt < 0)
  1034. {
  1035. ERR("restore error: %s\n", snd_strerror(amt));
  1036. aluHandleDisconnect(Device);
  1037. break;
  1038. }
  1039. avail = amt;
  1040. continue;
  1041. }
  1042. WriteRingBuffer(data->ring, data->buffer, amt);
  1043. avail -= amt;
  1044. }
  1045. return RingBufferSize(data->ring);
  1046. }
  1047. static void alsa_stop_capture(ALCdevice *Device)
  1048. {
  1049. alsa_data *data = (alsa_data*)Device->ExtraData;
  1050. ALCuint avail;
  1051. int err;
  1052. /* OpenAL requires access to unread audio after stopping, but ALSA's
  1053. * snd_pcm_drain is unreliable and snd_pcm_drop drops it. Capture what's
  1054. * available now so it'll be available later after the drop. */
  1055. avail = alsa_available_samples(Device);
  1056. if(!data->ring && avail > 0)
  1057. {
  1058. /* The ring buffer implicitly captures when checking availability.
  1059. * Direct access needs to explicitly capture it into temp storage. */
  1060. ALsizei size;
  1061. void *ptr;
  1062. size = snd_pcm_frames_to_bytes(data->pcmHandle, avail);
  1063. ptr = realloc(data->buffer, size);
  1064. if(ptr)
  1065. {
  1066. data->buffer = ptr;
  1067. alsa_capture_samples(Device, data->buffer, avail);
  1068. data->size = size;
  1069. }
  1070. }
  1071. err = snd_pcm_drop(data->pcmHandle);
  1072. if(err < 0)
  1073. ERR("drop failed: %s\n", snd_strerror(err));
  1074. data->doCapture = AL_FALSE;
  1075. }
  1076. static const BackendFuncs alsa_funcs = {
  1077. alsa_open_playback,
  1078. alsa_close_playback,
  1079. alsa_reset_playback,
  1080. alsa_start_playback,
  1081. alsa_stop_playback,
  1082. alsa_open_capture,
  1083. alsa_close_capture,
  1084. alsa_start_capture,
  1085. alsa_stop_capture,
  1086. alsa_capture_samples,
  1087. alsa_available_samples
  1088. };
  1089. ALCboolean alc_alsa_init(BackendFuncs *func_list)
  1090. {
  1091. if(!alsa_load())
  1092. return ALC_FALSE;
  1093. *func_list = alsa_funcs;
  1094. return ALC_TRUE;
  1095. }
  1096. void alc_alsa_deinit(void)
  1097. {
  1098. ALuint i;
  1099. for(i = 0;i < numDevNames;++i)
  1100. {
  1101. free(allDevNameMap[i].name);
  1102. free(allDevNameMap[i].device);
  1103. }
  1104. free(allDevNameMap);
  1105. allDevNameMap = NULL;
  1106. numDevNames = 0;
  1107. for(i = 0;i < numCaptureDevNames;++i)
  1108. {
  1109. free(allCaptureDevNameMap[i].name);
  1110. free(allCaptureDevNameMap[i].device);
  1111. }
  1112. free(allCaptureDevNameMap);
  1113. allCaptureDevNameMap = NULL;
  1114. numCaptureDevNames = 0;
  1115. #ifdef HAVE_DYNLOAD
  1116. if(alsa_handle)
  1117. CloseLib(alsa_handle);
  1118. alsa_handle = NULL;
  1119. #endif
  1120. }
  1121. void alc_alsa_probe(enum DevProbe type)
  1122. {
  1123. ALuint i;
  1124. switch(type)
  1125. {
  1126. case ALL_DEVICE_PROBE:
  1127. for(i = 0;i < numDevNames;++i)
  1128. {
  1129. free(allDevNameMap[i].name);
  1130. free(allDevNameMap[i].device);
  1131. }
  1132. free(allDevNameMap);
  1133. allDevNameMap = probe_devices(SND_PCM_STREAM_PLAYBACK, &numDevNames);
  1134. for(i = 0;i < numDevNames;++i)
  1135. AppendAllDeviceList(allDevNameMap[i].name);
  1136. break;
  1137. case CAPTURE_DEVICE_PROBE:
  1138. for(i = 0;i < numCaptureDevNames;++i)
  1139. {
  1140. free(allCaptureDevNameMap[i].name);
  1141. free(allCaptureDevNameMap[i].device);
  1142. }
  1143. free(allCaptureDevNameMap);
  1144. allCaptureDevNameMap = probe_devices(SND_PCM_STREAM_CAPTURE, &numCaptureDevNames);
  1145. for(i = 0;i < numCaptureDevNames;++i)
  1146. AppendCaptureDeviceList(allCaptureDevNameMap[i].name);
  1147. break;
  1148. }
  1149. }