aRts audio server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

audioiocsl.cc 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. /*
  2. Copyright (C) 2000-2002 Stefan Westerfeld
  3. stefan@space.twc.de
  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. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public License
  13. along with this library; see the file COPYING.LIB. If not, write to
  14. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. Boston, MA 02110-1301, USA.
  16. */
  17. #ifdef HAVE_CONFIG_H
  18. #include <config.h>
  19. #endif
  20. /**
  21. * only compile 'csl' AudioIO class if libcsl is present
  22. */
  23. #ifdef HAVE_LIBCSL
  24. #include <csl/csl.h>
  25. /* g_newa */
  26. #include <gsl/gsldefs.h>
  27. #include <vector>
  28. #include "audioio.h"
  29. #include "audiosubsys.h"
  30. #include "debug.h"
  31. #include "dispatcher.h"
  32. #include "iomanager.h"
  33. namespace Arts {
  34. class AudioIOCSL : public AudioIO,
  35. public IONotify
  36. {
  37. protected:
  38. CslPcmStream *inputStream, *outputStream;
  39. CslDriver *cslDriver;
  40. int requestedFragmentSize;
  41. int requestedFragmentCount;
  42. const char *cslDriverName;
  43. std::vector<CslPollFD> cslFds, cslOldFds;
  44. int csl2iomanager(int cslTypes);
  45. void updateFds();
  46. void notifyIO(int fd, int types);
  47. static void handleRead(void *user_data, CslPcmStream *stream);
  48. static void handleWrite(void *user_data, CslPcmStream *stream);
  49. public:
  50. AudioIOCSL(const char *driverName = 0);
  51. void setParam(AudioParam param, int& value);
  52. int getParam(AudioParam param);
  53. bool open();
  54. void close();
  55. int read(void *buffer, int size);
  56. int write(void *buffer, int size);
  57. };
  58. REGISTER_AUDIO_IO(AudioIOCSL,"csl","Common Sound Layer");
  59. class AudioIOCSLFactory : public AudioIOFactory {
  60. protected:
  61. const char *driverName;
  62. std::string _name;
  63. std::string _fullName;
  64. public:
  65. AudioIOCSLFactory(const char *driverName)
  66. : driverName(driverName)
  67. {
  68. _name = "csl-";
  69. _name += driverName;
  70. _fullName = "Common Sound Layer (";
  71. _fullName += driverName;
  72. _fullName += ")";
  73. }
  74. virtual ~AudioIOCSLFactory()
  75. {
  76. }
  77. AudioIO *createAudioIO() { return new AudioIOCSL(driverName); }
  78. virtual const char *name() { return _name.c_str(); }
  79. virtual const char *fullName() { return _fullName.c_str(); }
  80. };
  81. static class AudioIOCSLInit {
  82. protected:
  83. std::list<AudioIOCSLFactory *> factories;
  84. public:
  85. AudioIOCSLInit()
  86. {
  87. unsigned int i,n;
  88. const char **drivers = csl_list_drivers(&n);
  89. for(i = 0; i < n; i++)
  90. factories.push_back(new AudioIOCSLFactory(drivers[i]));
  91. }
  92. ~AudioIOCSLInit()
  93. {
  94. std::list<AudioIOCSLFactory *>::iterator i;
  95. for(i = factories.begin(); i != factories.end(); i++)
  96. delete (*i);
  97. factories.clear();
  98. }
  99. } aci;
  100. };
  101. using namespace std;
  102. using namespace Arts;
  103. AudioIOCSL::AudioIOCSL(const char *driverName)
  104. : cslDriverName(driverName)
  105. {
  106. /*
  107. * default parameters
  108. */
  109. param(samplingRate) = 44100;
  110. paramStr(deviceName) = "todo";
  111. requestedFragmentSize = param(fragmentSize) = 1024;
  112. requestedFragmentCount = param(fragmentCount) = 7;
  113. param(channels) = 2;
  114. param(direction) = 2;
  115. #ifdef WORDS_BIGENDIAN
  116. param(format) = 17;
  117. #else
  118. param(format) = 16;
  119. #endif
  120. }
  121. bool AudioIOCSL::open()
  122. {
  123. string& errorMsg = paramStr(lastError);
  124. string& _deviceName = paramStr(deviceName);
  125. int& _channels = param(channels);
  126. int& _fragmentSize = param(fragmentSize);
  127. int& _fragmentCount = param(fragmentCount);
  128. int& _samplingRate = param(samplingRate);
  129. int& _format = param(format);
  130. int fmt = 0;
  131. char *env = 0;
  132. if(cslDriverName && strcmp(cslDriverName, "arts") == 0)
  133. env = arts_strdup_printf("ARTS_SERVER=%s",_deviceName.c_str());
  134. if(env)
  135. {
  136. putenv(env);
  137. arts_debug("AudioIOCsl: set %s\n",env);
  138. }
  139. CslErrorType error;
  140. error = csl_driver_init(cslDriverName, &cslDriver); /* choose backend */
  141. if(env)
  142. {
  143. putenv("ARTS_SERVER");
  144. free(env);
  145. }
  146. if (error)
  147. {
  148. errorMsg = "unable to initialize CSL driver: ";
  149. errorMsg += csl_strerror(error);
  150. return false;
  151. }
  152. if(_format == 8)
  153. fmt = CSL_PCM_FORMAT_U8;
  154. else if(_format == 16)
  155. fmt = CSL_PCM_FORMAT_S16_LE;
  156. else if(_format == 17)
  157. fmt = CSL_PCM_FORMAT_S16_BE;
  158. inputStream = outputStream = 0;
  159. if(param(direction) & directionRead)
  160. {
  161. /* open PCM output stream */
  162. error = csl_pcm_open_output(cslDriver,
  163. "artsd output",
  164. _samplingRate,
  165. _channels,
  166. fmt, &inputStream);
  167. if (error)
  168. {
  169. errorMsg = "failed to open CSL input stream: ";
  170. errorMsg += csl_strerror(error);
  171. return false;
  172. }
  173. csl_pcm_set_callback(inputStream, handleRead, 0, 0);
  174. }
  175. if(param(direction) & directionWrite)
  176. {
  177. /* open PCM output stream */
  178. error = csl_pcm_open_output(cslDriver,
  179. "artsd output",
  180. _samplingRate,
  181. _channels,
  182. fmt, &outputStream);
  183. if (error)
  184. {
  185. close();
  186. errorMsg = "failed to open CSL output stream: ";
  187. errorMsg += csl_strerror(error);
  188. return false;
  189. }
  190. csl_pcm_set_callback(outputStream, handleWrite, 0, 0);
  191. }
  192. #if 0
  193. if (_format && (ossBits(gotFormat) != ossBits(requestedFormat)))
  194. {
  195. char details[80];
  196. sprintf(details," (_format = %d, asked driver to give %d, got %d)",
  197. _format, requestedFormat, gotFormat);
  198. _error = "Can't set playback format";
  199. _error += details;
  200. close();
  201. return false;
  202. }
  203. if(gotFormat == AFMT_U8)
  204. _format = 8;
  205. else if(gotFormat == AFMT_S16_LE)
  206. _format = 16;
  207. else if(gotFormat == AFMT_S16_BE)
  208. _format = 17;
  209. else
  210. {
  211. char details[80];
  212. sprintf(details," (_format = %d, asked driver to give %d, got %d)",
  213. _format, requestedFormat, gotFormat);
  214. _error = "unknown format given by driver";
  215. _error += details;
  216. close();
  217. return false;
  218. }
  219. int stereo=-1; /* 0=mono, 1=stereo */
  220. if(_channels == 1)
  221. {
  222. stereo = 0;
  223. }
  224. if(_channels == 2)
  225. {
  226. stereo = 1;
  227. }
  228. if(stereo == -1)
  229. {
  230. _error = "internal error; set channels to 1 (mono) or 2 (stereo)";
  231. close();
  232. return false;
  233. }
  234. int requeststereo = stereo;
  235. if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo)==-1)
  236. {
  237. _error = "SNDCTL_DSP_STEREO failed - ";
  238. _error += strerror(errno);
  239. close();
  240. return false;
  241. }
  242. if (requeststereo != stereo)
  243. {
  244. _error = "audio device doesn't support number of requested channels";
  245. close();
  246. return false;
  247. }
  248. int speed = _samplingRate;
  249. if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed)==-1)
  250. {
  251. _error = "SNDCTL_DSP_SPEED failed - ";
  252. _error += strerror(errno);
  253. close();
  254. return false;
  255. }
  256. /*
  257. * Some soundcards seem to be able to only supply "nearly" the requested
  258. * sampling rate, especially PAS 16 cards seem to quite radical supplying
  259. * something different than the requested sampling rate ;)
  260. *
  261. * So we have a quite large tolerance here (when requesting 44100 Hz, it
  262. * will accept anything between 38690 Hz and 49510 Hz). Most parts of the
  263. * aRts code will do resampling where appropriate, so it shouldn't affect
  264. * sound quality.
  265. */
  266. int tolerance = _samplingRate/10+1000;
  267. if (abs(speed-_samplingRate) > tolerance)
  268. {
  269. _error = "can't set requested samplingrate";
  270. char details[80];
  271. sprintf(details," (requested rate %d, got rate %d)",
  272. _samplingRate, speed);
  273. _error += details;
  274. close();
  275. return false;
  276. }
  277. _samplingRate = speed;
  278. /*
  279. * set the fragment settings to what the user requested
  280. */
  281. _fragmentSize = requestedFragmentSize;
  282. _fragmentCount = requestedFragmentCount;
  283. /*
  284. * lower 16 bits are the fragment size (as 2^S)
  285. * higher 16 bits are the number of fragments
  286. */
  287. int frag_arg = 0;
  288. int size = _fragmentSize;
  289. while(size > 1) { size /= 2; frag_arg++; }
  290. frag_arg += (_fragmentCount << 16);
  291. if(ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_arg) == -1)
  292. {
  293. char buffer[1024];
  294. _error = "can't set requested fragments settings";
  295. sprintf(buffer,"size%d:count%d\n",_fragmentSize,_fragmentCount);
  296. close();
  297. return false;
  298. }
  299. /*
  300. * now see what we really got as cards aren't required to supply what
  301. * we asked for
  302. */
  303. audio_buf_info info;
  304. if(ioctl(audio_fd,SNDCTL_DSP_GETOSPACE, &info) == -1)
  305. {
  306. _error = "can't retrieve fragment settings";
  307. close();
  308. return false;
  309. }
  310. // update fragment settings with what we got
  311. _fragmentSize = info.fragsize;
  312. _fragmentCount = info.fragstotal;
  313. artsdebug("buffering: %d fragments with %d bytes "
  314. "(audio latency is %1.1f ms)", _fragmentCount, _fragmentSize,
  315. (float)(_fragmentSize*_fragmentCount) /
  316. (float)(2.0 * _samplingRate * _channels)*1000.0);
  317. /*
  318. * Workaround for broken kernel drivers: usually filling up the audio
  319. * buffer is _only_ required if _fullDuplex is true. However, there
  320. * are kernel drivers around (especially everything related to ES1370/1371)
  321. * which will not trigger select()ing the file descriptor unless we have
  322. * written something first.
  323. */
  324. char *zbuffer = (char *)calloc(sizeof(char), _fragmentSize);
  325. if(_format == 8)
  326. for(int zpos = 0; zpos < _fragmentSize; zpos++)
  327. zbuffer[zpos] |= 0x80;
  328. for(int fill = 0; fill < _fragmentCount; fill++)
  329. {
  330. int len = ::write(audio_fd,zbuffer,_fragmentSize);
  331. if(len != _fragmentSize)
  332. {
  333. arts_debug("AudioIOCSL: failed prefilling audio buffer (might cause synchronization problems in conjunction with full duplex)");
  334. fill = _fragmentCount+1;
  335. }
  336. }
  337. free(zbuffer);
  338. /*
  339. * Triggering - the original aRts code did this for full duplex:
  340. *
  341. * - stop audio i/o using SETTRIGGER(~(PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT))
  342. * - fill buffer (see zbuffer code two lines above)
  343. * - start audio i/o using SETTRIGGER(PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT)
  344. *
  345. * this should guarantee synchronous start of input/output. Today, it
  346. * seems there are too many broken drivers around for this.
  347. */
  348. if(device_caps & DSP_CAP_TRIGGER)
  349. {
  350. int enable_bits = 0;
  351. if(param(direction) & 1) enable_bits |= PCM_ENABLE_INPUT;
  352. if(param(direction) & 2) enable_bits |= PCM_ENABLE_OUTPUT;
  353. if(ioctl(audio_fd,SNDCTL_DSP_SETTRIGGER, &enable_bits) == -1)
  354. {
  355. _error = "can't start sound i/o";
  356. close();
  357. return false;
  358. }
  359. }
  360. #endif
  361. updateFds();
  362. return true;
  363. }
  364. void AudioIOCSL::close()
  365. {
  366. if(inputStream)
  367. {
  368. csl_pcm_close(inputStream);
  369. inputStream = 0;
  370. }
  371. if(outputStream)
  372. {
  373. csl_pcm_close(outputStream);
  374. outputStream = 0;
  375. }
  376. updateFds();
  377. }
  378. void AudioIOCSL::setParam(AudioParam p, int& value)
  379. {
  380. switch(p)
  381. {
  382. case fragmentSize:
  383. param(p) = requestedFragmentSize = value;
  384. break;
  385. case fragmentCount:
  386. param(p) = requestedFragmentCount = value;
  387. break;
  388. default:
  389. param(p) = value;
  390. break;
  391. }
  392. }
  393. int AudioIOCSL::getParam(AudioParam p)
  394. {
  395. CslErrorType error;
  396. CslPcmStatus status;
  397. switch(p)
  398. {
  399. case canRead:
  400. error = csl_pcm_get_status (inputStream, &status);
  401. if (error) /* FIXME */
  402. arts_fatal("unable to obtain csl stream status: %s",
  403. csl_strerror (error));
  404. updateFds();
  405. return status.n_bytes_available;
  406. break;
  407. case canWrite:
  408. error = csl_pcm_get_status(outputStream, &status);
  409. if (error) /* FIXME */
  410. arts_fatal("unable to obtain csl stream status: %s",
  411. csl_strerror (error));
  412. updateFds();
  413. return status.n_bytes_available;
  414. break;
  415. case autoDetect:
  416. /* CSL is pretty experimental currently */
  417. return 1;
  418. break;
  419. default:
  420. return param(p);
  421. break;
  422. }
  423. }
  424. int AudioIOCSL::read(void *buffer, int size)
  425. {
  426. arts_assert(inputStream != 0);
  427. int result = csl_pcm_read(inputStream, size, buffer);
  428. updateFds();
  429. return result;
  430. }
  431. void AudioIOCSL::handleRead(void *, CslPcmStream *)
  432. {
  433. AudioSubSystem::the()->handleIO(AudioSubSystem::ioRead);
  434. }
  435. int AudioIOCSL::write(void *buffer, int size)
  436. {
  437. arts_assert(outputStream != 0);
  438. int result = csl_pcm_write(outputStream, size, buffer);
  439. updateFds();
  440. return result;
  441. }
  442. void AudioIOCSL::handleWrite(void *, CslPcmStream *)
  443. {
  444. AudioSubSystem::the()->handleIO(AudioSubSystem::ioWrite);
  445. }
  446. /* mainloop integration: make CSL callbacks work inside the aRts mainloop */
  447. int AudioIOCSL::csl2iomanager(int cslTypes)
  448. {
  449. /* FIXME: doublecheck this list */
  450. int types = 0;
  451. if(cslTypes & CSL_POLLIN)
  452. types |= IOType::read;
  453. if(cslTypes & CSL_POLLOUT)
  454. types |= IOType::write;
  455. if(cslTypes & CSL_POLLERR)
  456. types |= IOType::except;
  457. return types;
  458. }
  459. void AudioIOCSL::updateFds()
  460. {
  461. unsigned int n_fds = csl_poll_count_fds(cslDriver);
  462. CslPollFD *newFds = g_newa(CslPollFD, n_fds);
  463. unsigned int have_fds = csl_poll_get_fds(cslDriver, n_fds, newFds);
  464. arts_assert(have_fds == n_fds);
  465. cslFds.clear();
  466. unsigned int i;
  467. for(i = 0; i < have_fds; i++)
  468. cslFds.push_back(newFds[i]);
  469. /* FIXME: if csl provided a flag for this, we could save some work here */
  470. bool fdsChanged;
  471. if(cslFds.size() == cslOldFds.size())
  472. {
  473. fdsChanged = false;
  474. for(i = 0; i < have_fds; i++)
  475. {
  476. if(cslFds[i].events != cslOldFds[i].events)
  477. fdsChanged = true;
  478. if(cslFds[i].fd != cslOldFds[i].fd)
  479. fdsChanged = true;
  480. }
  481. }
  482. else
  483. {
  484. fdsChanged = true;
  485. }
  486. if(!fdsChanged)
  487. return;
  488. vector<CslPollFD>::iterator ci;
  489. /* remove old watches */
  490. /*
  491. * UGLY! due to broken API, we can only remove all watches here, and not
  492. * do anything selectively - its not a problem for the code here, but it
  493. * might be a problem elsewhere. Unfortunately, it can't be fixed without
  494. * breaking BC.
  495. */
  496. Dispatcher::the()->ioManager()->remove(this, IOType::all);
  497. arts_debug("AudioIOCSL::updateFds(): removing watches");
  498. /* add new watches */
  499. for(ci = cslFds.begin(); ci < cslFds.end(); ci++)
  500. {
  501. int types = csl2iomanager(ci->events);
  502. if(types)
  503. {
  504. Dispatcher::the()->ioManager()->watchFD(ci->fd, types, this);
  505. arts_debug("AudioIOCSL::updateFds(): adding watch on %d", ci->fd);
  506. }
  507. }
  508. cslOldFds = cslFds;
  509. }
  510. void AudioIOCSL::notifyIO(int fd, int type)
  511. {
  512. vector<CslPollFD>::iterator fi;
  513. for(fi = cslFds.begin(); fi != cslFds.end(); fi++)
  514. {
  515. if(fi->fd == fd)
  516. {
  517. int ftype = csl2iomanager(fi->events);
  518. fi->revents = 0;
  519. if(type & ftype & IOType::read)
  520. fi->revents |= CSL_POLLIN;
  521. if(type & ftype & IOType::write)
  522. fi->revents |= CSL_POLLOUT;
  523. if(type & ftype & IOType::except)
  524. fi->revents |= CSL_POLLERR;
  525. if(fi->revents)
  526. csl_poll_handle_fds(cslDriver, 1, &(*fi));
  527. }
  528. }
  529. updateFds();
  530. }
  531. #endif