13#define afile mainw->files[pulsed->playing_file]
17#define THRESH_BASE 10000.
18#define THRESH_MAX 50000.
20static pulse_driver_t pulsed;
21static pulse_driver_t pulsed_reader;
23static pa_threaded_mainloop *pa_mloop = NULL;
24static pa_context *pcon = NULL;
25static char pactxnm[512];
27static uint32_t pulse_server_rate = 0;
29#define PULSE_READ_BYTES 48000
31static uint8_t prbuf[PULSE_READ_BYTES * 2];
35static boolean seek_err;
36static boolean sync_ready =
FALSE;
38static volatile int lock_count = 0;
40static 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");
66static 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);
72static void pulse_success_cb(pa_stream *stream,
int i,
void *userdata) {pa_threaded_mainloop_signal(pa_mloop, 0);}
75#include <sys/resource.h>
77static void stream_underflow_callback(pa_stream *s,
void *userdata) {
84 fprintf(stderr,
"PA Stream underrun.\n");
91static 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);
101static void stream_moved_callback(pa_stream *s,
void *userdata) {
103 fprintf(stderr,
"Stream moved. \n");
107static void stream_buffer_attr_callback(pa_stream *s,
void *userdata) {
112boolean 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"));
183void 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;
194static void pulse_set_rec_avals(pulse_driver_t *pulsed) {
198 pulse_get_rec_avals(pulsed);
203LIVES_GLOBAL_INLINE size_t pulse_get_buffsize(pulse_driver_t *pulsed) {
return pulsed->chunk_size;}
205#if !HAVE_PA_STREAM_BEGIN_WRITE
206static void pulse_buff_free(
void *ptr) {
lives_free(ptr);}
209static 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;
225static 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)
284static short *shortbuffer = NULL;
311static 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");
1145lives_printerr(
"done\n");
1150size_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;
1242static 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);
1434void 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);
1450void 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;
1467int 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;
1506int pulse_audio_read_init(
void) {
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;
1540static 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]);
1556int 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);
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;
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) {
1739static 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;
1749static 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);
1760void 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);
1775void 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;
1817boolean 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;
1844ticks_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;
1872double 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;
1884boolean 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);
1907int64_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;
1950boolean pulse_try_reconnect(
void) {
1968 if (!lives_pulse_init(9999)) {
1973 pulse_audio_read_init();
1983 d_print(
_(
"\nConnection to pulseaudio was reset.\n"));
2000void pulse_aud_pb_ready(
int fileno) {
2001 char *tmpfilename = NULL;
2045 if (timeout == 0) pulse_try_reconnect();
2052 pulse_message.next = NULL;
void append_to_audio_bufferf(float *src, uint64_t nsamples, int channum)
boolean get_audio_from_plugin(float **fbuffer, int nchans, int arate, int nsamps, boolean is_audio_thread)
void append_to_audio_buffer16(void *src, uint64_t nsamples, int channum)
LIVES_GLOBAL_INLINE void audio_stream(void *buff, size_t nbytes, int fd)
void sample_silence_stream(int nchans, int64_t nframes)
int64_t sample_move_float_int(void *holding_buff, float **float_buffer, int nsamps, double scale, int chans, int asamps, int usigned, boolean rev_endian, boolean interleaved, float vol)
convert float samples back to int interleaved is for the float buffer; output int is always interleav...
float sample_move_d16_float(float *dst, short *src, uint64_t nsamples, uint64_t src_skip, int is_unsigned, boolean rev_endian, float vol)
void sample_move_d16_d16(int16_t *dst, int16_t *src, uint64_t nsamples, size_t tbytes, double scale, int nDstChannels, int nSrcChannels, int swap_endian, int swap_sign)
convert from any number of source channels to any number of destination channels - both interleaved
LIVES_GLOBAL_INLINE char * lives_get_audio_file_name(int fnum)
void sample_move_d16_d8(uint8_t *dst, short *src, uint64_t nsamples, size_t tbytes, double scale, int nDstChannels, int nSrcChannels, int swap_sign)
convert from any number of source channels to any number of destination channels - 8 bit output
boolean pad_with_silence(int out_fd, void *buff, off64_t oins_size, int64_t ins_size, int asamps, int aunsigned, boolean big_endian)
void sample_move_d8_d16(short *dst, uint8_t *src, uint64_t nsamples, size_t tbytes, double scale, int nDstChannels, int nSrcChannels, int swap_sign)
int64_t sample_move_abuf_int16(short *obuf, int nchans, int nsamps, int out_arate)
copy audio data from cache into audio sound buffer
#define AUD_WRITE_CHECK
after recording this many bytes we check disk space (default 128MB)
#define ASERVER_CMD_FILE_SEEK
#define SWAP_L_TO_X
local to other
#define ASERVER_CMD_PROCESSED
asynch msging
#define ASERVER_CMD_FILE_CLOSE
#define lives_vol_from_linear(vol)
#define SWAP_X_TO_L
endian swapping
#define SWAP_U_TO_S
sign swapping
#define ASERVER_CMD_FILE_OPEN
#define SWAP_S_TO_U
signed to unsigned
void on_mute_activate(LiVESMenuItem *menuitem, livespointer user_data)
boolean clip_can_reverse(int clipno)
LIVES_GLOBAL_INLINE weed_layer_t * weed_layer_free(weed_layer_t *layer)
frees pixel_data for a layer, then the layer itself
LIVES_GLOBAL_INLINE weed_layer_t * weed_layer_new(int layer_type)
LIVES_GLOBAL_INLINE float ** weed_layer_get_audio_data(weed_layer_t *layer, int *naudchans)
LIVES_GLOBAL_INLINE weed_layer_t * weed_layer_set_audio_data(weed_layer_t *layer, float **data, int arate, int naudchans, weed_size_t nsamps)
#define WEED_LAYER_TYPE_AUDIO
weed_plant_t weed_layer_t
LiVESResponseType do_error_dialogf(const char *fmt,...)
void do_threaded_dialog(const char *trans_text, boolean has_cancel)
LIVES_GLOBAL_INLINE LiVESResponseType do_abort_cancel_retry_dialog(const char *text)
LIVES_GLOBAL_INLINE void do_pulse_lost_conn_error(void)
void end_threaded_dialog(void)
LIVES_GLOBAL_INLINE LiVESResponseType do_error_dialog(const char *text)
void threaded_dialog_spin(double fraction)
void weed_apply_audio_effects_rt(weed_layer_t *alayer, weed_timecode_t tc, boolean analysers_only, boolean is_audio_thread)
boolean has_audio_filters(lives_af_t af_type)
LIVES_GLOBAL_INLINE void * lives_calloc_safety(size_t nmemb, size_t xsize)
LIVES_GLOBAL_INLINE uint64_t lives_random(void)
LIVES_GLOBAL_INLINE uint64_t fastrand(void)
#define lives_nanosleep(nanosec)
ssize_t lives_read_buffered(int fd, void *buf, ssize_t count, boolean allow_less)
int lives_close_buffered(int fd)
#define CLIP_HAS_AUDIO(clip)
boolean check_for_disk_space(boolean fullcheck)
#define LIVES_GLOBAL_INLINE
ticks_t lives_get_current_playback_ticks(ticks_t origsecs, ticks_t origusecs, lives_time_source_t *time_source)
boolean lives_read_buffered_eof(int fd)
#define ALIGN_CEIL64(a, b)
boolean lives_alarm_clear(lives_alarm_t alarm_handle)
int lives_system(const char *com, boolean allow_error)
void switch_aud_to_none(boolean set_pref)
#define AFORM_LITTLE_ENDIAN
void add_to_ascrap_mb(uint64_t bytes)
int lives_open_buffered_rdonly(const char *pathname)
lives_alarm_t lives_alarm_set(ticks_t ticks)
set alarm for now + delta ticks (10 nanosec) param ticks (10 nanoseconds) is the offset when we want ...
@ LIVES_DIRECTION_FORWARD
#define IS_VALID_CLIP(clip)
off_t lives_buffered_offset(int fd)
char * filename_from_fd(char *val, int fd)
: return filename from an open fd, freeing val first
void d_print(const char *fmt,...)
boolean lives_buffered_rdonly_set_reversed(int fd, boolean val)
off_t lives_lseek_buffered_rdonly_absolute(int fd, off_t offset)
boolean lives_freep(void **ptr)
ticks_t lives_alarm_check(lives_alarm_t alarm_handle)
@ CANCEL_AUD_END
video playback completed
@ CANCEL_KEEP
user pressed 'Keep'
#define LIVES_SHORT_TIMEOUT
#define LIVES_SHORTEST_TIMEOUT
#define USEC_TO_TICKS
multiplying factor uSec -> ticks_t (def. 100)
#define TICKS_PER_SECOND_DBL
actually microseconds / 100.
boolean pref_factory_float(const char *prefidx, float newval, boolean permanent)
#define PREF_MASTER_VOLUME
#define AUDIO_OPTS_FOLLOW_CLIPS
#define AUDIO_OPTS_FOLLOW_FPS
_future_prefs * future_prefs
volatile float volume
audio volume level (for jack and pulse)
boolean perm_audio_reader
volatile uint32_t audio_opts
boolean force_system_clock
boolean(* render_audio_frame_float)(float **audio, int nsamps)
volatile struct _aserver_message_t * next
volatile size_t samples_filled
number of samples filled (readonly client)
corresponds to one clip in the GUI
int arps
audio physical sample rate (i.e the "normal" sample rate of the clip when played at 1,...
int asampsize
audio sample size in bits (8 or 16)
volatile off64_t aseek_pos
audio seek posn. (bytes) for when we switch clips
int achans
number of audio channels (0, 1 or 2)
int cb_src
source clip for clipboard; for other clips, may be used to hold some temporary linkage
uint32_t signed_endian
bitfield
double pb_fps
current playback rate, may vary from fps, can be 0. or negative
int arate
current audio playback rate (varies if the clip rate is changed)
_vid_playback_plugin * vpp
video plugin
volatile int agen_key
which fx key is generating audio [1 based] (or 0 for none)
volatile boolean video_seek_ready
pthread_mutex_t audio_filewriteend_mutex
sync for ending writing audio to file
int aud_rec_fd
fd of file we are recording audio to
volatile ticks_t currticks
wall clock time, updated whenever lives_get_*_ticks is called
void * pulsed
pulseaudio player
lives_clip_t * files[MAX_FILES+1]
+1 for the clipboard
ticks_t origsecs
playback start seconds - subtracted from all other ticks to keep numbers smaller
volatile boolean loop_cont
volatile boolean ext_audio
using external video playback plugin to stream audio
volatile lives_cancel_t cancelled
pthread_cond_t avseek_cond
ticks_t orignsecs
usecs at start of playback - ditto
uint64_t aud_data_written
frames_t fps_mini_measure
show fps stats during playback
pthread_mutex_t vpp_stream_mutex
prevent from writing audio when stream is closing
int play_sequence
currticks when last display was shown (used for fixed fps)
volatile int rec_aclip
recording values - to be inserted at the following video frame
volatile double rec_aseek
boolean playing_sel
list of set names in current workdir, mau be NULL
LiVESWidget * ext_audio_mon
volatile boolean record_paused
pause during recording
int ascrap_file
scrap file for recording audio scraps
double audio_stretch
for fixed fps modes, the value is used to speed up / slow down audio
lives_mt * multitrack
holds a pointer to the entire multitrack environment; NULL in Clip Edit mode
pthread_mutex_t avseek_mutex
volatile boolean ping_pong
boolean foreign
for external window capture
volatile boolean agen_needs_reinit
boolean is_processing
states
boolean preview_rendering
ticks_t syncticks
adjustment to compensate for missed clock updates when switching time sources
volatile ticks_t startticks
effective ticks when current frame was (should have been) displayed
volatile boolean audio_seek_ready
volatile lives_whentostop_t whentostop
int playing_file
which number file we are playing (or -1) [generally mainw->current_file]
volatile lives_audio_buf_t * audio_frame_buffer
used for buffering / feeding audio to video generators
volatile int uflow_count
experimental values, primarily for testing
weed_event_t * event_list
current event_list, for recording
#define lives_strdup_printf(fmt,...)