eSpeak NG is an open source speech synthesizer that supports more than hundred languages and accents.
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.

wave_pulse.c 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. /*
  2. * Copyright (C) 2007, Gilles Casse <[email protected]>
  3. * Copyright (C) 2015 Reece H. Dunn
  4. * eSpeak driver for PulseAudio
  5. * based on the XMMS PulseAudio Plugin
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, see: <http://www.gnu.org/licenses/>.
  19. */
  20. // TBD:
  21. // * ARCH_BIG
  22. // * uint64? a_timing_info.read_index
  23. // * prebuf,... size?
  24. // * 0.9.6: pb pulse_free using tlength=8820 (max size never returned -> tlength=10000 ok, but higher drain).
  25. //
  26. #include "speech.h"
  27. #ifdef USE_ASYNC
  28. // This source file is only used for asynchronious modes
  29. #include <stdbool.h>
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <stdlib.h>
  33. #include <math.h>
  34. #include <assert.h>
  35. #include <sys/time.h>
  36. #include <time.h>
  37. #include <pulse/pulseaudio.h>
  38. #include <pthread.h>
  39. #ifndef PLATFORM_WINDOWS
  40. #include <unistd.h>
  41. #endif
  42. #include "wave.h"
  43. #include "debug.h"
  44. enum {ONE_BILLION=1000000000};
  45. enum {
  46. /* return value */
  47. PULSE_OK = 0,
  48. PULSE_ERROR = -1,
  49. PULSE_NO_CONNECTION = -2
  50. };
  51. #ifdef USE_PULSEAUDIO
  52. static t_wave_callback* my_callback_is_output_enabled=NULL;
  53. #define SAMPLE_RATE 22050
  54. #define ESPEAK_FORMAT PA_SAMPLE_S16LE
  55. #define ESPEAK_CHANNEL 1
  56. #define MAXLENGTH 132300
  57. #define TLENGTH 4410
  58. #define PREBUF 2200
  59. #define MINREQ 880
  60. #define FRAGSIZE 0
  61. #ifdef USE_PORTAUDIO
  62. // rename functions to be wrapped
  63. #define wave_init wave_pulse_init
  64. #define wave_open wave_pulse_open
  65. #define wave_write wave_pulse_write
  66. #define wave_close wave_pulse_close
  67. #define wave_is_busy wave_pulse_is_busy
  68. #define wave_terminate wave_pulse_terminate
  69. #define wave_get_read_position wave_pulse_get_read_position
  70. #define wave_get_write_position wave_pulse_get_write_position
  71. #define wave_flush wave_pulse_flush
  72. #define wave_set_callback_is_output_enabled wave_pulse_set_callback_is_output_enabled
  73. #define wave_test_get_write_buffer wave_pulse_test_get_write_buffer
  74. #define wave_get_remaining_time wave_pulse_get_remaining_time
  75. // check whether we can connect to PulseAudio
  76. #include <pulse/simple.h>
  77. int is_pulse_running()
  78. {
  79. pa_sample_spec ss;
  80. ss.format = ESPEAK_FORMAT;
  81. ss.rate = SAMPLE_RATE;
  82. ss.channels = ESPEAK_CHANNEL;
  83. pa_simple *s = pa_simple_new(NULL, "eSpeak", PA_STREAM_PLAYBACK, NULL, "is_pulse_running", &ss, NULL, NULL, NULL);
  84. if (s) {
  85. pa_simple_free(s);
  86. return 1;
  87. } else
  88. return 0;
  89. }
  90. #endif // USE_PORTAUDIO
  91. static pthread_mutex_t pulse_mutex;
  92. static pa_context *context = NULL;
  93. static pa_stream *stream = NULL;
  94. static pa_threaded_mainloop *mainloop = NULL;
  95. static int do_trigger = 0;
  96. static uint64_t written = 0;
  97. static int time_offset_msec = 0;
  98. static int just_flushed = 0;
  99. static int connected = 0;
  100. static int wave_samplerate;
  101. #define CHECK_DEAD_GOTO(label, warn) do { \
  102. if (!mainloop || \
  103. !context || pa_context_get_state(context) != PA_CONTEXT_READY || \
  104. !stream || pa_stream_get_state(stream) != PA_STREAM_READY) { \
  105. if (warn) \
  106. SHOW("Connection died: %s\n", context ? pa_strerror(pa_context_errno(context)) : "NULL"); \
  107. goto label; \
  108. } \
  109. } while(0);
  110. #define CHECK_CONNECTED(retval) \
  111. do { \
  112. if (!connected) return retval; \
  113. } while (0);
  114. #define CHECK_CONNECTED_NO_RETVAL(id) \
  115. do { \
  116. if (!connected) { SHOW("CHECK_CONNECTED_NO_RETVAL: !pulse_connected\n", ""); return; } \
  117. } while (0);
  118. static void subscribe_cb(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) {
  119. ENTER(__FUNCTION__);
  120. assert(c);
  121. if (!stream ||
  122. index != pa_stream_get_index(stream) ||
  123. (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) &&
  124. t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW)))
  125. return;
  126. }
  127. static void context_state_cb(pa_context *c, void *userdata) {
  128. ENTER(__FUNCTION__);
  129. assert(c);
  130. switch (pa_context_get_state(c)) {
  131. case PA_CONTEXT_READY:
  132. case PA_CONTEXT_TERMINATED:
  133. case PA_CONTEXT_FAILED:
  134. pa_threaded_mainloop_signal(mainloop, 0);
  135. break;
  136. case PA_CONTEXT_UNCONNECTED:
  137. case PA_CONTEXT_CONNECTING:
  138. case PA_CONTEXT_AUTHORIZING:
  139. case PA_CONTEXT_SETTING_NAME:
  140. break;
  141. }
  142. }
  143. static void stream_state_cb(pa_stream *s, void * userdata) {
  144. ENTER(__FUNCTION__);
  145. assert(s);
  146. switch (pa_stream_get_state(s)) {
  147. case PA_STREAM_READY:
  148. case PA_STREAM_FAILED:
  149. case PA_STREAM_TERMINATED:
  150. pa_threaded_mainloop_signal(mainloop, 0);
  151. break;
  152. case PA_STREAM_UNCONNECTED:
  153. case PA_STREAM_CREATING:
  154. break;
  155. }
  156. }
  157. static void stream_success_cb(pa_stream *s, int success, void *userdata) {
  158. ENTER(__FUNCTION__);
  159. assert(s);
  160. if (userdata)
  161. *(int*) userdata = success;
  162. pa_threaded_mainloop_signal(mainloop, 0);
  163. }
  164. static void context_success_cb(pa_context *c, int success, void *userdata) {
  165. ENTER(__FUNCTION__);
  166. assert(c);
  167. if (userdata)
  168. *(int*) userdata = success;
  169. pa_threaded_mainloop_signal(mainloop, 0);
  170. }
  171. static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
  172. ENTER(__FUNCTION__);
  173. assert(s);
  174. pa_threaded_mainloop_signal(mainloop, 0);
  175. }
  176. static void stream_latency_update_cb(pa_stream *s, void *userdata) {
  177. assert(s);
  178. pa_threaded_mainloop_signal(mainloop, 0);
  179. }
  180. static int pulse_free(void) {
  181. ENTER(__FUNCTION__);
  182. size_t l = 0;
  183. pa_operation *o = NULL;
  184. CHECK_CONNECTED(0);
  185. SHOW("pulse_free: %s (call)\n", "pa_threaded_main_loop_lock");
  186. pa_threaded_mainloop_lock(mainloop);
  187. CHECK_DEAD_GOTO(fail, 1);
  188. if ((l = pa_stream_writable_size(stream)) == (size_t) -1) {
  189. SHOW("pa_stream_writable_size() failed: %s", pa_strerror(pa_context_errno(context)));
  190. l = 0;
  191. goto fail;
  192. }
  193. SHOW("pulse_free: %s (ret=%d)\n", "pa_stream_writable_size", l);
  194. /* If this function is called twice with no pulse_write() call in
  195. * between this means we should trigger the playback */
  196. if (do_trigger) {
  197. int success = 0;
  198. SHOW("pulse_free: %s (call)\n", "pa_stream_trigger");
  199. if (!(o = pa_stream_trigger(stream, stream_success_cb, &success))) {
  200. SHOW("pa_stream_trigger() failed: %s", pa_strerror(pa_context_errno(context)));
  201. goto fail;
  202. }
  203. SHOW("pulse_free: %s (call)\n", "pa_threaded_main_loop");
  204. while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
  205. CHECK_DEAD_GOTO(fail, 1);
  206. pa_threaded_mainloop_wait(mainloop);
  207. }
  208. SHOW("pulse_free: %s (ret)\n", "pa_threaded_main_loop");
  209. if (!success)
  210. SHOW("pa_stream_trigger() failed: %s", pa_strerror(pa_context_errno(context)));
  211. }
  212. fail:
  213. SHOW("pulse_free: %s (call)\n", "pa_operation_unref");
  214. if (o)
  215. pa_operation_unref(o);
  216. SHOW("pulse_free: %s (call)\n", "pa_threaded_main_loop_unlock");
  217. pa_threaded_mainloop_unlock(mainloop);
  218. do_trigger = !!l;
  219. SHOW("pulse_free: %d (ret)\n", (int)l);
  220. return (int) l;
  221. }
  222. static int pulse_playing(const pa_timing_info *the_timing_info) {
  223. ENTER(__FUNCTION__);
  224. int r = 0;
  225. const pa_timing_info *i;
  226. assert(the_timing_info);
  227. CHECK_CONNECTED(0);
  228. pa_threaded_mainloop_lock(mainloop);
  229. for (;; ) {
  230. CHECK_DEAD_GOTO(fail, 1);
  231. if ((i = pa_stream_get_timing_info(stream)))
  232. {
  233. break;
  234. }
  235. if (pa_context_errno(context) != PA_ERR_NODATA) {
  236. SHOW("pa_stream_get_timing_info() failed: %s", pa_strerror(pa_context_errno(context)));
  237. goto fail;
  238. }
  239. pa_threaded_mainloop_wait(mainloop);
  240. }
  241. r = i->playing;
  242. memcpy((void*)the_timing_info, (void*)i, sizeof(pa_timing_info));
  243. fail:
  244. pa_threaded_mainloop_unlock(mainloop);
  245. return r;
  246. }
  247. static void pulse_write(void* ptr, int length) {
  248. ENTER(__FUNCTION__);
  249. SHOW("pulse_write > length=%d\n", length);
  250. CHECK_CONNECTED_NO_RETVAL();
  251. pa_threaded_mainloop_lock(mainloop);
  252. CHECK_DEAD_GOTO(fail, 1);
  253. if (pa_stream_write(stream, ptr, length, NULL, PA_SEEK_RELATIVE, (pa_seek_mode_t)0) < 0) {
  254. SHOW("pa_stream_write() failed: %s", pa_strerror(pa_context_errno(context)));
  255. goto fail;
  256. }
  257. do_trigger = 0;
  258. written += length;
  259. fail:
  260. pa_threaded_mainloop_unlock(mainloop);
  261. }
  262. static int drain(void) {
  263. pa_operation *o = NULL;
  264. int success = 0;
  265. int ret = PULSE_ERROR;
  266. ENTER(__FUNCTION__);
  267. CHECK_CONNECTED(ret);
  268. pa_threaded_mainloop_lock(mainloop);
  269. CHECK_DEAD_GOTO(fail, 0);
  270. SHOW_TIME("pa_stream_drain (call)");
  271. if (!(o = pa_stream_drain(stream, stream_success_cb, &success))) {
  272. SHOW("pa_stream_drain() failed: %s\n", pa_strerror(pa_context_errno(context)));
  273. goto fail;
  274. }
  275. SHOW_TIME("pa_threaded_mainloop_wait (call)");
  276. while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
  277. CHECK_DEAD_GOTO(fail, 1);
  278. pa_threaded_mainloop_wait(mainloop);
  279. }
  280. SHOW_TIME("pa_threaded_mainloop_wait (ret)");
  281. if (!success) {
  282. SHOW("pa_stream_drain() failed: %s\n", pa_strerror(pa_context_errno(context)));
  283. }
  284. else {
  285. ret = PULSE_OK;
  286. }
  287. fail:
  288. SHOW_TIME("pa_operation_unref (call)");
  289. if (o)
  290. pa_operation_unref(o);
  291. pa_threaded_mainloop_unlock(mainloop);
  292. SHOW_TIME("drain (ret)");
  293. return ret;
  294. }
  295. static void pulse_close(void) {
  296. ENTER(__FUNCTION__);
  297. drain();
  298. connected = 0;
  299. if (mainloop)
  300. pa_threaded_mainloop_stop(mainloop);
  301. connected = 0;
  302. if (context) {
  303. SHOW_TIME("pa_context_disconnect (call)");
  304. pa_context_disconnect(context);
  305. pa_context_unref(context);
  306. context = NULL;
  307. }
  308. if (mainloop) {
  309. SHOW_TIME("pa_threaded_mainloop_free (call)");
  310. pa_threaded_mainloop_free(mainloop);
  311. mainloop = NULL;
  312. }
  313. SHOW_TIME("pulse_close (ret)");
  314. }
  315. static int pulse_open()
  316. {
  317. ENTER(__FUNCTION__);
  318. pa_sample_spec ss;
  319. pa_operation *o = NULL;
  320. int success;
  321. int ret = PULSE_ERROR;
  322. assert(!mainloop);
  323. assert(!context);
  324. assert(!stream);
  325. assert(!connected);
  326. pthread_mutex_init( &pulse_mutex, (const pthread_mutexattr_t *)NULL);
  327. ss.format = ESPEAK_FORMAT;
  328. ss.rate = wave_samplerate;
  329. ss.channels = ESPEAK_CHANNEL;
  330. if (!pa_sample_spec_valid(&ss))
  331. return false;
  332. SHOW_TIME("pa_threaded_mainloop_new (call)");
  333. if (!(mainloop = pa_threaded_mainloop_new())) {
  334. SHOW("Failed to allocate main loop\n","");
  335. goto fail;
  336. }
  337. pa_threaded_mainloop_lock(mainloop);
  338. SHOW_TIME("pa_context_new (call)");
  339. if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "eSpeak"))) {
  340. SHOW("Failed to allocate context\n","");
  341. goto unlock_and_fail;
  342. }
  343. pa_context_set_state_callback(context, context_state_cb, NULL);
  344. pa_context_set_subscribe_callback(context, subscribe_cb, NULL);
  345. SHOW_TIME("pa_context_connect (call)");
  346. if (pa_context_connect(context, NULL, (pa_context_flags_t)0, NULL) < 0) {
  347. SHOW("Failed to connect to server: %s", pa_strerror(pa_context_errno(context)));
  348. ret = PULSE_NO_CONNECTION;
  349. goto unlock_and_fail;
  350. }
  351. SHOW_TIME("pa_threaded_mainloop_start (call)");
  352. if (pa_threaded_mainloop_start(mainloop) < 0) {
  353. SHOW("Failed to start main loop","");
  354. goto unlock_and_fail;
  355. }
  356. /* Wait until the context is ready */
  357. SHOW_TIME("pa_threaded_mainloop_wait");
  358. pa_threaded_mainloop_wait(mainloop);
  359. if (pa_context_get_state(context) != PA_CONTEXT_READY) {
  360. SHOW("Failed to connect to server: %s", pa_strerror(pa_context_errno(context)));
  361. ret = PULSE_NO_CONNECTION;
  362. if (mainloop)
  363. pa_threaded_mainloop_stop(mainloop);
  364. goto unlock_and_fail;
  365. }
  366. SHOW_TIME("pa_stream_new");
  367. if (!(stream = pa_stream_new(context, "unknown", &ss, NULL))) {
  368. SHOW("Failed to create stream: %s", pa_strerror(pa_context_errno(context)));
  369. goto unlock_and_fail;
  370. }
  371. pa_stream_set_state_callback(stream, stream_state_cb, NULL);
  372. pa_stream_set_write_callback(stream, stream_request_cb, NULL);
  373. pa_stream_set_latency_update_callback(stream, stream_latency_update_cb, NULL);
  374. pa_buffer_attr a_attr;
  375. a_attr.maxlength = MAXLENGTH;
  376. a_attr.tlength = TLENGTH;
  377. a_attr.prebuf = PREBUF;
  378. a_attr.minreq = MINREQ;
  379. a_attr.fragsize = 0;
  380. SHOW_TIME("pa_connect_playback");
  381. if (pa_stream_connect_playback(stream, NULL, &a_attr, (pa_stream_flags_t)(PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE), NULL, NULL) < 0) {
  382. SHOW("Failed to connect stream: %s", pa_strerror(pa_context_errno(context)));
  383. goto unlock_and_fail;
  384. }
  385. /* Wait until the stream is ready */
  386. SHOW_TIME("pa_threaded_mainloop_wait");
  387. pa_threaded_mainloop_wait(mainloop);
  388. if (pa_stream_get_state(stream) != PA_STREAM_READY) {
  389. SHOW("Failed to connect stream: %s", pa_strerror(pa_context_errno(context)));
  390. goto unlock_and_fail;
  391. }
  392. /* Now subscribe to events */
  393. SHOW_TIME("pa_context_subscribe");
  394. if (!(o = pa_context_subscribe(context, PA_SUBSCRIPTION_MASK_SINK_INPUT, context_success_cb, &success))) {
  395. SHOW("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context)));
  396. goto unlock_and_fail;
  397. }
  398. success = 0;
  399. SHOW_TIME("pa_threaded_mainloop_wait");
  400. while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
  401. CHECK_DEAD_GOTO(fail, 1);
  402. pa_threaded_mainloop_wait(mainloop);
  403. }
  404. pa_operation_unref(o);
  405. if (!success) {
  406. SHOW("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context)));
  407. goto unlock_and_fail;
  408. }
  409. do_trigger = 0;
  410. written = 0;
  411. time_offset_msec = 0;
  412. just_flushed = 0;
  413. connected = 1;
  414. pa_threaded_mainloop_unlock(mainloop);
  415. SHOW_TIME("pulse_open (ret true)");
  416. return PULSE_OK;
  417. unlock_and_fail:
  418. if (o)
  419. pa_operation_unref(o);
  420. pa_threaded_mainloop_unlock(mainloop);
  421. fail:
  422. if (ret == PULSE_NO_CONNECTION) {
  423. if (context) {
  424. SHOW_TIME("pa_context_disconnect (call)");
  425. pa_context_disconnect(context);
  426. pa_context_unref(context);
  427. context = NULL;
  428. }
  429. if (mainloop) {
  430. SHOW_TIME("pa_threaded_mainloop_free (call)");
  431. pa_threaded_mainloop_free(mainloop);
  432. mainloop = NULL;
  433. }
  434. }
  435. else {
  436. pulse_close();
  437. }
  438. SHOW_TIME("pulse_open (ret false)");
  439. return ret;
  440. }
  441. void wave_flush(void* theHandler)
  442. {
  443. ENTER("wave_flush");
  444. }
  445. void wave_set_callback_is_output_enabled(t_wave_callback* cb)
  446. {
  447. my_callback_is_output_enabled = cb;
  448. }
  449. int wave_init(int srate)
  450. {
  451. ENTER("wave_init");
  452. stream = NULL;
  453. wave_samplerate = srate;
  454. return pulse_open() == PULSE_OK;
  455. }
  456. void* wave_open(const char* the_api)
  457. {
  458. ENTER("wave_open");
  459. return((void*)1);
  460. }
  461. size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize)
  462. {
  463. ENTER("wave_write");
  464. size_t bytes_to_write = theSize;
  465. char* aBuffer=theMono16BitsWaveBuffer;
  466. assert(stream);
  467. size_t aTotalFreeMem=0;
  468. pthread_mutex_lock(&pulse_mutex);
  469. while (1)
  470. {
  471. if (my_callback_is_output_enabled
  472. && (0==my_callback_is_output_enabled()))
  473. {
  474. SHOW_TIME("wave_write > my_callback_is_output_enabled: no!");
  475. theSize=0;
  476. goto terminate;
  477. }
  478. aTotalFreeMem = pulse_free();
  479. if (aTotalFreeMem >= bytes_to_write)
  480. {
  481. SHOW("wave_write > aTotalFreeMem(%d) >= bytes_to_write(%d)\n", aTotalFreeMem, bytes_to_write);
  482. break;
  483. }
  484. // TBD: check if really helpful
  485. if (aTotalFreeMem >= MAXLENGTH*2)
  486. {
  487. aTotalFreeMem = MAXLENGTH*2;
  488. }
  489. SHOW("wave_write > wait: aTotalFreeMem(%d) < bytes_to_write(%d)\n", aTotalFreeMem, bytes_to_write);
  490. // 500: threshold for avoiding too many calls to pulse_write
  491. if (aTotalFreeMem>500)
  492. {
  493. pulse_write(aBuffer, aTotalFreeMem);
  494. bytes_to_write -= aTotalFreeMem;
  495. aBuffer += aTotalFreeMem;
  496. }
  497. usleep(10000);
  498. }
  499. pulse_write(aBuffer, bytes_to_write);
  500. terminate:
  501. pthread_mutex_unlock(&pulse_mutex);
  502. SHOW("wave_write: theSize=%d", theSize);
  503. SHOW_TIME("wave_write > LEAVE");
  504. return theSize;
  505. }
  506. int wave_close(void* theHandler)
  507. {
  508. SHOW_TIME("wave_close > ENTER");
  509. static int aStopStreamCount = 0;
  510. // Avoid race condition by making sure this function only
  511. // gets called once at a time
  512. aStopStreamCount++;
  513. if (aStopStreamCount != 1)
  514. {
  515. SHOW_TIME("wave_close > LEAVE (stopStreamCount)");
  516. return 0;
  517. }
  518. int a_status = pthread_mutex_lock(&pulse_mutex);
  519. if (a_status)
  520. {
  521. SHOW("Error: pulse_mutex lock=%d (%s)\n", a_status, __FUNCTION__);
  522. aStopStreamCount = 0; // last action
  523. return PULSE_ERROR;
  524. }
  525. drain();
  526. pthread_mutex_unlock(&pulse_mutex);
  527. SHOW_TIME("wave_close (ret)");
  528. aStopStreamCount = 0; // last action
  529. return PULSE_OK;
  530. }
  531. int wave_is_busy(void* theHandler)
  532. {
  533. SHOW_TIME("wave_is_busy");
  534. pa_timing_info a_timing_info;
  535. int active = pulse_playing(&a_timing_info);
  536. SHOW("wave_is_busy: %d\n",active);
  537. return active;
  538. }
  539. void wave_terminate()
  540. {
  541. ENTER("wave_terminate");
  542. int a_status;
  543. pthread_mutex_t* a_mutex = NULL;
  544. a_mutex = &pulse_mutex;
  545. a_status = pthread_mutex_lock(a_mutex);
  546. pulse_close();
  547. SHOW_TIME("unlock mutex");
  548. a_status = pthread_mutex_unlock(a_mutex);
  549. pthread_mutex_destroy(a_mutex);
  550. }
  551. uint32_t wave_get_read_position(void* theHandler)
  552. {
  553. pa_timing_info a_timing_info;
  554. pulse_playing(&a_timing_info);
  555. SHOW("wave_get_read_position > %lx\n", a_timing_info.read_index);
  556. return a_timing_info.read_index;
  557. }
  558. uint32_t wave_get_write_position(void* theHandler)
  559. {
  560. pa_timing_info a_timing_info;
  561. pulse_playing(&a_timing_info);
  562. SHOW("wave_get_read_position > %lx\n", a_timing_info.write_index);
  563. return a_timing_info.write_index;
  564. }
  565. int wave_get_remaining_time(uint32_t sample, uint32_t* time)
  566. {
  567. double a_time=0;
  568. if (!time || !stream)
  569. {
  570. SHOW("event get_remaining_time> %s\n","audio device not available");
  571. return -1;
  572. }
  573. pa_timing_info a_timing_info;
  574. pulse_playing(&a_timing_info);
  575. if (sample > a_timing_info.read_index)
  576. {
  577. // TBD: take in account time suplied by portaudio V18 API
  578. a_time = sample - a_timing_info.read_index;
  579. a_time = 0.5 + (a_time * 1000.0) / wave_samplerate;
  580. }
  581. else
  582. {
  583. a_time = 0;
  584. }
  585. SHOW("wave_get_remaining_time > sample=%d, time=%d\n", sample, (uint32_t)a_time);
  586. *time = (uint32_t)a_time;
  587. return 0;
  588. }
  589. void *wave_test_get_write_buffer()
  590. {
  591. return NULL;
  592. }
  593. #else
  594. int wave_init(return 1; ) {
  595. }
  596. void* wave_open(const char* the_api) {
  597. return (void *)1;
  598. }
  599. size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) {
  600. return theSize;
  601. }
  602. int wave_close(void* theHandler) {
  603. return 0;
  604. }
  605. int wave_is_busy(void* theHandler) {
  606. return 0;
  607. }
  608. void wave_terminate() {
  609. }
  610. uint32_t wave_get_read_position(void* theHandler) {
  611. return 0;
  612. }
  613. uint32_t wave_get_write_position(void* theHandler) {
  614. return 0;
  615. }
  616. void wave_flush(void* theHandler) {
  617. }
  618. typedef int (t_wave_callback)(void);
  619. void wave_set_callback_is_output_enabled(t_wave_callback* cb) {
  620. }
  621. extern void* wave_test_get_write_buffer() {
  622. return NULL;
  623. }
  624. int wave_get_remaining_time(uint32_t sample, uint32_t* time)
  625. {
  626. if (!time) return(-1);
  627. *time = (uint32_t)0;
  628. return 0;
  629. }
  630. #endif // of USE_PULSEAUDIO
  631. #ifndef USE_PORTAUDIO
  632. void clock_gettime2(struct timespec *ts)
  633. {
  634. struct timeval tv;
  635. if (!ts)
  636. {
  637. return;
  638. }
  639. assert (gettimeofday(&tv, NULL) != -1);
  640. ts->tv_sec = tv.tv_sec;
  641. ts->tv_nsec = tv.tv_usec*1000;
  642. }
  643. void add_time_in_ms(struct timespec *ts, int time_in_ms)
  644. {
  645. if (!ts)
  646. {
  647. return;
  648. }
  649. uint64_t t_ns = (uint64_t)ts->tv_nsec + 1000000 * (uint64_t)time_in_ms;
  650. while(t_ns >= ONE_BILLION)
  651. {
  652. SHOW("event > add_time_in_ms ns: %d sec %Lu nsec \n", ts->tv_sec, t_ns);
  653. ts->tv_sec += 1;
  654. t_ns -= ONE_BILLION;
  655. }
  656. ts->tv_nsec = (long int)t_ns;
  657. }
  658. #endif // ifndef USE_PORTAUDIO
  659. #endif // USE_ASYNC