7 #ifdef HAVE_PULSE_AUDIO
13 #define afile mainw->files[pulsed->playing_file]
17 #define THRESH_BASE 10000.
18 #define THRESH_MAX 50000.
20 static pulse_driver_t pulsed;
21 static pulse_driver_t pulsed_reader;
23 static pa_threaded_mainloop *pa_mloop = NULL;
24 static pa_context *pcon = NULL;
25 static char pactxnm[512];
27 static uint32_t pulse_server_rate = 0;
29 #define PULSE_READ_BYTES 48000
31 static uint8_t prbuf[PULSE_READ_BYTES * 2];
33 static size_t prb = 0;
35 static boolean seek_err;
36 static boolean sync_ready =
FALSE;
38 static volatile int lock_count = 0;
40 static off_t fwd_seek_pos = 0;
46 if (!pa_threaded_mainloop_in_thread(pa_mloop)) {
47 pa_threaded_mainloop_lock(pa_mloop);
50 LIVES_ERROR(
"tried to lock pa mainloop within audio thread");
55 if (!pa_threaded_mainloop_in_thread(pa_mloop)) {
58 pa_threaded_mainloop_unlock(pa_mloop);
61 LIVES_ERROR(
"tried to unlock pa mainloop within audio thread");
66 static void pulse_server_cb(pa_context *c,
const pa_server_info *info,
void *userdata) {
67 if (!info) pulse_server_rate = 0;
68 else pulse_server_rate = info->sample_spec.rate;
69 pa_threaded_mainloop_signal(pa_mloop, 0);
72 static void pulse_success_cb(pa_stream *stream,
int i,
void *userdata) {pa_threaded_mainloop_signal(pa_mloop, 0);}
75 #include <sys/resource.h>
77 static void stream_underflow_callback(pa_stream *s,
void *userdata) {
84 fprintf(stderr,
"PA Stream underrun.\n");
91 static void stream_overflow_callback(pa_stream *s,
void *userdata) {
94 fprintf(stderr,
"Stream overrun.\n");
95 paop = pa_stream_flush(s, NULL, NULL);
96 pa_operation_unref(paop);
101 static void stream_moved_callback(pa_stream *s,
void *userdata) {
103 fprintf(stderr,
"Stream moved. \n");
107 static void stream_buffer_attr_callback(pa_stream *s,
void *userdata) {
112 boolean lives_pulse_init(
short startup_phase) {
115 pa_context_state_t pa_state;
118 LiVESResponseType resp;
119 boolean retried =
FALSE;
121 if (pa_mloop)
return TRUE;
125 pa_mloop = pa_threaded_mainloop_new();
127 pcon = pa_context_new(pa_threaded_mainloop_get_api(pa_mloop), pactxnm);
128 pa_context_connect(pcon, NULL, (pa_context_flags_t)0, NULL);
129 pa_threaded_mainloop_start(pa_mloop);
131 pa_state = pa_context_get_state(pcon);
134 while ((timeout =
lives_alarm_check(alarm_handle)) > 0 && pa_state != PA_CONTEXT_READY) {
137 pa_state = pa_context_get_state(pcon);
141 if (pa_context_get_state(pcon) == PA_CONTEXT_READY) timeout = 1;
144 pa_context_unref(pcon);
151 LIVES_WARN(
"Unable to connect to the pulseaudio server");
154 if (startup_phase != 2) {
156 _(
"\nUnable to connect to the pulseaudio server.\n"
157 "Click Abort to exit from LiVES, Retry to try again,\n"
158 "or Cancel to run LiVES without audio features.\n"
159 "Audio settings can be updated in Tools/Preferences/Playback.\n"));
160 if (resp == LIVES_RESPONSE_RETRY) {
161 fprintf(stderr,
"Retrying...\n");
164 fprintf(stderr,
"Giving up.\n");
167 msg = (
_(
"\nUnable to connect to the pulseaudio server.\n"));
168 if (startup_phase != 2) {
172 do_error_dialogf(
"%s%s", msg,
_(
"LiVES will exit and you can choose another audio player.\n"));
183 void pulse_get_rec_avals(pulse_driver_t *pulsed) {
186 mainw->
rec_aseek = fabs((
double)(fwd_seek_pos / (
double)(afile->achans * afile->asampsize / 8)) / (
double)afile->arps)
188 mainw->
rec_avel = fabs((
double)pulsed->in_arate / (
double)afile->arps) * (double)afile->adirection;
194 static void pulse_set_rec_avals(pulse_driver_t *pulsed) {
198 pulse_get_rec_avals(pulsed);
203 LIVES_GLOBAL_INLINE size_t pulse_get_buffsize(pulse_driver_t *pulsed) {
return pulsed->chunk_size;}
205 #if !HAVE_PA_STREAM_BEGIN_WRITE
206 static void pulse_buff_free(
void *ptr) {
lives_free(ptr);}
209 static void sync_ready_ok(pulse_driver_t *pulsed,
size_t nbytes) {
210 if (nbytes >= 8192) {
211 mainw->
syncticks += ((double)nbytes / (
double)(pulsed->out_arate) * 1000000.
212 / (
double)(pulsed->out_achans * pulsed->out_asamps >> 3) + .5) *
USEC_TO_TICKS;
225 static void sample_silence_pulse(pulse_driver_t *pulsed,
size_t nbytes,
size_t xbytes) {
229 if (sync_ready) sync_ready_ok(pulsed, xbytes > 0 ? xbytes : 0);
231 if (xbytes <= 0)
return;
235 #if HAVE_PA_STREAM_BEGIN_WRITE
238 pa_stream_begin_write(pulsed->pstream, (
void **)&buff, &xbytes);
240 if (nbytes < xbytes) xbytes = nbytes;
241 #if !HAVE_PA_STREAM_BEGIN_WRITE
244 if (!buff || ret != 0)
return;
246 #if HAVE_PA_STREAM_BEGIN_WRITE
249 if (pulsed->astream_fd != -1)
audio_stream(buff, xbytes, pulsed->astream_fd);
251 nsamples = xbytes / pulsed->out_achans / (pulsed->out_asamps >> 3);
266 #if !HAVE_PA_STREAM_BEGIN_WRITE
267 pa_stream_write(pulsed->pstream, buff, xbytes, pulse_buff_free, 0, PA_SEEK_RELATIVE);
269 pa_stream_write(pulsed->pstream, buff, xbytes, NULL, 0, PA_SEEK_RELATIVE);
272 if (!pulsed->is_paused) pulsed->frames_written += nsamples;
273 pulsed->extrausec += ((double)xbytes / (
double)(pulsed->out_arate) * 1000000.
274 / (
double)(pulsed->out_achans * pulsed->out_asamps >> 3) + .5);
276 pulsed->real_seek_pos = pulsed->seek_pos;
277 if (
IS_VALID_CLIP(pulsed->playing_file) && pulsed->seek_pos < afile->afilesize)
278 afile->aseek_pos = pulsed->seek_pos;
282 #define NBYTES_LIMIT (65536 * 4)
284 static short *shortbuffer = NULL;
311 static void pulse_audio_write_process(pa_stream *pstream,
size_t nbytes,
void *arg) {
312 pulse_driver_t *pulsed = (pulse_driver_t *)arg;
315 ssize_t pad_bytes = 0;
317 uint64_t nsamples = nbytes / pulsed->out_achans / (pulsed->out_asamps >> 3);
319 size_t xbytes = pa_stream_writable_size(pstream);
324 boolean got_cmd =
FALSE;
325 boolean from_memory =
FALSE;
326 boolean needs_free =
FALSE;
334 pulsed->real_seek_pos = pulsed->seek_pos;
335 pulsed->pstream = pstream;
337 if (xbytes > nbytes) xbytes = nbytes;
340 sample_silence_pulse(pulsed, nsamples * pulsed->out_achans * (pulsed->out_asamps >> 3), xbytes);
350 pulsed->in_use =
TRUE;
351 paop = pa_stream_flush(pulsed->pstream, NULL, NULL);
352 pa_operation_unref(paop);
353 new_file = atoi((
char *)msg->
data);
354 if (pulsed->playing_file != new_file) {
357 if (pulsed->fd == -1) {
361 pulsed->playing_file = -1;
365 pulsed->real_seek_pos = pulsed->seek_pos = 0;
366 pulsed->playing_file = new_file;
370 pulsed->in_use =
TRUE;
371 paop = pa_stream_flush(pulsed->pstream, NULL, NULL);
372 pa_operation_unref(paop);
374 if (pulsed->sound_buffer == pulsed->aPlayPtr->data) pulsed->sound_buffer = NULL;
375 if (pulsed->aPlayPtr->data) {
377 pulsed->aPlayPtr->data = NULL;
379 pulsed->aPlayPtr->max_size = pulsed->aPlayPtr->size = 0;
380 pulsed->fd = pulsed->playing_file = -1;
381 pulsed->in_use =
FALSE;
382 pulsed->seek_pos = pulsed->real_seek_pos = fwd_seek_pos = 0;
385 if (pulsed->fd < 0)
break;
386 pulsed->in_use =
TRUE;
387 paop = pa_stream_flush(pulsed->pstream, NULL, NULL);
388 pa_operation_unref(paop);
389 xseek = seek = atol((
char *)msg->
data);
400 if (seek < 0.) xseek = 0.;
401 xseek =
ALIGN_CEIL64(xseek, afile->achans * (afile->asampsize >> 3));
403 pulsed->real_seek_pos = pulsed->seek_pos = afile->aseek_pos = xseek;
416 pulsed->msgq = msg->
next;
417 if (pulsed->msgq && pulsed->msgq->next == pulsed->msgq) pulsed->msgq->next = NULL;
420 sample_silence_pulse(pulsed, nsamples * pulsed->out_achans * (pulsed->out_asamps >> 3), xbytes);
425 fwd_seek_pos = pulsed->real_seek_pos;
427 if (pulsed->chunk_size != nbytes) pulsed->chunk_size = nbytes;
429 pulsed->state = pa_stream_get_state(pulsed->pstream);
431 if (pulsed->state == PA_STREAM_READY) {
432 uint64_t pulseFramesAvailable = nsamples;
433 uint64_t inputFramesAvailable = 0;
434 uint64_t numFramesToWrite = 0;
435 double in_framesd = 0.;
438 int64_t in_frames = 0;
440 size_t in_bytes = 0, xin_bytes = 0;
442 float shrink_factor = 1.f;
446 if (
IS_VALID_CLIP(pulsed->playing_file)) qnt = afile->achans * (afile->asampsize >> 3);
449 lives_printerr(
"playing... pulseFramesAvailable = %ld\n", pulseFramesAvailable);
456 || ((((pulsed->fd < 0 || pulsed->seek_pos < 0 ||
461 if (pulsed->seek_pos < 0 &&
IS_VALID_CLIP(pulsed->playing_file) && pulsed->in_arate > 0) {
462 pulsed->seek_pos += (double)(pulsed->in_arate / pulsed->out_arate) * nsamples * qnt;
464 if (pulsed->seek_pos > 0) {
465 pad_bytes = -pulsed->real_seek_pos;
466 pulsed->real_seek_pos = pulsed->seek_pos = 0;
471 && pulsed->seek_pos > afile->afilesize && pulsed->in_arate < 0) {
472 pulsed->seek_pos += (pulsed->in_arate / pulsed->out_arate) * nsamples * pulsed->in_achans * pulsed->in_asamps / 8;
473 pulsed->seek_pos =
ALIGN_CEIL64(pulsed->seek_pos - qnt, qnt);
474 if (pulsed->seek_pos < afile->afilesize) {
475 pad_bytes = (afile->afilesize - pulsed->real_seek_pos);
476 pulsed->real_seek_pos = pulsed->seek_pos = afile->afilesize;
480 g_print(
"pt a3 %d\n", pulsed->in_use);
484 sample_silence_pulse(pulsed, nsamples * pulsed->out_achans * pulsed->out_asamps >> 3, xbytes);
498 int64_t xusec = pulsed->extrausec;
499 sample_silence_pulse(pulsed, nsamples * pulsed->out_achans * pulsed->out_asamps >> 3, xbytes);
501 fwd_seek_pos = pulsed->real_seek_pos = pulsed->seek_pos;
502 pulsed->usec_start += (pulsed->extrausec - xusec);
503 pulsed->extrausec = xusec;
508 dqnt = (double)afile->achans * afile->asampsize / 8.;
509 qnt = afile->achans * (afile->asampsize >> 3);
514 rnd_frame = (
frames_t)((
double)pulsed->seek_pos / (double)afile->arate / dqnt * afile->fps
520 rnd_samp = (int64_t)((
double)(rnd_frame + .00001) / afile->fps * (double)afile->arate + .5);
521 pulsed->seek_pos = (ssize_t)(rnd_samp * qnt);
526 fwd_seek_pos = pulsed->real_seek_pos = pulsed->seek_pos;
534 shrink_factor = (float)pulsed->in_arate / (
float)pulsed->out_arate /
mainw->
audio_stretch;
535 in_framesd = fabs((
double)shrink_factor * (
double)pulseFramesAvailable);
538 in_bytes = (size_t)(in_framesd * pulsed->in_achans * (pulsed->in_asamps >> 3));
548 if (LIVES_LIKELY(pulseFramesAvailable > 0 && (pulsed->read_abuf > -1
549 || (pulsed->aPlayPtr && pulsed->in_achans > 0) ||
556 numFramesToWrite = pulseFramesAvailable;
559 if (LIVES_LIKELY(pulsed->fd >= 0)) {
561 pulsed->seek_end = 0;
564 pulsed->seek_end = (int64_t)((
double)(afile->end - 1.) / afile->fps * afile->arps) * afile->achans
565 * (afile->asampsize / 8);
566 if (pulsed->seek_end > afile->afilesize) pulsed->seek_end = afile->afilesize;
569 * afile->achans * (afile->asampsize / 8);
570 else pulsed->seek_end = afile->afilesize;
572 if (pulsed->seek_end > afile->afilesize) pulsed->seek_end = afile->afilesize;
578 pulsed->aPlayPtr->size = 0;
580 shrink_factor = (float)pulsed->in_arate / (
float)pulsed->out_arate /
mainw->
audio_stretch;
581 in_framesd = fabs((
double)shrink_factor * (
double)pulseFramesAvailable);
584 in_bytes = (int)(in_framesd + ((
double)
fastrand() / (
double)LIVES_MAXUINT64))
585 * pulsed->in_achans * (pulsed->in_asamps >> 3);
588 in_frames = in_bytes / pulsed->in_achans * (pulsed->in_asamps >> 3);
589 g_print(
"in bytes=%ld %d %d %lu %lu %lu\n", in_bytes, pulsed->in_arate, pulsed->out_arate, pulseFramesAvailable,
590 pulsed->in_achans, pulsed->in_asamps);
594 if (LIVES_UNLIKELY((in_bytes > pulsed->aPlayPtr->max_size && !(*pulsed->cancelled) && fabsf(shrink_factor) <= 100.f))) {
595 boolean update_sbuffer =
FALSE;
596 if (pulsed->sound_buffer == pulsed->aPlayPtr->data) update_sbuffer =
TRUE;
597 if (pulsed->aPlayPtr->data)
lives_free((
void *)(pulsed->aPlayPtr->data));
599 if (update_sbuffer) pulsed->sound_buffer = (
void *)(pulsed->aPlayPtr->data);
600 if (pulsed->aPlayPtr->data) pulsed->aPlayPtr->max_size = in_bytes;
601 else pulsed->aPlayPtr->max_size = 0;
617 pulsed->aPlayPtr->size = 0;
619 if (shrink_factor > 0.) {
623 if (pad_bytes < 0) pad_bytes = 0;
625 pad_bytes *= shrink_factor;
628 if (pad_bytes)
lives_memset((
void *)pulsed->aPlayPtr->data, 0, pad_bytes);
629 pulsed->aPlayPtr->size =
lives_read_buffered(pulsed->fd, (
void *)(pulsed->aPlayPtr->data + pad_bytes),
630 in_bytes - pad_bytes,
TRUE) + pad_bytes;
631 }
else pulsed->aPlayPtr->size = in_bytes;
632 pulsed->sound_buffer = (
void *)(pulsed->aPlayPtr->data);
633 pulsed->seek_pos += in_bytes - pad_bytes;
634 if (pulsed->seek_pos >= pulsed->seek_end && !afile->opening) {
635 ssize_t rem = pulsed->seek_end - pulsed->real_seek_pos;
636 if (pulsed->aPlayPtr->size + rem > in_bytes) rem = in_bytes - pulsed->aPlayPtr->size;
639 + pulsed->aPlayPtr->size,
640 pulsed->seek_end - pulsed->real_seek_pos,
TRUE);
645 pulsed->in_use =
FALSE;
648 pulsed->in_arate = -pulsed->in_arate;
649 afile->adirection = -afile->adirection;
652 pulsed->seek_pos = pulsed->seek_end;
653 pulsed->seek_pos =
ALIGN_CEIL64(pulsed->seek_pos - qnt, qnt);
654 pulsed->real_seek_pos = pulsed->seek_pos;
658 pulsed->seek_pos = (int64_t)((
double)(afile->start - 1.) / afile->fps * afile->arps)
659 * afile->achans * (afile->asampsize / 8);
660 pulsed->real_seek_pos = pulsed->seek_pos =
ALIGN_CEIL64(pulsed->seek_pos, qnt);
661 }
else pulsed->seek_pos = 0;
662 if (pulsed->seek_pos == pulsed->seek_end)
break;
664 if (pulsed->aPlayPtr->size < in_bytes) {
666 + pulsed->aPlayPtr->size, in_bytes - pulsed->aPlayPtr->size,
TRUE);
670 if (pulsed->aPlayPtr->size < in_bytes) {
671 pad_bytes = in_bytes - pulsed->aPlayPtr->size;
673 lives_memset((
void *)pulsed->aPlayPtr->data + in_bytes - pad_bytes, 0, pad_bytes);
674 pulsed->aPlayPtr->size = in_bytes;
678 pulsed->seek_pos =
ALIGN_CEIL64(pulsed->seek_pos - qnt, qnt);
679 fwd_seek_pos = pulsed->real_seek_pos = pulsed->seek_pos;
684 else if (pulsed->playing_file !=
mainw->
ascrap_file && shrink_factor < 0.f) {
687 (int64_t)((
double)(afile->start - 1.) / afile->fps * afile->arps)
688 * afile->achans * (afile->asampsize / 8) : 0);
690 if (pad_bytes > 0) pad_bytes = 0;
693 pad_bytes *= shrink_factor;
696 lives_memset((
void *)pulsed->aPlayPtr->data + in_bytes - pad_bytes, 0, pad_bytes);
700 if ((pulsed->seek_pos -= (in_bytes - pad_bytes)) < seek_start) {
712 (
void *)(pulsed->aPlayPtr->data) + in_bytes - pad_bytes -
713 (pulsed->real_seek_pos - pulsed->seek_pos),
714 pulsed->real_seek_pos - pulsed->seek_pos,
TRUE);
715 if (pulsed->aPlayPtr->size < pulsed->real_seek_pos - seek_start) {
717 lives_memmove((
void *)pulsed->aPlayPtr->data + in_bytes - pad_bytes - pulsed->aPlayPtr->size,
718 (
void *)(pulsed->aPlayPtr->data) + in_bytes - pad_bytes -
719 (pulsed->real_seek_pos - seek_start), pulsed->aPlayPtr->size);
723 pulsed->aPlayPtr->size += pad_bytes;
728 pulsed->in_arate = -pulsed->in_arate;
729 afile->adirection = -afile->adirection;
730 pulsed->seek_pos = seek_start;
732 pulsed->seek_pos = pulsed->seek_end - pulsed->aPlayPtr->size;
735 pulsed->seek_pos =
ALIGN_CEIL64(pulsed->seek_pos - qnt, qnt);
736 fwd_seek_pos = pulsed->real_seek_pos = pulsed->seek_pos;
748 if (pulsed->aPlayPtr->size < in_bytes) {
749 pulsed->real_seek_pos = pulsed->seek_pos =
ALIGN_CEIL64(pulsed->seek_pos, qnt);
751 pulsed->aPlayPtr->size
753 + pulsed->aPlayPtr->size,
754 in_bytes - pulsed->aPlayPtr->size,
TRUE);
759 if (pulsed->aPlayPtr->size < in_bytes) {
762 if (pulsed->in_arate > 0) {
763 pad_with_silence(-1, (
void *)pulsed->aPlayPtr->data, pulsed->aPlayPtr->size, in_bytes,
767 lives_memmove((
void *)pulsed->aPlayPtr->data + (in_bytes - pulsed->aPlayPtr->size), (
void *)pulsed->aPlayPtr->data,
768 pulsed->aPlayPtr->size);
769 pad_with_silence(-1, (
void *)pulsed->aPlayPtr->data, 0, in_bytes - pulsed->aPlayPtr->size,
777 if (pulsed->mute || in_bytes == 0 || pulsed->aPlayPtr->size == 0 || !
IS_VALID_CLIP(pulsed->playing_file)
780 sample_silence_pulse(pulsed, nsamples * pulsed->out_achans * (pulsed->out_asamps >> 3), xbytes);
788 in_bytes = pulseFramesAvailable * pulsed->out_achans * 2;
789 if (xin_bytes == 0) xin_bytes = in_bytes;
797 inputFramesAvailable = pulsed->aPlayPtr->size / (pulsed->in_achans * (pulsed->in_asamps >> 3));
799 lives_printerr(
"%ld inputFramesAvailable == %ld, %ld, %d %d,pulseFramesAvailable == %lu\n", pulsed->aPlayPtr->size,
800 inputFramesAvailable,
801 in_frames, pulsed->in_arate, pulsed->out_arate, pulseFramesAvailable);
805 buffer = (uint8_t *)pulsed->aPlayPtr->data;
807 numFramesToWrite = MIN(pulseFramesAvailable, (inputFramesAvailable / fabsf(shrink_factor) + .001));
810 lives_printerr(
"inputFramesAvailable after conversion %ld\n", (uint64_t)((
double)inputFramesAvailable
811 / shrink_factor + .001));
812 lives_printerr(
"nsamples == %ld, pulseFramesAvailable == %ld,\n\tpulsed->num_input_channels == %ld, "
813 "pulsed->out_achans == %ld\n",
815 pulseFramesAvailable, pulsed->in_achans, pulsed->out_achans);
819 if (pulsed->in_asamps == pulsed->out_asamps && shrink_factor == 1. && pulsed->in_achans == pulsed->out_achans &&
820 !pulsed->reverse_endian && !swap_sign) {
822 pulsed->sound_buffer = buffer;
824 if (pulsed->sound_buffer != pulsed->aPlayPtr->data)
lives_freep((
void **)&pulsed->sound_buffer);
828 if (!pulsed->sound_buffer) {
829 sample_silence_pulse(pulsed, nsamples * pulsed->out_achans * (pulsed->out_asamps >> 3), xbytes);
838 if (in_bytes > in_framesd * pulsed->in_achans * (pulsed->in_asamps >> 3) && !((uint64_t)in_framesd & 1))
839 in_bytes -= pulsed->in_achans * (pulsed->in_asamps >> 3);
843 if (pulsed->in_asamps == 8) {
844 sample_move_d8_d16((
short *)(pulsed->sound_buffer), (uint8_t *)buffer, nsamples, in_bytes,
845 shrink_factor, pulsed->out_achans, pulsed->in_achans, swap_sign ?
SWAP_U_TO_S : 0);
847 sample_move_d16_d16((
short *)pulsed->sound_buffer, (
short *)buffer, nsamples, in_bytes, shrink_factor,
848 pulsed->out_achans, pulsed->in_achans, pulsed->reverse_endian ?
SWAP_X_TO_L : 0,
854 boolean memok =
TRUE;
855 float **fltbuf = (
float **)
lives_calloc(pulsed->out_achans,
sizeof(
float *));
858 for (i = 0; i < pulsed->out_achans; i++) {
863 for (--i; i >= 0; i--) {
871 nsamples, pulsed->out_achans,
FALSE,
FALSE, 1.0);
900 sample_move_float_int(pulsed->sound_buffer, fltbuf, nsamples, 1.0, pulsed->out_achans, PA_SAMPSIZE, 0,
903 for (i = 0; i < pulsed->out_achans; i++) {
912 float **fltbuf = NULL;
913 boolean pl_error =
FALSE;
915 numFramesToWrite = pulseFramesAvailable;
919 fltbuf = (
float **)
lives_malloc(pulsed->out_achans *
sizeof(
float *));
920 for (
int i = 0; i < pulsed->out_achans; i++) fltbuf[i] =
928 if (LIVES_UNLIKELY(nbytes > pulsed->aPlayPtr->max_size)) {
929 boolean update_sbuffer =
FALSE;
930 if (pulsed->sound_buffer == pulsed->aPlayPtr->data) update_sbuffer =
TRUE;
931 if (pulsed->aPlayPtr->data)
lives_free((
void *)(pulsed->aPlayPtr->data));
934 if (update_sbuffer) pulsed->sound_buffer = (
void *)(pulsed->aPlayPtr->data);
935 if (pulsed->aPlayPtr->data) {
936 pulsed->aPlayPtr->max_size = nbytes;
938 pulsed->aPlayPtr->size = pulsed->aPlayPtr->max_size = 0;
942 if (!pl_error) pulsed->aPlayPtr->size = nbytes;
946 if (pl_error) nbytes = 0;
948 boolean memok =
FALSE;
975 pulsed->sound_buffer = (uint8_t *)pulsed->aPlayPtr->data;
981 for (
register int i = 0; i < pulsed->out_achans; i++)
lives_freep((
void **)&fltbuf[i]);
996 pulsed->sound_buffer);
1002 pulseFramesAvailable -= numFramesToWrite;
1005 lives_printerr(
"pulseFramesAvailable == %ld\n", pulseFramesAvailable);
1014 pa_cvolume_set(&pulsed->volume, pulsed->out_achans, pavol);
1015 paop = pa_context_set_sink_input_volume(pulsed->con,
1016 pa_stream_get_index(pulsed->pstream), &pulsed->volume, NULL, NULL);
1017 pa_operation_unref(paop);
1025 if (sync_ready) sync_ready_ok(pulsed, nbytes);
1027 while (nbytes > 0) {
1028 if (nbytes < xbytes) xbytes = nbytes;
1031 #if !HAVE_PA_STREAM_BEGIN_WRITE
1032 if (xbytes / pulsed->out_achans / (pulsed->out_asamps >> 3) <= numFramesToWrite && offs == 0) {
1033 buffer = pulsed->sound_buffer;
1045 if (pulsed->sound_buffer) {
1046 #if HAVE_PA_STREAM_BEGIN_WRITE
1049 ret = pa_stream_begin_write(pulsed->pstream, (
void **)&buffer, &xbytes);
1050 if (nbytes < xbytes) xbytes = nbytes;
1055 if (!pulsed->sound_buffer || ret != 0 || !buffer) {
1056 sample_silence_pulse(pulsed, nsamples * pulsed->out_achans * (pulsed->out_asamps >> 3), nbytes);
1062 lives_memcpy(buffer, pulsed->sound_buffer + offs, xbytes);
1068 if (pulsed->astream_fd != -1)
audio_stream(buffer, xbytes, pulsed->astream_fd);
1075 #if !HAVE_PA_STREAM_BEGIN_WRITE
1076 pa_stream_write(pulsed->pstream, buffer, xbytes, buffer == pulsed->aPlayPtr->data ? NULL :
1077 pulse_buff_free, 0, PA_SEEK_RELATIVE);
1079 pa_stream_write(pulsed->pstream, buffer, xbytes, NULL, 0, PA_SEEK_RELATIVE);
1082 pulsed->extrausec += ((double)xbytes / (
double)(pulsed->out_arate) * 1000000.
1083 / (
double)(pulsed->out_achans * pulsed->out_asamps >> 3) + .5);
1084 pulsed->frames_written += xbytes / pulsed->out_achans / (pulsed->out_asamps >> 3);
1087 if (pulsed->read_abuf > -1 && !pulsed->mute) {
1089 #if HAVE_PA_STREAM_BEGIN_WRITE
1091 ret = pa_stream_begin_write(pulsed->pstream, (
void **)&shortbuffer, &xbytes);
1093 if (nbytes < xbytes) xbytes = nbytes;
1094 #if !HAVE_PA_STREAM_BEGIN_WRITE
1097 if (!shortbuffer || ret != 0) {
1098 sample_silence_pulse(pulsed, nsamples * pulsed->out_achans * (pulsed->out_asamps >> 3), nbytes);
1104 sample_move_abuf_int16(shortbuffer, pulsed->out_achans, (xbytes >> 1) / pulsed->out_achans, pulsed->out_arate);
1105 if (pulsed->astream_fd != -1)
audio_stream(shortbuffer, xbytes, pulsed->astream_fd);
1106 #if !HAVE_PA_STREAM_BEGIN_WRITE
1107 pa_stream_write(pulsed->pstream, shortbuffer, xbytes, pulse_buff_free, 0, PA_SEEK_RELATIVE);
1109 pa_stream_write(pulsed->pstream, shortbuffer, xbytes, NULL, 0, PA_SEEK_RELATIVE);
1112 pulsed->extrausec += ((double)xbytes / (
double)(pulsed->out_arate) * 1000000.
1113 / (
double)(pulsed->out_achans * pulsed->out_asamps >> 3) + .5);
1114 pulsed->frames_written += xbytes / pulsed->out_achans / (pulsed->out_asamps >> 3);
1116 sample_silence_pulse(pulsed, xbytes, xbytes);
1122 if (needs_free && pulsed->sound_buffer != pulsed->aPlayPtr->data && pulsed->sound_buffer) {
1126 fwd_seek_pos = pulsed->real_seek_pos = pulsed->seek_pos;
1128 if (pulseFramesAvailable) {
1130 lives_printerr(
"buffer underrun of %ld frames\n", pulseFramesAvailable);
1132 xbytes = pa_stream_writable_size(pstream);
1133 sample_silence_pulse(pulsed, pulseFramesAvailable * pulsed->out_achans * (pulsed->out_asamps >> 3), xbytes);
1134 if (!pulsed->is_paused) pulsed->frames_written += xbytes / pulsed->out_achans / (pulsed->out_asamps >> 3);
1138 if (pulsed->state == PA_STREAM_UNCONNECTED || pulsed->state == PA_STREAM_CREATING)
1139 LIVES_INFO(
"pulseaudio stream UNCONNECTED or CREATING");
1141 LIVES_WARN(
"pulseaudio stream FAILED or TERMINATED");
1145 lives_printerr(
"done\n");
1150 size_t pulse_flush_read_data(pulse_driver_t *pulsed,
int fileno,
size_t rbytes,
boolean rev_endian,
void *data) {
1154 size_t bytes_out, frames_out, bytes = 0;
1162 if (!data) data = prbuf;
1166 if (prb <= PULSE_READ_BYTES * 2) {
1167 gbuf = (
short *)data;
1170 if (!gbuf)
return 0;
1171 if (prb > rbytes)
lives_memcpy((
void *)gbuf, prbuf, prb - rbytes);
1172 lives_memcpy((
void *)gbuf + (prb - rbytes > 0 ? prb - rbytes : 0), data, rbytes);
1176 if (rbytes == 0)
return 0;
1177 if (fileno == -1)
return 0;
1178 gbuf = (
short *)data;
1184 out_scale = (float)pulsed->in_arate / (
float)ofile->
arate;
1185 }
else out_scale = 1.;
1189 frames_out = (size_t)((
double)((prb / (ofile->
asampsize >> 3) / ofile->
achans)) / out_scale);
1192 if (frames_out != pulsed->chunk_size) pulsed->chunk_size = frames_out;
1199 if (!holding_buff) {
1223 size_t target = frames_out * (ofile->
asampsize / 8) * ofile->
achans, bytes;
1242 static void pulse_audio_read_process(pa_stream * pstream,
size_t nbytes,
void *arg) {
1247 pulse_driver_t *pulsed = (pulse_driver_t *)arg;
1249 size_t frames_out, nsamples;
1251 size_t rbytes = nbytes, zbytes;
1253 pulsed->pstream = pstream;
1255 if (pulsed->is_corked)
return;
1258 pa_stream_peek(pulsed->pstream, (
const void **)&data, &rbytes);
1261 pa_stream_drop(pulsed->pstream);
1265 pulsed->extrausec += ((double)nbytes / (
double)(pulsed->out_arate) * 1000000.
1266 / (
double)(pulsed->out_achans * pulsed->out_asamps >> 3) + .5);
1270 zbytes = pa_stream_readable_size(pulsed->pstream);
1277 if (pa_stream_peek(pulsed->pstream, (
const void **)&data, &rbytes)) {
1283 pa_stream_drop(pulsed->pstream);
1292 pulsed->extrausec += ((double)rbytes / (
double)(pulsed->out_arate) * 1000000.
1293 / (
double)(pulsed->out_achans * pulsed->out_asamps >> 3) + .5);
1297 if (pulsed->playing_file == -1) {
1300 out_scale = (float)afile->arate / (
float)pulsed->in_arate;
1305 if (prb <= PULSE_READ_BYTES * 2) {
1307 pulse_flush_read_data(pulsed, pulsed->playing_file, prb, pulsed->reverse_endian, prbuf);
1309 pulse_flush_read_data(pulsed, pulsed->playing_file, rbytes, pulsed->reverse_endian, data);
1316 frames_out = (size_t)((
double)((prb / (pulsed->in_asamps >> 3) / pulsed->in_achans)) / out_scale + .5);
1318 nsamples = (size_t)((
double)((rbytes / (pulsed->in_asamps >> 3) / pulsed->in_achans)) / out_scale + .5);
1321 if (!pulsed->is_paused) {
1322 pulsed->frames_written += nsamples;
1335 boolean memok =
TRUE;
1336 float **fltbuf = (
float **)
lives_malloc(pulsed->in_achans *
sizeof(
float *));
1339 size_t xnsamples = (size_t)(rbytes / (pulsed->in_asamps >> 3) / pulsed->in_achans);
1343 pa_stream_drop(pulsed->pstream);
1347 for (i = 0; i < pulsed->in_achans; i++) {
1349 fltbuf[i] = (
float *)
lives_calloc(xnsamples,
sizeof(
float));
1352 for (--i; i >= 0; i--)
lives_free(fltbuf[i]);
1356 pulsed->abs_maxvol_heard
1384 for (i = 0; i < pulsed->in_achans; i++) {
1394 pa_stream_drop(pulsed->pstream);
1395 if (pulsed->is_paused) {
1399 pa_operation *paop = pa_stream_flush(pulsed->pstream, NULL,
1401 pa_operation_unref(paop);
1411 pulsed->seek_pos += rbytes;
1413 if (prb < PULSE_READ_BYTES && (
mainw->
rec_samples == -1 || frames_out < mainw->rec_samples)) {
1417 if (prb <= PULSE_READ_BYTES * 2) {
1419 pulse_flush_read_data(pulsed, pulsed->playing_file, prb, pulsed->reverse_endian, prbuf);
1421 pulse_flush_read_data(pulsed, pulsed->playing_file, rbytes, pulsed->reverse_endian, data);
1425 pa_stream_drop(pulsed->pstream);
1434 void pulse_shutdown(
void) {
1438 pa_context_disconnect(pcon);
1439 pa_context_unref(pcon);
1442 pa_threaded_mainloop_stop(pa_mloop);
1443 pa_threaded_mainloop_free(pa_mloop);
1450 void pulse_close_client(pulse_driver_t *pdriver) {
1451 if (pdriver->pstream) {
1453 pa_stream_disconnect(pdriver->pstream);
1454 pa_stream_set_write_callback(pdriver->pstream, NULL, NULL);
1455 pa_stream_set_read_callback(pdriver->pstream, NULL, NULL);
1456 pa_stream_set_underflow_callback(pdriver->pstream, NULL, NULL);
1457 pa_stream_set_overflow_callback(pdriver->pstream, NULL, NULL);
1458 pa_stream_unref(pdriver->pstream);
1461 if (pdriver->pa_props) pa_proplist_free(pdriver->pa_props);
1462 pdriver->pa_props = NULL;
1463 pdriver->pstream = NULL;
1467 int pulse_audio_init(
void) {
1469 pulsed.in_use =
FALSE;
1470 pulsed.mloop = pa_mloop;
1475 pulsed.state = (pa_stream_state_t)PA_STREAM_UNCONNECTED;
1476 pulsed.in_arate = 44100;
1478 pulsed.seek_pos = pulsed.seek_end = pulsed.real_seek_pos = 0;
1480 pulsed.num_calls = 0;
1481 pulsed.chunk_size = 0;
1482 pulsed.astream_fd = -1;
1483 pulsed.abs_maxvol_heard = 0.;
1484 pulsed.pulsed_died =
FALSE;
1485 pulsed.aPlayPtr = (audio_buffer_t *)
lives_malloc(
sizeof(audio_buffer_t));
1486 pulsed.aPlayPtr->data = NULL;
1487 pulsed.aPlayPtr->size = 0;
1488 pulsed.aPlayPtr->max_size = 0;
1489 pulsed.in_achans = PA_ACHANS;
1490 pulsed.out_achans = PA_ACHANS;
1491 pulsed.out_asamps = PA_SAMPSIZE;
1492 pulsed.mute =
FALSE;
1493 pulsed.out_chans_available = PULSE_MAX_OUTPUT_CHANS;
1494 pulsed.is_output =
TRUE;
1495 pulsed.read_abuf = -1;
1496 pulsed.is_paused =
FALSE;
1498 pulsed.pa_props = NULL;
1499 pulsed.playing_file = -1;
1500 pulsed.sound_buffer = NULL;
1501 pulsed.extrausec = 0;
1506 int pulse_audio_read_init(
void) {
1508 #if PA_SW_CONNECTION
1512 pulsed_reader.in_use =
FALSE;
1513 pulsed_reader.mloop = pa_mloop;
1514 pulsed_reader.con = pcon;
1517 pulsed_reader.state = (pa_stream_state_t)PA_STREAM_UNCONNECTED;
1518 pulsed_reader.fd = -1;
1519 pulsed_reader.seek_pos = pulsed_reader.seek_end = 0;
1520 pulsed_reader.msgq = NULL;
1521 pulsed_reader.num_calls = 0;
1522 pulsed_reader.chunk_size = 0;
1523 pulsed_reader.astream_fd = -1;
1524 pulsed_reader.abs_maxvol_heard = 0.;
1525 pulsed_reader.pulsed_died =
FALSE;
1526 pulsed_reader.in_achans = PA_ACHANS;
1527 pulsed_reader.in_asamps = PA_SAMPSIZE;
1528 pulsed_reader.mute =
FALSE;
1529 pulsed_reader.is_output =
FALSE;
1530 pulsed_reader.is_paused =
FALSE;
1531 pulsed_reader.pstream = NULL;
1532 pulsed_reader.pa_props = NULL;
1533 pulsed_reader.sound_buffer = NULL;
1534 pulsed_reader.extrausec = 0;
1539 #if PA_SW_CONNECTION
1540 static void info_cb(pa_context * c,
const pa_sink_input_info * i,
int eol,
void *userdata) {
1545 pulse_driver_t *pdriver = (pulse_driver_t *)userdata;
1548 pdrive->volume = i->volume;
1549 pdriver->volume_linear = pa_sw_volume_to_linear(i->volume.values[0]);
1556 int pulse_driver_activate(pulse_driver_t *pdriver) {
1558 char *pa_clientname;
1561 pa_sample_spec pa_spec;
1562 pa_channel_map pa_map;
1563 pa_buffer_attr pa_battr;
1565 pa_operation *pa_op;
1567 if (pdriver->pstream)
return 0;
1571 if (pdriver->is_output) {
1572 pa_clientname =
"LiVES_audio_out";
1574 pa_clientname =
"LiVES_audio_in";
1579 pdriver->pa_props = pa_proplist_new();
1581 pa_proplist_sets(pdriver->pa_props, PA_PROP_APPLICATION_ICON_NAME, lives_get_application_name());
1582 pa_proplist_sets(pdriver->pa_props, PA_PROP_APPLICATION_ID, lives_get_application_name());
1583 pa_proplist_sets(pdriver->pa_props, PA_PROP_APPLICATION_NAME, lives_get_application_name());
1585 pa_proplist_sets(pdriver->pa_props, PA_PROP_APPLICATION_PROCESS_BINARY,
capable->
myname);
1586 pa_proplist_sets(pdriver->pa_props, PA_PROP_APPLICATION_PROCESS_ID, mypid);
1587 pa_proplist_sets(pdriver->pa_props, PA_PROP_APPLICATION_VERSION, LiVES_VERSION);
1592 pa_proplist_sets(pdriver->pa_props, PA_PROP_APPLICATION_LANGUAGE, pango_language_to_string(gtk_get_default_language()));
1597 pa_proplist_sets(pdriver->pa_props, PA_PROP_APPLICATION_LANGUAGE,
1598 (QLocale::languageToString(ql.language())).toLocal8Bit().constData());
1601 pa_channel_map_init_stereo(&pa_map);
1603 pa_spec.format = PA_SAMPLE_S16NE;
1605 pa_spec.channels = pdriver->out_achans = pdriver->in_achans;
1607 pdriver->in_asamps = pdriver->out_asamps = PA_SAMPSIZE;
1612 pa_spec.format = PA_SAMPLE_S16BE;
1615 pa_spec.format = PA_SAMPLE_S16LE;
1618 if (pdriver->is_output) {
1619 pa_battr.maxlength = LIVES_PA_BUFF_MAXLEN;
1620 pa_battr.tlength = LIVES_PA_BUFF_TARGET;
1621 pa_battr.minreq = LIVES_PA_BUFF_MINREQ * 2;
1625 pa_battr.prebuf = 0;
1627 pa_battr.maxlength = LIVES_PA_BUFF_MAXLEN * 2;
1628 pa_battr.fragsize = LIVES_PA_BUFF_FRAGSIZE * 4;
1629 pa_battr.minreq = (uint32_t) - 1;
1630 pa_battr.prebuf = -1;
1634 if (pulse_server_rate == 0) {
1635 pa_op = pa_context_get_server_info(pdriver->con, pulse_server_cb, pa_mloop);
1636 while (pa_operation_get_state(pa_op) == PA_OPERATION_RUNNING) {
1637 pa_threaded_mainloop_wait(pa_mloop);
1639 pa_operation_unref(pa_op);
1642 if (pulse_server_rate == 0) {
1644 LIVES_WARN(
"Problem getting pulseaudio rate...expect more problems ahead.");
1648 pa_spec.rate = pdriver->out_arate = pdriver->in_arate = pulse_server_rate;
1650 pdriver->pstream = pa_stream_new_with_proplist(pdriver->con, pa_clientname, &pa_spec, &pa_map, pdriver->pa_props);
1654 if (pdriver->is_output) {
1656 pdriver->is_corked =
TRUE;
1659 pa_stream_set_write_callback(pdriver->pstream, pulse_audio_write_process, pdriver);
1660 pa_stream_set_underflow_callback(pdriver->pstream, stream_underflow_callback, pdriver);
1661 pa_stream_set_overflow_callback(pdriver->pstream, stream_overflow_callback, pdriver);
1662 pa_stream_set_moved_callback(pdriver->pstream, stream_moved_callback, pdriver);
1663 pa_stream_set_buffer_attr_callback(pdriver->pstream, stream_buffer_attr_callback, pdriver);
1665 #if PA_SW_CONNECTION
1666 pa_stream_connect_playback(pdriver->pstream, NULL, &pa_battr, (pa_stream_flags_t)(PA_STREAM_ADJUST_LATENCY |
1667 PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_START_CORKED |
1668 PA_STREAM_AUTO_TIMING_UPDATE), NULL, NULL);
1671 pavol = pa_sw_volume_from_linear(pdriver->volume_linear);
1672 pa_cvolume_set(&pdriver->volume, pdriver->out_achans, pavol);
1676 pa_stream_connect_playback(pdriver->pstream, NULL, &pa_battr, (pa_stream_flags_t)(0
1677 | PA_STREAM_RELATIVE_VOLUME
1678 | PA_STREAM_INTERPOLATE_TIMING
1679 | PA_STREAM_START_CORKED
1680 | PA_STREAM_START_UNMUTED
1681 | PA_STREAM_NOT_MONOTONIC
1682 | PA_STREAM_AUTO_TIMING_UPDATE),
1683 &pdriver->volume, NULL);
1687 while (pa_stream_get_state(pdriver->pstream) != PA_STREAM_READY) {
1692 pdriver->volume_linear = -1;
1694 #if PA_SW_CONNECTION
1696 pa_op = pa_context_get_sink_info(pdriver->con, info_cb, &pdriver);
1698 while (pa_operation_get_state(pa_op) == PA_OPERATION_RUNNING) {
1702 pa_operation_unref(pa_op);
1706 pdriver->frames_written = 0;
1707 pdriver->usec_start = 0;
1708 pdriver->in_use =
FALSE;
1709 pdriver->abs_maxvol_heard = 0.;
1710 pdriver->is_corked =
TRUE;
1713 pa_stream_set_underflow_callback(pdriver->pstream, stream_underflow_callback, pdriver);
1714 pa_stream_set_overflow_callback(pdriver->pstream, stream_overflow_callback, pdriver);
1716 pa_stream_set_moved_callback(pdriver->pstream, stream_moved_callback, pdriver);
1717 pa_stream_set_buffer_attr_callback(pdriver->pstream, stream_buffer_attr_callback, pdriver);
1718 pa_stream_set_read_callback(pdriver->pstream, pulse_audio_read_process, pdriver);
1720 pa_stream_connect_record(pdriver->pstream, NULL, &pa_battr,
1721 (pa_stream_flags_t)(PA_STREAM_START_CORKED
1722 | PA_STREAM_ADJUST_LATENCY
1723 | PA_STREAM_INTERPOLATE_TIMING
1724 | PA_STREAM_AUTO_TIMING_UPDATE
1725 | PA_STREAM_NOT_MONOTONIC));
1728 while (pa_stream_get_state(pdriver->pstream) != PA_STREAM_READY) {
1739 static void uncorked_cb(pa_stream * s,
int success,
void *userdata) {
1740 pulse_driver_t *pdriver = (pulse_driver_t *)userdata;
1741 #ifdef DEBUG_PULSE_CORK
1742 g_print(
"uncorked %p\n", pdriver);
1744 pdriver->is_corked =
FALSE;
1749 static void corked_cb(pa_stream * s,
int success,
void *userdata) {
1750 pulse_driver_t *pdriver = (pulse_driver_t *)userdata;
1751 #ifdef DEBUG_PULSE_CORK
1752 g_print(
"corked %p\n", pdriver);
1754 pdriver->is_corked =
TRUE;
1756 pa_threaded_mainloop_signal(pa_mloop, 0);
1760 void pulse_driver_uncork(pulse_driver_t *pdriver) {
1762 pdriver->abs_maxvol_heard = 0.;
1763 if (!pdriver->is_corked)
return;
1765 paop = pa_stream_cork(pdriver->pstream, 0, uncorked_cb, pdriver);
1767 if (pdriver->is_output) {
1768 pa_operation_unref(paop);
1771 pa_operation_unref(paop);
1775 void pulse_driver_cork(pulse_driver_t *pdriver) {
1779 if (pdriver->is_corked) {
1787 paop = pa_stream_cork(pdriver->pstream, 1, corked_cb, pdriver);
1788 while (pa_operation_get_state(paop) == PA_OPERATION_RUNNING && (timeout =
lives_alarm_check(alarm_handle)) > 0) {
1789 pa_threaded_mainloop_wait(pa_mloop);
1791 pa_operation_unref(paop);
1797 paop = pa_stream_flush(pdriver->pstream, NULL, NULL);
1798 pa_operation_unref(paop);
1806 if (is_output)
return &pulsed;
1807 return &pulsed_reader;
1813 return pulsed->msgq;
1817 boolean pa_time_reset(pulse_driver_t *pulsed,
ticks_t offset) {
1819 pa_operation *pa_op;
1821 if (!pulsed->pstream)
return FALSE;
1824 pa_op = pa_stream_update_timing_info(pulsed->pstream, pulse_success_cb, pa_mloop);
1826 while (pa_operation_get_state(pa_op) == PA_OPERATION_RUNNING) {
1827 pa_threaded_mainloop_wait(pa_mloop);
1829 pa_operation_unref(pa_op);
1832 while (pa_stream_get_time(pulsed->pstream, (pa_usec_t *)&usec) < 0) {
1836 pulsed->frames_written = 0;
1844 ticks_t lives_pulse_get_time(pulse_driver_t *pulsed) {
1854 while ((timeout =
lives_alarm_check(alarm_handle)) > 0 && pulse_get_msgq(pulsed)) {
1858 if (timeout == 0)
return -1;
1863 while (pa_stream_get_time(pulsed->pstream, (pa_usec_t *)&usec) < 0) {
1867 if (retval == -1) retval = 0;
1872 double lives_pulse_get_pos(pulse_driver_t *pulsed) {
1875 if (pulsed->playing_file > -1) {
1876 return (
double)(fwd_seek_pos)
1877 / (
double)(afile->arps * afile->achans * afile->asampsize / 8);
1880 return (
double)pulsed->frames_written / (double)pulsed->out_arate;
1884 boolean pulse_audio_seek_frame(pulse_driver_t *pulsed,
double frame) {
1890 if (frame > afile->frames && afile->frames > 0) frame = afile->frames;
1892 else fps = afile->fps;
1894 seekstart = (int64_t)(((frame - 1.) / fps
1896 * (pulsed->in_arate >= 0. ? 1.0 : -1.0) : 0.)) * (double)afile->arate)
1897 * afile->achans * afile->asampsize / 8;
1902 pulse_audio_seek_bytes(pulsed, seekstart, afile);
1907 int64_t pulse_audio_seek_bytes(pulse_driver_t *pulsed, int64_t bytes,
lives_clip_t *sfile) {
1916 fwd_seek_pos = bytes;
1918 if (!pulsed->is_corked) {
1921 pmsg = pulse_get_msgq(pulsed);
1924 pmsg = pulse_get_msgq(pulsed);
1928 if (timeout == 0 || pulsed->playing_file == -1) {
1929 if (timeout == 0)
LIVES_WARN(
"PA connect timed out");
1934 if (bytes < 0) bytes = 0;
1941 pulse_message2.next = NULL;
1943 pulse_message2.tc = 0;
1944 if (!pulsed->msgq) pulsed->msgq = &pulse_message2;
1945 else pulsed->msgq->next = &pulse_message2;
1950 boolean pulse_try_reconnect(
void) {
1968 if (!lives_pulse_init(9999)) {
1973 pulse_audio_read_init();
1983 d_print(
_(
"\nConnection to pulseaudio was reset.\n"));
2000 void pulse_aud_pb_ready(
int fileno) {
2001 char *tmpfilename = NULL;
2045 if (timeout == 0) pulse_try_reconnect();
2052 pulse_message.next = NULL;