LiVES  3.2.0
pulse.c
Go to the documentation of this file.
1 // pulse.c
2 // LiVES (lives-exe)
3 // (c) G. Finch <salsaman+lives@gmail.com> 2005 - 2020
4 // Released under the GPL 3 or later
5 // see file ../COPYING for licensing details
6 
7 #ifdef HAVE_PULSE_AUDIO
8 #include "main.h"
9 #include "callbacks.h"
10 #include "effects.h"
11 #include "effects-weed.h"
12 
13 #define afile mainw->files[pulsed->playing_file]
14 
15 //#define DEBUG_PULSE
16 
17 #define THRESH_BASE 10000.
18 #define THRESH_MAX 50000.
19 
20 static pulse_driver_t pulsed;
21 static pulse_driver_t pulsed_reader;
22 
23 static pa_threaded_mainloop *pa_mloop = NULL;
24 static pa_context *pcon = NULL;
25 static char pactxnm[512];
26 
27 static uint32_t pulse_server_rate = 0;
28 
29 #define PULSE_READ_BYTES 48000
30 
31 static uint8_t prbuf[PULSE_READ_BYTES * 2];
32 
33 static size_t prb = 0;
34 
35 static boolean seek_err;
36 static boolean sync_ready = FALSE;
37 
38 static volatile int lock_count = 0;
39 
40 static off_t fwd_seek_pos = 0;
41 
43 
44 
45 LIVES_GLOBAL_INLINE void pa_mloop_lock(void) {
46  if (!pa_threaded_mainloop_in_thread(pa_mloop)) {
47  pa_threaded_mainloop_lock(pa_mloop);
48  ++lock_count;
49  } else {
50  LIVES_ERROR("tried to lock pa mainloop within audio thread");
51  }
52 }
53 
54 LIVES_GLOBAL_INLINE void pa_mloop_unlock(void) {
55  if (!pa_threaded_mainloop_in_thread(pa_mloop)) {
56  if (lock_count > 0) {
57  --lock_count;
58  pa_threaded_mainloop_unlock(pa_mloop);
59  }
60  } else {
61  LIVES_ERROR("tried to unlock pa mainloop within audio thread");
62  }
63 }
64 
65 
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);
70 }
71 
72 static void pulse_success_cb(pa_stream *stream, int i, void *userdata) {pa_threaded_mainloop_signal(pa_mloop, 0);}
73 
74 #include <sys/time.h>
75 #include <sys/resource.h>
76 
77 static void stream_underflow_callback(pa_stream *s, void *userdata) {
78  // we get isolated cases when the GUI is very busy, for example right after playback
79  // we should ignore these isolated cases, except in DEBUG mode.
80  // otherwise - increase tlen and possibly maxlen ?
81  // e.g. pa_stream_set_buffer_attr(s, battr, success_cb, NULL);
82 
83  if (prefs->show_dev_opts) {
84  fprintf(stderr, "PA Stream underrun.\n");
85  }
86 
87  mainw->uflow_count++;
88 }
89 
90 
91 static void stream_overflow_callback(pa_stream *s, void *userdata) {
92  pa_operation *paop;
93  //pulse_driver_t *pulsed = (pulse_driver_t *)userdata;
94  fprintf(stderr, "Stream overrun.\n");
95  paop = pa_stream_flush(s, NULL, NULL);
96  pa_operation_unref(paop);
97  //break_me();
98 }
99 
100 
101 static void stream_moved_callback(pa_stream *s, void *userdata) {
102  //pulse_driver_t *pulsed = (pulse_driver_t *)userdata;
103  fprintf(stderr, "Stream moved. \n");
104 }
105 
106 
107 static void stream_buffer_attr_callback(pa_stream *s, void *userdata) {
108  //fprintf(stderr, "Stream ba changed. \n");
109 }
110 
111 
112 boolean lives_pulse_init(short startup_phase) {
113  // startup pulseaudio server
114  char *msg;
115  pa_context_state_t pa_state;
116  ticks_t timeout;
117  lives_alarm_t alarm_handle;
118  LiVESResponseType resp;
119  boolean retried = FALSE;
120 
121  if (pa_mloop) return TRUE;
122 
123 retry:
124 
125  pa_mloop = pa_threaded_mainloop_new();
126  lives_snprintf(pactxnm, 512, "LiVES-%"PRId64, lives_random());
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);
130 
131  pa_state = pa_context_get_state(pcon);
132 
133  alarm_handle = lives_alarm_set(LIVES_SHORT_TIMEOUT);
134  while ((timeout = lives_alarm_check(alarm_handle)) > 0 && pa_state != PA_CONTEXT_READY) {
135  sched_yield();
136  lives_usleep(prefs->sleep_time);
137  pa_state = pa_context_get_state(pcon);
138  }
139  lives_alarm_clear(alarm_handle);
140 
141  if (pa_context_get_state(pcon) == PA_CONTEXT_READY) timeout = 1;
142 
143  if (timeout == 0) {
144  pa_context_unref(pcon);
145  pcon = NULL;
146  pulse_shutdown();
147  if (!retried) {
148  retried = TRUE;
149  goto retry;
150  }
151  LIVES_WARN("Unable to connect to the pulseaudio server");
152 
153  if (!mainw->foreign) {
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");
162  goto retry;
163  }
164  fprintf(stderr, "Giving up.\n");
166  } else {
167  msg = (_("\nUnable to connect to the pulseaudio server.\n"));
168  if (startup_phase != 2) {
169  do_error_dialog(msg);
171  } else {
172  do_error_dialogf("%s%s", msg, _("LiVES will exit and you can choose another audio player.\n"));
173  }
174  lives_free(msg);
175  }
176  }
177  return FALSE;
178  }
179  return TRUE;
180 }
181 
182 
183 void pulse_get_rec_avals(pulse_driver_t *pulsed) {
184  mainw->rec_aclip = pulsed->playing_file;
185  if (mainw->rec_aclip != -1) {
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;
189  //g_print("RECSEEK is %f %ld\n", mainw->rec_aseek, pulsed->real_seek_pos);
190  }
191 }
192 
193 
194 static void pulse_set_rec_avals(pulse_driver_t *pulsed) {
195  // record direction change (internal)
196  mainw->rec_aclip = pulsed->playing_file;
197  if (mainw->rec_aclip != -1) {
198  pulse_get_rec_avals(pulsed);
199  }
200 }
201 
202 
203 LIVES_GLOBAL_INLINE size_t pulse_get_buffsize(pulse_driver_t *pulsed) {return pulsed->chunk_size;}
204 
205 #if !HAVE_PA_STREAM_BEGIN_WRITE
206 static void pulse_buff_free(void *ptr) {lives_free(ptr);}
207 #endif
208 
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;
213  } else {
215  }
216  mainw->fps_mini_measure = 0;
218  pthread_mutex_lock(&mainw->avseek_mutex);
220  pthread_cond_signal(&mainw->avseek_cond);
221  pthread_mutex_unlock(&mainw->avseek_mutex);
222 }
223 
224 
225 static void sample_silence_pulse(pulse_driver_t *pulsed, size_t nbytes, size_t xbytes) {
226  uint8_t *buff;
227  int nsamples;
228 
229  if (sync_ready) sync_ready_ok(pulsed, xbytes > 0 ? xbytes : 0);
230 
231  if (xbytes <= 0) return;
232  if (mainw->aplayer_broken) return;
233  while (nbytes > 0) {
234  int ret = 0;
235 #if HAVE_PA_STREAM_BEGIN_WRITE
236  xbytes = -1;
237  // returns a buffer and size for us to write to
238  pa_stream_begin_write(pulsed->pstream, (void **)&buff, &xbytes);
239 #endif
240  if (nbytes < xbytes) xbytes = nbytes;
241 #if !HAVE_PA_STREAM_BEGIN_WRITE
242  buff = (uint8_t *)lives_calloc(xbytes);
243 #endif
244  if (!buff || ret != 0) return;
245 
246 #if HAVE_PA_STREAM_BEGIN_WRITE
247  lives_memset(buff, 0, xbytes);
248 #endif
249  if (pulsed->astream_fd != -1) audio_stream(buff, xbytes, pulsed->astream_fd); // old streaming API
250 
251  nsamples = xbytes / pulsed->out_achans / (pulsed->out_asamps >> 3);
252 
253  // streaming API
254  if (mainw->ext_audio && mainw->vpp && mainw->vpp->render_audio_frame_float && pulsed->playing_file != -1
255  && pulsed->playing_file != mainw->ascrap_file) {
256  sample_silence_stream(pulsed->out_achans, nsamples);
257  }
258 
260  && (!mainw->event_list || mainw->record || mainw->record_paused)) {
261  // buffer audio for any generators
262  // interleaved, so we paste all to channel 0
263  append_to_audio_buffer16(buff, nsamples * pulsed->out_achans, 0);
264  mainw->audio_frame_buffer->samples_filled += nsamples * pulsed->out_achans;
265  }
266 #if !HAVE_PA_STREAM_BEGIN_WRITE
267  pa_stream_write(pulsed->pstream, buff, xbytes, pulse_buff_free, 0, PA_SEEK_RELATIVE);
268 #else
269  pa_stream_write(pulsed->pstream, buff, xbytes, NULL, 0, PA_SEEK_RELATIVE);
270 #endif
271  nbytes -= xbytes;
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);
275  }
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;
279 }
280 
281 
282 #define NBYTES_LIMIT (65536 * 4)
283 
284 static short *shortbuffer = NULL;
285 
311 static void pulse_audio_write_process(pa_stream *pstream, size_t nbytes, void *arg) {
312  pulse_driver_t *pulsed = (pulse_driver_t *)arg;
313  pa_operation *paop;
314  aserver_message_t *msg;
315  ssize_t pad_bytes = 0;
316  uint8_t *buffer;
317  uint64_t nsamples = nbytes / pulsed->out_achans / (pulsed->out_asamps >> 3);
318  off_t offs = 0;
319  size_t xbytes = pa_stream_writable_size(pstream);
320  off_t seek, xseek;
321  pa_volume_t pavol;
322  char *filename;
323 
324  boolean got_cmd = FALSE;
325  boolean from_memory = FALSE;
326  boolean needs_free = FALSE;
327 
328  int new_file;
329 
330  sync_ready = FALSE;
331 
332  //pa_thread_make_realtime(50);
333  //g_print("PA\n");
334  pulsed->real_seek_pos = pulsed->seek_pos;
335  pulsed->pstream = pstream;
336 
337  if (xbytes > nbytes) xbytes = nbytes;
338 
339  if (!mainw->is_ready || !pulsed || (!LIVES_IS_PLAYING && !pulsed->msgq) || nbytes > NBYTES_LIMIT) {
340  sample_silence_pulse(pulsed, nsamples * pulsed->out_achans * (pulsed->out_asamps >> 3), xbytes);
341  //g_print("pt a1 %ld %d %p %d %p %ld\n",nsamples, mainw->is_ready, pulsed, mainw->playing_file, pulsed->msgq, nbytes);
342  return;
343  }
344 
346  if ((msg = (aserver_message_t *)pulsed->msgq) != NULL) {
347  got_cmd = TRUE;
348  switch (msg->command) {
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) {
355  filename = lives_get_audio_file_name(new_file);
356  pulsed->fd = lives_open_buffered_rdonly(filename);
357  if (pulsed->fd == -1) {
358  // dont show gui errors - we are running in realtime thread
359  LIVES_ERROR("pulsed: error opening");
360  LIVES_ERROR(filename);
361  pulsed->playing_file = -1;
362  }
363  lives_free(filename);
364  }
365  pulsed->real_seek_pos = pulsed->seek_pos = 0;
366  pulsed->playing_file = new_file;
367  //pa_stream_trigger(pulsed->pstream, NULL, NULL); // only needed for prebuffer
368  break;
370  pulsed->in_use = TRUE;
371  paop = pa_stream_flush(pulsed->pstream, NULL, NULL);
372  pa_operation_unref(paop);
373  if (pulsed->fd >= 0) lives_close_buffered(pulsed->fd);
374  if (pulsed->sound_buffer == pulsed->aPlayPtr->data) pulsed->sound_buffer = NULL;
375  if (pulsed->aPlayPtr->data) {
376  lives_free((void *)(pulsed->aPlayPtr->data));
377  pulsed->aPlayPtr->data = NULL;
378  }
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;
383  break;
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);
398 
399  //g_print("xseek is %ld\n", xseek);
400  if (seek < 0.) xseek = 0.;
401  xseek = ALIGN_CEIL64(xseek, afile->achans * (afile->asampsize >> 3));
402  lives_lseek_buffered_rdonly_absolute(pulsed->fd, xseek);
403  pulsed->real_seek_pos = pulsed->seek_pos = afile->aseek_pos = xseek;
404  if (pulsed->playing_file == mainw->ascrap_file || afile->adirection == LIVES_DIRECTION_FORWARD) {
406  } else {
408  }
409  break;
410  default:
411  pulsed->msgq = NULL;
412  msg->data = NULL;
413  }
414  if (msg->next != msg) lives_freep((void **) & (msg->data));
416  pulsed->msgq = msg->next;
417  if (pulsed->msgq && pulsed->msgq->next == pulsed->msgq) pulsed->msgq->next = NULL;
418  }
419  if (got_cmd) {
420  sample_silence_pulse(pulsed, nsamples * pulsed->out_achans * (pulsed->out_asamps >> 3), xbytes);
421  return;
422  }
423 
425  fwd_seek_pos = pulsed->real_seek_pos;
426 
427  if (pulsed->chunk_size != nbytes) pulsed->chunk_size = nbytes;
428 
429  pulsed->state = pa_stream_get_state(pulsed->pstream);
430 
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.;
436  float clip_vol = 1.;
437 #ifdef DEBUG_PULSE
438  int64_t in_frames = 0;
439 #endif
440  size_t in_bytes = 0, xin_bytes = 0;
442  float shrink_factor = 1.f;
443  int swap_sign;
444  int qnt = 1;
445 
446  if (IS_VALID_CLIP(pulsed->playing_file)) qnt = afile->achans * (afile->asampsize >> 3);
447 
448 #ifdef DEBUG_PULSE
449  lives_printerr("playing... pulseFramesAvailable = %ld\n", pulseFramesAvailable);
450 #endif
451 
452  pulsed->num_calls++;
453 
455  if (!pulsed->in_use || (pulsed->read_abuf > -1 && !LIVES_IS_PLAYING)
456  || ((((pulsed->fd < 0 || pulsed->seek_pos < 0 ||
457  (!mainw->multitrack && IS_VALID_CLIP(pulsed->playing_file) && pulsed->seek_pos > afile->afilesize))
458  && pulsed->read_abuf < 0) && ((mainw->agen_key == 0 && !mainw->agen_needs_reinit) || mainw->multitrack))
459  || pulsed->is_paused || (mainw->pulsed_read && mainw->pulsed_read->playing_file != -1))) {
460 
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;
463  pulsed->seek_pos = ALIGN_CEIL64(pulsed->seek_pos, qnt);
464  if (pulsed->seek_pos > 0) {
465  pad_bytes = -pulsed->real_seek_pos;
466  pulsed->real_seek_pos = pulsed->seek_pos = 0;
467  }
468  }
469 
470  if (IS_VALID_CLIP(pulsed->playing_file) && !mainw->multitrack
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); // -ve val
476  pulsed->real_seek_pos = pulsed->seek_pos = afile->afilesize;
477  }
478  }
479 #ifdef DEBUG_PULSE
480  g_print("pt a3 %d\n", pulsed->in_use);
481 #endif
482 
483  if (!pad_bytes) {
484  sample_silence_pulse(pulsed, nsamples * pulsed->out_achans * pulsed->out_asamps >> 3, xbytes);
485  return;
486  }
487  }
488 
489  if (!mainw->audio_seek_ready && pulsed->playing_file != mainw->playing_file)
491 
492  if (!mainw->audio_seek_ready) {
493  double dqnt;
494  size_t qnt;
495  int64_t rnd_samp;
496  frames_t rnd_frame;
497  if (!mainw->video_seek_ready) {
498  int64_t xusec = pulsed->extrausec;
499  sample_silence_pulse(pulsed, nsamples * pulsed->out_achans * pulsed->out_asamps >> 3, xbytes);
500  //pulsed->seek_pos += xbytes;
501  fwd_seek_pos = pulsed->real_seek_pos = pulsed->seek_pos;
502  pulsed->usec_start += (pulsed->extrausec - xusec);
503  pulsed->extrausec = xusec;
504  //mainw->startticks = mainw->currticks = lives_get_current_playback_ticks(mainw->origsecs, mainw->orignsecs, NULL);
505  return;
507  }
508  dqnt = (double)afile->achans * afile->asampsize / 8.;
509  qnt = afile->achans * (afile->asampsize >> 3);
510  /* g_print("@ SYNCxx %d seek pos %ld = %f ct %ld st %ld\n", mainw->actual_frame, pulsed->seek_pos, */
511  /* ((double)pulsed->seek_pos / (double)afile->arps / 4. * afile->fps + 1.), mainw->currticks, mainw->startticks); */
512  /* pulsed->seek_pos += afile->adirection * (double)(mainw->currticks - mainw->startticks) / TICKS_PER_SECOND_DBL */
513  /* * (double)(afile->arps * qnt); */
514  rnd_frame = (frames_t)((double)pulsed->seek_pos / (double)afile->arate / dqnt * afile->fps
515  + (afile->last_play_sequence != mainw->play_sequence ? .000001 : .5));
516  //g_print("RND frame is %d\n", rnd_frame + 1);
517  //g_print("VALXXX %d %d %d\n", mainw->play_sequence, afile->last_play_sequence, mainw->switch_during_pb);
518  rnd_frame += afile->adirection * (mainw->switch_during_pb && afile->last_play_sequence == mainw->play_sequence ? 1 : 0);
520  rnd_samp = (int64_t)((double)(rnd_frame + .00001) / afile->fps * (double)afile->arate + .5);
521  pulsed->seek_pos = (ssize_t)(rnd_samp * qnt);
522  //g_print("rndfr = %d rnt = %ld skpo = %ld\n", rnd_frame + 1, rnd_samp, pulsed->seek_pos);
523  pulsed->seek_pos = ALIGN_CEIL64(pulsed->seek_pos, qnt);
524  lives_lseek_buffered_rdonly_absolute(pulsed->fd, pulsed->seek_pos);
525  //g_print("seek to %ld %ld\n", pulsed->seek_pos, (int64_t)((double)pulsed->seek_pos / 48000. / 4. * afile->fps) + 1);
526  fwd_seek_pos = pulsed->real_seek_pos = pulsed->seek_pos;
527 
528  if (pulsed->playing_file == mainw->ascrap_file || afile->adirection == LIVES_DIRECTION_FORWARD) {
530  } else {
532  }
533 
534  shrink_factor = (float)pulsed->in_arate / (float)pulsed->out_arate / mainw->audio_stretch;
535  in_framesd = fabs((double)shrink_factor * (double)pulseFramesAvailable);
536 
537  // preload the buffer for first read
538  in_bytes = (size_t)(in_framesd * pulsed->in_achans * (pulsed->in_asamps >> 3));
539  lives_read_buffered(pulsed->fd, NULL, in_bytes * 8, TRUE);
540  lives_lseek_buffered_rdonly_absolute(pulsed->fd, pulsed->seek_pos);
541  //mainw->startticks = mainw->currticks = lives_get_current_playback_ticks(mainw->origsecs, mainw->orignsecs, NULL);
542 
543  /* g_print("@ SYNC %d seek pos %ld = %f ct %ld st %ld\n", mainw->actual_frame, pulsed->seek_pos, */
544  /* ((double)pulsed->seek_pos / (double)afile->arps / 4. * afile->fps + 1.), mainw->currticks, mainw->startticks); */
545  sync_ready = TRUE;
546  }
547 
548  if (LIVES_LIKELY(pulseFramesAvailable > 0 && (pulsed->read_abuf > -1
549  || (pulsed->aPlayPtr && pulsed->in_achans > 0) ||
550  (((mainw->agen_key != 0 || mainw->agen_needs_reinit)
551  && !mainw->preview) && !mainw->multitrack)))) {
552  if (LIVES_IS_PLAYING && pulsed->read_abuf > -1) {
553  // playing back from memory buffers instead of from file
554  // this is used in multitrack
555  from_memory = TRUE;
556  numFramesToWrite = pulseFramesAvailable;
557  } else {
558  // from file or audio generator
559  if (LIVES_LIKELY(pulsed->fd >= 0)) {
560  int playfile = mainw->playing_file;
561  pulsed->seek_end = 0;
562  if (mainw->agen_key == 0 && !mainw->agen_needs_reinit && IS_VALID_CLIP(pulsed->playing_file)) {
563  if (mainw->playing_sel) {
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;
567  } else {
568  if (!mainw->loop_video) pulsed->seek_end = (int64_t)((double)(mainw->play_end - 1.) / afile->fps * afile->arps)
569  * afile->achans * (afile->asampsize / 8);
570  else pulsed->seek_end = afile->afilesize;
571  }
572  if (pulsed->seek_end > afile->afilesize) pulsed->seek_end = afile->afilesize;
573  }
574  if (pulsed->seek_end == 0 || ((pulsed->playing_file == mainw->ascrap_file && !mainw->preview) && IS_VALID_CLIP(playfile)
575  && mainw->files[playfile]->achans > 0)) pulsed->seek_end = INT64_MAX;
576 
578  pulsed->aPlayPtr->size = 0;
579 
580  shrink_factor = (float)pulsed->in_arate / (float)pulsed->out_arate / mainw->audio_stretch;
581  in_framesd = fabs((double)shrink_factor * (double)pulseFramesAvailable);
582 
583  // add in a small random factor so on longer timescales we arent losing or gaining samples
584  in_bytes = (int)(in_framesd + ((double)fastrand() / (double)LIVES_MAXUINT64))
585  * pulsed->in_achans * (pulsed->in_asamps >> 3);
586 
587 #ifdef DEBUG_PULSE
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);
591 #endif
592 
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));
598  pulsed->aPlayPtr->data = lives_calloc_safety(in_bytes >> 2, 4);
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;
602  }
603 
604  // update looping mode
605  if (mainw->whentostop == NEVER_STOP || mainw->loop_cont) {
607  && ((prefs->audio_opts & AUDIO_OPTS_FOLLOW_CLIPS) || mainw->current_file == pulsed->playing_file)
609  && mainw->agen_key == 0 && !mainw->agen_needs_reinit)
610  pulsed->loop = AUDIO_LOOP_PINGPONG;
611  else pulsed->loop = AUDIO_LOOP_FORWARD;
612  } else {
613  pulsed->loop = AUDIO_LOOP_NONE;
614  //in_bytes = 0;
615  }
616 
617  pulsed->aPlayPtr->size = 0;
618 
619  if (shrink_factor > 0.) {
620  // forward playback
621  if ((mainw->agen_key == 0 || mainw->multitrack || mainw->preview) && in_bytes > 0) {
623  if (pad_bytes < 0) pad_bytes = 0;
624  else {
625  pad_bytes *= shrink_factor;
626  pad_bytes = ALIGN_CEIL64(pad_bytes - qnt, qnt);
627  }
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;
637  if (rem > 0)
638  pulsed->aPlayPtr->size += lives_read_buffered(pulsed->fd, (void *)(pulsed->aPlayPtr->data)
639  + pulsed->aPlayPtr->size,
640  pulsed->seek_end - pulsed->real_seek_pos, TRUE);
641 
642  if (pulsed->loop == AUDIO_LOOP_NONE) {
643  if (*pulsed->whentostop == STOP_ON_AUD_END) *pulsed->cancelled = CANCEL_AUD_END;
644  in_bytes = 0;
645  pulsed->in_use = FALSE;
646  } else {
647  if (pulsed->loop == AUDIO_LOOP_PINGPONG && (afile->pb_fps < 0. || clip_can_reverse(pulsed->playing_file))) {
648  pulsed->in_arate = -pulsed->in_arate;
649  afile->adirection = -afile->adirection;
651 
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;
655  } else {
656  do {
657  if (mainw->playing_sel) {
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;
663  lives_lseek_buffered_rdonly_absolute(pulsed->fd, pulsed->seek_pos);
664  if (pulsed->aPlayPtr->size < in_bytes) {
665  pulsed->aPlayPtr->size += lives_read_buffered(pulsed->fd, (void *)(pulsed->aPlayPtr->data)
666  + pulsed->aPlayPtr->size, in_bytes - pulsed->aPlayPtr->size, TRUE);
667  pulsed->real_seek_pos = pulsed->seek_pos = lives_buffered_offset(pulsed->fd);
668  }
669  } while (pulsed->aPlayPtr->size < in_bytes && !lives_read_buffered_eof(pulsed->fd));
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;
675  }
676  }
677  }
678  pulsed->seek_pos = ALIGN_CEIL64(pulsed->seek_pos - qnt, qnt);
679  fwd_seek_pos = pulsed->real_seek_pos = pulsed->seek_pos;
680  if (mainw->record && !mainw->record_paused) pulse_set_rec_avals(pulsed);
681  }
682  }
683 
684  else if (pulsed->playing_file != mainw->ascrap_file && shrink_factor < 0.f) {
686  off_t seek_start = (mainw->playing_sel ?
687  (int64_t)((double)(afile->start - 1.) / afile->fps * afile->arps)
688  * afile->achans * (afile->asampsize / 8) : 0);
689  seek_start = ALIGN_CEIL64(seek_start - qnt, qnt);
690  if (pad_bytes > 0) pad_bytes = 0;
691  else {
692  if (pad_bytes < 0) {
693  pad_bytes *= shrink_factor;
694  pad_bytes = ALIGN_CEIL64(pad_bytes, qnt);
696  lives_memset((void *)pulsed->aPlayPtr->data + in_bytes - pad_bytes, 0, pad_bytes);
697  }
698  }
699 
700  if ((pulsed->seek_pos -= (in_bytes - pad_bytes)) < seek_start) {
702  if (pulsed->loop == AUDIO_LOOP_NONE) {
703  if (*pulsed->whentostop == STOP_ON_AUD_END) *pulsed->cancelled = CANCEL_AUD_END;
704  in_bytes = 0;
705  } else {
708  pulsed->seek_pos = ALIGN_CEIL64(seek_start, qnt);
709  if (((mainw->agen_key == 0 && !mainw->agen_needs_reinit))) {
710  lives_lseek_buffered_rdonly_absolute(pulsed->fd, pulsed->seek_pos);
711  pulsed->aPlayPtr->size = lives_read_buffered(pulsed->fd,
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);
720  }
721  }
722 
723  pulsed->aPlayPtr->size += pad_bytes;
724 
726  if (pulsed->loop == AUDIO_LOOP_PINGPONG) {
728  pulsed->in_arate = -pulsed->in_arate;
729  afile->adirection = -afile->adirection;
730  pulsed->seek_pos = seek_start;
731  } else {
732  pulsed->seek_pos = pulsed->seek_end - pulsed->aPlayPtr->size;
733  }
734  }
735  pulsed->seek_pos = ALIGN_CEIL64(pulsed->seek_pos - qnt, qnt);
736  fwd_seek_pos = pulsed->real_seek_pos = pulsed->seek_pos;
737  if (mainw->record && !mainw->record_paused) pulse_set_rec_avals(pulsed);
738  }
739 
740  if (((mainw->agen_key == 0 && !mainw->agen_needs_reinit)) && in_bytes - pulsed->aPlayPtr->size > 0) {
742  pulsed->seek_pos = ALIGN_CEIL64(pulsed->seek_pos, qnt);
743  lives_lseek_buffered_rdonly_absolute(pulsed->fd, pulsed->seek_pos);
744  if (pulsed->playing_file == mainw->ascrap_file || pulsed->in_arate > 0) {
746  } else {
748  if (pulsed->aPlayPtr->size < in_bytes) {
749  pulsed->real_seek_pos = pulsed->seek_pos = ALIGN_CEIL64(pulsed->seek_pos, qnt);
750  lives_lseek_buffered_rdonly_absolute(pulsed->fd, pulsed->seek_pos);
751  pulsed->aPlayPtr->size
752  += lives_read_buffered(pulsed->fd, (void *)(pulsed->aPlayPtr->data)
753  + pulsed->aPlayPtr->size,
754  in_bytes - pulsed->aPlayPtr->size, TRUE);
755  // *INDENT-OFF*
756  }}}}
757  // *INDENT-ON*
758 
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,
764  afile->asampsize >> 3, afile->signed_endian & AFORM_UNSIGNED,
765  afile->signed_endian & AFORM_BIG_ENDIAN);
766  } else {
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,
770  afile->asampsize >> 3, afile->signed_endian & AFORM_UNSIGNED,
771  afile->signed_endian & AFORM_BIG_ENDIAN);
772  }
773  }
774  }
775 
777  if (pulsed->mute || in_bytes == 0 || pulsed->aPlayPtr->size == 0 || !IS_VALID_CLIP(pulsed->playing_file)
778  || (!pulsed->aPlayPtr->data && ((mainw->agen_key == 0 && !mainw->agen_needs_reinit) ||
779  mainw->multitrack || mainw->preview))) {
780  sample_silence_pulse(pulsed, nsamples * pulsed->out_achans * (pulsed->out_asamps >> 3), xbytes);
781 #ifdef DEBUG_PULSE
782  g_print("pt a4\n");
783 #endif
784  return;
785  }
786 
787  if (mainw->agen_key != 0 && !mainw->multitrack && !mainw->preview) {
788  in_bytes = pulseFramesAvailable * pulsed->out_achans * 2;
789  if (xin_bytes == 0) xin_bytes = in_bytes;
790  }
791 
792  if ((mainw->agen_key == 0 && !mainw->agen_needs_reinit) || mainw->multitrack || (mainw->preview &&
795  swap_sign = afile->signed_endian & AFORM_UNSIGNED;
796 
797  inputFramesAvailable = pulsed->aPlayPtr->size / (pulsed->in_achans * (pulsed->in_asamps >> 3));
798 #ifdef DEBUG_PULSE
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);
802 #endif
803 
805  buffer = (uint8_t *)pulsed->aPlayPtr->data;
807  numFramesToWrite = MIN(pulseFramesAvailable, (inputFramesAvailable / fabsf(shrink_factor) + .001)); // VALGRIND
808 
809 #ifdef DEBUG_PULSE
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",
814  nsamples,
815  pulseFramesAvailable, pulsed->in_achans, pulsed->out_achans);
816 #endif
817 
818  // pulsed->sound_buffer will either point to pulsed->aPlayPtr->data or will hold transformed audio
819  if (pulsed->in_asamps == pulsed->out_asamps && shrink_factor == 1. && pulsed->in_achans == pulsed->out_achans &&
820  !pulsed->reverse_endian && !swap_sign) {
821  // no transformation needed
822  pulsed->sound_buffer = buffer;
823  } else {
824  if (pulsed->sound_buffer != pulsed->aPlayPtr->data) lives_freep((void **)&pulsed->sound_buffer);
825 
826  pulsed->sound_buffer = (uint8_t *)lives_calloc_safety(pulsed->chunk_size >> 2, 4);
827 
828  if (!pulsed->sound_buffer) {
829  sample_silence_pulse(pulsed, nsamples * pulsed->out_achans * (pulsed->out_asamps >> 3), xbytes);
830 #ifdef DEBUG_PULSE
831  g_print("pt X2\n");
832 #endif
833  return;
834  }
835 
836  if (!from_memory) {
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);
840  }
841 
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);
846  } else {
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,
849  swap_sign ? SWAP_U_TO_S : 0);
850  }
851  }
852 
853  if ((has_audio_filters(AF_TYPE_ANY) || mainw->ext_audio) && (pulsed->playing_file != mainw->ascrap_file)) {
854  boolean memok = TRUE;
855  float **fltbuf = (float **)lives_calloc(pulsed->out_achans, sizeof(float *));
856  register int i;
858  for (i = 0; i < pulsed->out_achans; i++) {
859  // convert s16 to non-interleaved float
860  fltbuf[i] = (float *)lives_calloc_safety(nsamples, sizeof(float));
861  if (!fltbuf[i]) {
862  memok = FALSE;
863  for (--i; i >= 0; i--) {
864  lives_freep((void **)&fltbuf[i]);
865  }
866  break;
867  }
870  pulsed->abs_maxvol_heard = sample_move_d16_float(fltbuf[i], (short *)pulsed->sound_buffer + i,
871  nsamples, pulsed->out_achans, FALSE, FALSE, 1.0);
872  }
873 
874  if (memok) {
875  ticks_t tc = mainw->currticks;
876  // apply any audio effects with in_channels
877 
885  weed_layer_set_audio_data(layer, fltbuf, pulsed->out_arate, pulsed->out_achans, nsamples);
887  lives_free(fltbuf);
888  fltbuf = weed_layer_get_audio_data(layer, NULL);
889  weed_layer_set_audio_data(layer, NULL, 0, 0, 0);
890  weed_layer_free(layer);
891  }
892 
893  pthread_mutex_lock(&mainw->vpp_stream_mutex);
895  (*mainw->vpp->render_audio_frame_float)(fltbuf, numFramesToWrite);
896  }
897  pthread_mutex_unlock(&mainw->vpp_stream_mutex);
898 
899  // convert float audio back to s16 in pulsed->sound_buffer
900  sample_move_float_int(pulsed->sound_buffer, fltbuf, nsamples, 1.0, pulsed->out_achans, PA_SAMPSIZE, 0,
901  (capable->byte_order == LIVES_LITTLE_ENDIAN), FALSE, 1.0);
902 
903  for (i = 0; i < pulsed->out_achans; i++) {
904  lives_free(fltbuf[i]);
905  }
906  }
907  lives_free(fltbuf);
908  }
909  } else {
910  // PULLING AUDIO FROM AN AUDIO GENERATOR
911  // get float audio from gen, convert it to S16
912  float **fltbuf = NULL;
913  boolean pl_error = FALSE;
914  xbytes = nbytes;
915  numFramesToWrite = pulseFramesAvailable;
916 
917  if (mainw->agen_needs_reinit) pl_error = TRUE;
918  else {
919  fltbuf = (float **)lives_malloc(pulsed->out_achans * sizeof(float *));
920  for (int i = 0; i < pulsed->out_achans; i++) fltbuf[i] =
921  (float *)lives_calloc_safety(numFramesToWrite, sizeof(float));
922  if (!get_audio_from_plugin(fltbuf, pulsed->out_achans, pulsed->out_arate, numFramesToWrite, TRUE)) {
923  pl_error = TRUE;
924  }
925  }
926 
927  if (!pl_error) {
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));
932  pulsed->aPlayPtr->data = lives_calloc_safety(nbytes / 4 + 1, 4);
933  //g_print("realloc 2\n");
934  if (update_sbuffer) pulsed->sound_buffer = (void *)(pulsed->aPlayPtr->data);
935  if (pulsed->aPlayPtr->data) {
936  pulsed->aPlayPtr->max_size = nbytes;
937  } else {
938  pulsed->aPlayPtr->size = pulsed->aPlayPtr->max_size = 0;
939  pl_error = TRUE;
940  }
941  }
942  if (!pl_error) pulsed->aPlayPtr->size = nbytes;
943  }
944 
945  // get back non-interleaved float fbuffer; rate and channels should match
946  if (pl_error) nbytes = 0;
947  else {
948  boolean memok = FALSE;
949 
951  memok = TRUE;
952  if (memok) {
953  // apply any audio effects with in_channels
954  ticks_t tc = mainw->currticks;
957  weed_layer_set_audio_data(layer, fltbuf, pulsed->out_arate, pulsed->out_achans, numFramesToWrite);
959  lives_free(fltbuf);
960  fltbuf = weed_layer_get_audio_data(layer, NULL);
961  weed_layer_set_audio_data(layer, NULL, 0, 0, 0);
962  weed_layer_free(layer);
963  }
964  }
965  }
966 
967  // streaming - we can push float audio to the playback plugin
968  pthread_mutex_lock(&mainw->vpp_stream_mutex);
970  (*mainw->vpp->render_audio_frame_float)(fltbuf, numFramesToWrite);
971  }
972  pthread_mutex_unlock(&mainw->vpp_stream_mutex);
973 
974  // copy effected audio back into pulsed->aPlayPtr->data
975  pulsed->sound_buffer = (uint8_t *)pulsed->aPlayPtr->data;
976 
977  sample_move_float_int(pulsed->sound_buffer, fltbuf, numFramesToWrite, 1.0,
978  pulsed->out_achans, PA_SAMPSIZE, 0, (capable->byte_order == LIVES_LITTLE_ENDIAN), FALSE, 1.0);
979 
980  if (fltbuf) {
981  for (register int i = 0; i < pulsed->out_achans; i++) lives_freep((void **)&fltbuf[i]);
982  }
983 
984  lives_free(fltbuf);
986  }
987 
988  if (mainw->record && !mainw->record_paused && mainw->ascrap_file != -1 && mainw->playing_file > 0) {
992  size_t rbytes = numFramesToWrite * mainw->files[mainw->ascrap_file]->achans *
994  pulse_flush_read_data(pulsed, mainw->ascrap_file,
996  pulsed->sound_buffer);
997  mainw->files[mainw->ascrap_file]->aseek_pos += rbytes;
998  }
999  /* // end from gen */
1000  }
1001 
1002  pulseFramesAvailable -= numFramesToWrite;
1003 
1004 #ifdef DEBUG_PULSE
1005  lives_printerr("pulseFramesAvailable == %ld\n", pulseFramesAvailable);
1006 #endif
1007 
1008  // playback from memory or file
1009  if (pulsed->playing_file > -1) clip_vol = lives_vol_from_linear(afile->vol);
1010  if (future_prefs->volume * clip_vol != pulsed->volume_linear) {
1011  // TODO: pa_threaded_mainloop_once_unlocked() (pa 13.0 +) ??
1012  pa_operation *paop;
1013  pavol = pa_sw_volume_from_linear(future_prefs->volume * clip_vol);
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);
1018  pulsed->volume_linear = future_prefs->volume * clip_vol;
1019  }
1020  }
1021  }
1022 
1023  // buffer is reused here, it's what we'll actually push to pulse
1024 
1025  if (sync_ready) sync_ready_ok(pulsed, nbytes);
1026 
1027  while (nbytes > 0) {
1028  if (nbytes < xbytes) xbytes = nbytes;
1029 
1030  if (!from_memory) {
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;
1034 #if 0
1035  }
1036  }
1037 #endif
1038 #else
1039  if (0) {
1040  // do nothing
1041  }
1042 #endif
1043  else {
1044  int ret = 0;
1045  if (pulsed->sound_buffer) {
1046 #if HAVE_PA_STREAM_BEGIN_WRITE
1047  xbytes = -1;
1048  // returns a buffer and a max size fo us to write to
1049  ret = pa_stream_begin_write(pulsed->pstream, (void **)&buffer, &xbytes);
1050  if (nbytes < xbytes) xbytes = nbytes;
1051 #else
1052  buffer = (uint8_t *)lives_calloc(nbytes, 1);
1053 #endif
1054  }
1055  if (!pulsed->sound_buffer || ret != 0 || !buffer) {
1056  sample_silence_pulse(pulsed, nsamples * pulsed->out_achans * (pulsed->out_asamps >> 3), nbytes);
1057 #ifdef DEBUG_PULSE
1058  g_print("pt X3\n");
1059 #endif
1060  return;
1061  }
1062  lives_memcpy(buffer, pulsed->sound_buffer + offs, xbytes);
1063  offs += xbytes;
1064  needs_free = TRUE;
1065  }
1066 
1068  if (pulsed->astream_fd != -1) audio_stream(buffer, xbytes, pulsed->astream_fd);
1070  append_to_audio_buffer16(buffer, xbytes / 2, 0);
1071  mainw->audio_frame_buffer->samples_filled += xbytes / 2;
1072  }
1073 
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);
1078 #else
1079  pa_stream_write(pulsed->pstream, buffer, xbytes, NULL, 0, PA_SEEK_RELATIVE);
1080 #endif
1081  if (!sync_ready)
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);
1085  } else {
1086  // from memory (e,g multitrack)
1087  if (pulsed->read_abuf > -1 && !pulsed->mute) {
1088  int ret = 0;
1089 #if HAVE_PA_STREAM_BEGIN_WRITE
1090  xbytes = -1;
1091  ret = pa_stream_begin_write(pulsed->pstream, (void **)&shortbuffer, &xbytes);
1092 #endif
1093  if (nbytes < xbytes) xbytes = nbytes;
1094 #if !HAVE_PA_STREAM_BEGIN_WRITE
1095  shortbuffer = (short *)lives_calloc(xbytes);
1096 #endif
1097  if (!shortbuffer || ret != 0) {
1098  sample_silence_pulse(pulsed, nsamples * pulsed->out_achans * (pulsed->out_asamps >> 3), nbytes);
1099 #ifdef DEBUG_PULSE
1100  g_print("pt X4\n");
1101 #endif
1102  return;
1103  }
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);
1108 #else
1109  pa_stream_write(pulsed->pstream, shortbuffer, xbytes, NULL, 0, PA_SEEK_RELATIVE);
1110 #endif
1111  if (!sync_ready)
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);
1115  } else {
1116  sample_silence_pulse(pulsed, xbytes, xbytes);
1117  }
1118  }
1119  nbytes -= xbytes;
1120  }
1121 
1122  if (needs_free && pulsed->sound_buffer != pulsed->aPlayPtr->data && pulsed->sound_buffer) {
1123  lives_freep((void **)&pulsed->sound_buffer);
1124  }
1125 
1126  fwd_seek_pos = pulsed->real_seek_pos = pulsed->seek_pos;
1127 
1128  if (pulseFramesAvailable) {
1129 #ifdef DEBUG_PULSE
1130  lives_printerr("buffer underrun of %ld frames\n", pulseFramesAvailable);
1131 #endif
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);
1135  }
1136 } else {
1137 #ifdef DEBUG_PULSE
1138  if (pulsed->state == PA_STREAM_UNCONNECTED || pulsed->state == PA_STREAM_CREATING)
1139  LIVES_INFO("pulseaudio stream UNCONNECTED or CREATING");
1140  else
1141  LIVES_WARN("pulseaudio stream FAILED or TERMINATED");
1142 #endif
1143 }
1144 #ifdef DEBUG_PULSE
1145 lives_printerr("done\n");
1146 #endif
1147 }
1148 
1149 
1150 size_t pulse_flush_read_data(pulse_driver_t *pulsed, int fileno, size_t rbytes, boolean rev_endian, void *data) {
1151  // prb is how many bytes to write, with rbytes as the latest addition
1152 
1153  short *gbuf;
1154  size_t bytes_out, frames_out, bytes = 0;
1155  void *holding_buff;
1156 
1157  float out_scale;
1158  int swap_sign;
1159 
1160  lives_clip_t *ofile;
1161 
1162  if (!data) data = prbuf;
1163 
1164  if (mainw->agen_key == 0 && !mainw->agen_needs_reinit) {
1165  if (prb == 0 || mainw->rec_samples == 0) return 0;
1166  if (prb <= PULSE_READ_BYTES * 2) {
1167  gbuf = (short *)data;
1168  } else {
1169  gbuf = (short *)lives_malloc(prb);
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);
1173  }
1174  ofile = afile;
1175  } else {
1176  if (rbytes == 0) return 0;
1177  if (fileno == -1) return 0;
1178  gbuf = (short *)data;
1179  prb = rbytes;
1180  ofile = mainw->files[fileno];
1181  }
1182 
1183  if (mainw->agen_key == 0 && !mainw->agen_needs_reinit) {
1184  out_scale = (float)pulsed->in_arate / (float)ofile->arate;
1185  } else out_scale = 1.;
1186 
1187  swap_sign = ofile->signed_endian & AFORM_UNSIGNED;
1188 
1189  frames_out = (size_t)((double)((prb / (ofile->asampsize >> 3) / ofile->achans)) / out_scale);
1190 
1191  if (mainw->agen_key == 0 && !mainw->agen_needs_reinit) {
1192  if (frames_out != pulsed->chunk_size) pulsed->chunk_size = frames_out;
1193  }
1194 
1195  bytes_out = frames_out * ofile->achans * (ofile->asampsize >> 3);
1196 
1197  holding_buff = lives_malloc(bytes_out);
1198 
1199  if (!holding_buff) {
1200  if (gbuf != (short *)data) lives_free(gbuf);
1201  prb = 0;
1202  return 0;
1203  }
1204 
1205  if (ofile->asampsize == 16) {
1206  sample_move_d16_d16((short *)holding_buff, gbuf, frames_out, prb, out_scale, ofile->achans, pulsed->in_achans,
1207  pulsed->reverse_endian ? SWAP_L_TO_X : 0, swap_sign ? SWAP_S_TO_U : 0);
1208  } else {
1209  sample_move_d16_d8((uint8_t *)holding_buff, gbuf, frames_out, prb, out_scale, ofile->achans, pulsed->in_achans,
1210  swap_sign ? SWAP_S_TO_U : 0);
1211  }
1212 
1213  if (gbuf != (short *)data) lives_free(gbuf);
1214 
1215  prb = 0;
1216 
1217  if (mainw->rec_samples > 0) {
1218  if (frames_out > mainw->rec_samples) frames_out = mainw->rec_samples;
1219  mainw->rec_samples -= frames_out;
1220  }
1221 
1222  if (!THREADVAR(bad_aud_file)) {
1223  size_t target = frames_out * (ofile->asampsize / 8) * ofile->achans, bytes;
1224  // use write not lives_write - because of potential threading issues
1225  bytes = write(mainw->aud_rec_fd, holding_buff, target);
1226  if (bytes > 0) {
1227  uint64_t chk = (mainw->aud_data_written & AUD_WRITE_CHECK);
1228  mainw->aud_data_written += bytes;
1230  add_to_ascrap_mb(bytes);
1232  }
1233  if (bytes < target) THREADVAR(bad_aud_file) = filename_from_fd(NULL, mainw->aud_rec_fd);
1234  }
1235 
1236  lives_free(holding_buff);
1237 
1238  return bytes;
1239 }
1240 
1241 
1242 static void pulse_audio_read_process(pa_stream * pstream, size_t nbytes, void *arg) {
1243  // read nsamples from pulse buffer, and then possibly write to mainw->aud_rec_fd
1244 
1245  // this is the callback from pulse when we are recording or playing external audio
1246 
1247  pulse_driver_t *pulsed = (pulse_driver_t *)arg;
1248  float out_scale;
1249  size_t frames_out, nsamples;
1250  void *data;
1251  size_t rbytes = nbytes, zbytes;
1252 
1253  pulsed->pstream = pstream;
1254 
1255  if (pulsed->is_corked) return;
1256 
1257  if (!pulsed->in_use || (mainw->playing_file < 0 && prefs->audio_src == AUDIO_SRC_EXT) || mainw->effects_paused) {
1258  pa_stream_peek(pulsed->pstream, (const void **)&data, &rbytes);
1259  if (rbytes > 0) {
1260  //g_print("PVAL %d\n", (*(uint8_t *)data & 0x80) >> 7);
1261  pa_stream_drop(pulsed->pstream);
1262  }
1263  prb = 0;
1264  if (pulsed->in_use)
1265  pulsed->extrausec += ((double)nbytes / (double)(pulsed->out_arate) * 1000000.
1266  / (double)(pulsed->out_achans * pulsed->out_asamps >> 3) + .5);
1267  return;
1268  }
1269 
1270  zbytes = pa_stream_readable_size(pulsed->pstream);
1271 
1272  if (zbytes == 0) {
1273  //g_print("nothing to read from PA\n");
1274  return;
1275  }
1276 
1277  if (pa_stream_peek(pulsed->pstream, (const void **)&data, &rbytes)) {
1278  return;
1279  }
1280 
1281  if (!data) {
1282  if (rbytes > 0) {
1283  pa_stream_drop(pulsed->pstream);
1284  }
1285  return;
1286  }
1287 
1288  if (!mainw->fs && !mainw->faded && !mainw->multitrack && mainw->ext_audio_mon)
1289  lives_toggle_tool_button_set_active(LIVES_TOGGLE_TOOL_BUTTON(mainw->ext_audio_mon), (*(uint8_t *)data & 0x80) >> 7);
1290 
1291  // time interpolation
1292  pulsed->extrausec += ((double)rbytes / (double)(pulsed->out_arate) * 1000000.
1293  / (double)(pulsed->out_achans * pulsed->out_asamps >> 3) + .5);
1294 
1295  pthread_mutex_lock(&mainw->audio_filewriteend_mutex);
1296 
1297  if (pulsed->playing_file == -1) {
1298  out_scale = 1.0; // just listening, no recording
1299  } else {
1300  out_scale = (float)afile->arate / (float)pulsed->in_arate; // recording to ascrap_file
1301  }
1302 
1303  if (mainw->record && mainw->record_paused && prb > 0) {
1304  // flush audio when recording is paused
1305  if (prb <= PULSE_READ_BYTES * 2) {
1306  lives_memcpy(&prbuf[prb - rbytes], data, rbytes);
1307  pulse_flush_read_data(pulsed, pulsed->playing_file, prb, pulsed->reverse_endian, prbuf);
1308  } else {
1309  pulse_flush_read_data(pulsed, pulsed->playing_file, rbytes, pulsed->reverse_endian, data);
1310  }
1311  }
1312 
1313  if (pulsed->playing_file == -1 || (mainw->record && mainw->record_paused)) prb = 0;
1314  else prb += rbytes;
1315 
1316  frames_out = (size_t)((double)((prb / (pulsed->in_asamps >> 3) / pulsed->in_achans)) / out_scale + .5);
1317 
1318  nsamples = (size_t)((double)((rbytes / (pulsed->in_asamps >> 3) / pulsed->in_achans)) / out_scale + .5);
1319 
1320  // should really be frames_read here
1321  if (!pulsed->is_paused) {
1322  pulsed->frames_written += nsamples;
1323  }
1324 
1325  if (prefs->audio_src == AUDIO_SRC_EXT && (pulsed->playing_file == -1 || pulsed->playing_file == mainw->ascrap_file)) {
1326  // - (do not call this when recording ext window or voiceover)
1327 
1328  // in this case we read external audio, but maybe not record it
1329  // we may wish to analyse the audio for example, or push it to a video generator
1330  // or stream it to the video playback plugin
1331 
1332  if ((!mainw->video_seek_ready && prefs->ahold_threshold > pulsed->abs_maxvol_heard)
1334  // convert to float, apply any analysers
1335  boolean memok = TRUE;
1336  float **fltbuf = (float **)lives_malloc(pulsed->in_achans * sizeof(float *));
1337  register int i;
1338 
1339  size_t xnsamples = (size_t)(rbytes / (pulsed->in_asamps >> 3) / pulsed->in_achans);
1340 
1341  if (!fltbuf) {
1342  pthread_mutex_unlock(&mainw->audio_filewriteend_mutex);
1343  pa_stream_drop(pulsed->pstream);
1344  return;
1345  }
1346 
1347  for (i = 0; i < pulsed->in_achans; i++) {
1348  // convert s16 to non-interleaved float
1349  fltbuf[i] = (float *)lives_calloc(xnsamples, sizeof(float));
1350  if (!fltbuf[i]) {
1351  memok = FALSE;
1352  for (--i; i >= 0; i--) lives_free(fltbuf[i]);
1353  break;
1354  }
1355 
1356  pulsed->abs_maxvol_heard
1357  = sample_move_d16_float(fltbuf[i], (short *)(data) + i, xnsamples, pulsed->in_achans, FALSE, FALSE, 1.0);
1358 
1360  // if we have audio triggered gens., push audio to it
1361  append_to_audio_bufferf(fltbuf[i], xnsamples, i);
1362  if (i == pulsed->in_achans - 1) mainw->audio_frame_buffer->samples_filled += xnsamples;
1363  }
1364  }
1365 
1366  if (memok) {
1367  ticks_t tc = mainw->currticks;
1368  // apply any audio effects with in channels but no out channels (analysers)
1369 
1372  weed_layer_set_audio_data(layer, fltbuf, pulsed->in_arate, pulsed->in_achans, xnsamples);
1373  weed_apply_audio_effects_rt(layer, tc, TRUE, TRUE);
1374  lives_free(fltbuf);
1375  fltbuf = weed_layer_get_audio_data(layer, NULL);
1376  weed_layer_free(layer);
1377  }
1378  // stream audio to video playback plugin if appropriate (probably needs retesting...)
1379  pthread_mutex_lock(&mainw->vpp_stream_mutex);
1381  (*mainw->vpp->render_audio_frame_float)(fltbuf, xnsamples);
1382  }
1383  pthread_mutex_unlock(&mainw->vpp_stream_mutex);
1384  for (i = 0; i < pulsed->in_achans; i++) {
1385  lives_free(fltbuf[i]);
1386  }
1387  }
1388 
1389  lives_freep((void **)&fltbuf);
1390  }
1391  }
1392 
1393  if (pulsed->playing_file == -1 || (mainw->record && mainw->record_paused) || pulsed->is_paused) {
1394  pa_stream_drop(pulsed->pstream);
1395  if (pulsed->is_paused) {
1396  // This is NECESSARY to reduce / eliminate huge latencies.
1397 
1398  // TODO: pa_threaded_mainloop_once_unlocked() (pa 13.0 +)
1399  pa_operation *paop = pa_stream_flush(pulsed->pstream, NULL,
1400  NULL); // if not recording, flush the rest of audio (to reduce latency)
1401  pa_operation_unref(paop);
1402  }
1403  pthread_mutex_unlock(&mainw->audio_filewriteend_mutex);
1404  return;
1405  }
1406 
1408  mainw->files[mainw->playing_file]->aseek_pos += rbytes;
1409  if (mainw->ascrap_file != -1 && !mainw->record_paused) mainw->files[mainw->ascrap_file]->aseek_pos += rbytes;
1410 
1411  pulsed->seek_pos += rbytes;
1412 
1413  if (prb < PULSE_READ_BYTES && (mainw->rec_samples == -1 || frames_out < mainw->rec_samples)) {
1414  // buffer until we have enough
1415  lives_memcpy(&prbuf[prb - rbytes], data, rbytes);
1416  } else {
1417  if (prb <= PULSE_READ_BYTES * 2) {
1418  lives_memcpy(&prbuf[prb - rbytes], data, rbytes);
1419  pulse_flush_read_data(pulsed, pulsed->playing_file, prb, pulsed->reverse_endian, prbuf);
1420  } else {
1421  pulse_flush_read_data(pulsed, pulsed->playing_file, rbytes, pulsed->reverse_endian, data);
1422  }
1423  }
1424 
1425  pa_stream_drop(pulsed->pstream);
1426  pthread_mutex_unlock(&mainw->audio_filewriteend_mutex);
1427 
1428  if (mainw->rec_samples == 0 && mainw->cancelled == CANCEL_NONE) {
1429  mainw->cancelled = CANCEL_KEEP; // we wrote the required #
1430  }
1431 }
1432 
1433 
1434 void pulse_shutdown(void) {
1435  //g_print("pa shutdown\n");
1436  if (pcon) {
1437  //g_print("pa shutdown2\n");
1438  pa_context_disconnect(pcon);
1439  pa_context_unref(pcon);
1440  }
1441  if (pa_mloop) {
1442  pa_threaded_mainloop_stop(pa_mloop);
1443  pa_threaded_mainloop_free(pa_mloop);
1444  }
1445  pcon = NULL;
1446  pa_mloop = NULL;
1447 }
1448 
1449 
1450 void pulse_close_client(pulse_driver_t *pdriver) {
1451  if (pdriver->pstream) {
1452  pa_mloop_lock();
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);
1459  pa_mloop_unlock();
1460  }
1461  if (pdriver->pa_props) pa_proplist_free(pdriver->pa_props);
1462  pdriver->pa_props = NULL;
1463  pdriver->pstream = NULL;
1464 }
1465 
1466 
1467 int pulse_audio_init(void) {
1468  // initialise variables
1469  pulsed.in_use = FALSE;
1470  pulsed.mloop = pa_mloop;
1471  pulsed.con = pcon;
1472 
1473  //for (int j = 0; j < PULSE_MAX_OUTPUT_CHANS; j++) pulsed.volume.values[j] = pa_sw_volume_from_linear(future_prefs->volume);
1474  pulsed.volume_linear = future_prefs->volume;
1475  pulsed.state = (pa_stream_state_t)PA_STREAM_UNCONNECTED;
1476  pulsed.in_arate = 44100;
1477  pulsed.fd = -1;
1478  pulsed.seek_pos = pulsed.seek_end = pulsed.real_seek_pos = 0;
1479  pulsed.msgq = NULL;
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;
1497  //pulsed.pstream = NULL;
1498  pulsed.pa_props = NULL;
1499  pulsed.playing_file = -1;
1500  pulsed.sound_buffer = NULL;
1501  pulsed.extrausec = 0;
1502  return 0;
1503 }
1504 
1505 
1506 int pulse_audio_read_init(void) {
1507  // initialise variables
1508 #if PA_SW_CONNECTION
1509  int j;
1510 #endif
1511 
1512  pulsed_reader.in_use = FALSE;
1513  pulsed_reader.mloop = pa_mloop;
1514  pulsed_reader.con = pcon;
1515 
1516  //for (j = 0; j < PULSE_MAX_OUTPUT_CHANS; j++) pulsed_reader.volume.values[j] = pa_sw_volume_from_linear(future_prefs->volume);
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;
1535  return 0;
1536 }
1537 
1538 
1539 #if PA_SW_CONNECTION
1540 static void info_cb(pa_context * c, const pa_sink_input_info * i, int eol, void *userdata) {
1541  // would be great if this worked, but apparently it always returns NULL in i
1542  // for a hardware connection
1543 
1544  // TODO: get volume_writeable (pa 1.0+)
1545  pulse_driver_t *pdriver = (pulse_driver_t *)userdata;
1546  if (!i) return;
1547 
1548  pdrive->volume = i->volume;
1549  pdriver->volume_linear = pa_sw_volume_to_linear(i->volume.values[0]);
1550  pref_factory_float(PREF_MASTER_VOLUME, pdriver->volume_linear, TRUE);
1551  if (i->mute != mainw->mute) on_mute_activate(NULL, NULL);
1552 }
1553 #endif
1554 
1555 
1556 int pulse_driver_activate(pulse_driver_t *pdriver) {
1557  // create a new client and connect it to pulse server
1558  char *pa_clientname;
1559  char *mypid;
1560 
1561  pa_sample_spec pa_spec;
1562  pa_channel_map pa_map;
1563  pa_buffer_attr pa_battr;
1564 
1565  pa_operation *pa_op;
1566 
1567  if (pdriver->pstream) return 0;
1568 
1569  if (mainw->aplayer_broken) return 2;
1570 
1571  if (pdriver->is_output) {
1572  pa_clientname = "LiVES_audio_out";
1573  } else {
1574  pa_clientname = "LiVES_audio_in";
1575  }
1576 
1577  mypid = lives_strdup_printf("%d", capable->mainpid);
1578 
1579  pdriver->pa_props = pa_proplist_new();
1580 
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());
1584 
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);
1588 
1589  lives_free(mypid);
1590 
1591 #ifdef GUI_GTK
1592  pa_proplist_sets(pdriver->pa_props, PA_PROP_APPLICATION_LANGUAGE, pango_language_to_string(gtk_get_default_language()));
1593 #endif
1594 
1595 #ifdef GUI_QT
1596  QLocale ql;
1597  pa_proplist_sets(pdriver->pa_props, PA_PROP_APPLICATION_LANGUAGE,
1598  (QLocale::languageToString(ql.language())).toLocal8Bit().constData());
1599 #endif
1600 
1601  pa_channel_map_init_stereo(&pa_map);
1602 
1603  pa_spec.format = PA_SAMPLE_S16NE;
1604 
1605  pa_spec.channels = pdriver->out_achans = pdriver->in_achans;
1606 
1607  pdriver->in_asamps = pdriver->out_asamps = PA_SAMPSIZE;
1608  pdriver->out_signed = AFORM_SIGNED;
1609 
1610  if (capable->byte_order == LIVES_BIG_ENDIAN) {
1611  pdriver->out_endian = AFORM_BIG_ENDIAN;
1612  pa_spec.format = PA_SAMPLE_S16BE;
1613  } else {
1614  pdriver->out_endian = AFORM_LITTLE_ENDIAN;
1615  pa_spec.format = PA_SAMPLE_S16LE;
1616  }
1617 
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;
1622 
1624  // seek and fill the prefbuffer, then kill the thread loop and let pa take over. Must do the same on underflow though
1625  pa_battr.prebuf = 0;
1626  } else {
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;
1631  }
1632 
1633  pa_mloop_lock();
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);
1638  }
1639  pa_operation_unref(pa_op);
1640  }
1641 
1642  if (pulse_server_rate == 0) {
1643  pa_mloop_unlock();
1644  LIVES_WARN("Problem getting pulseaudio rate...expect more problems ahead.");
1645  return 1;
1646  }
1647 
1648  pa_spec.rate = pdriver->out_arate = pdriver->in_arate = pulse_server_rate;
1649 
1650  pdriver->pstream = pa_stream_new_with_proplist(pdriver->con, pa_clientname, &pa_spec, &pa_map, pdriver->pa_props);
1651 
1653 
1654  if (pdriver->is_output) {
1655  pa_volume_t pavol;
1656  pdriver->is_corked = TRUE;
1657 
1658  // set write callback
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);
1664 
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);
1669 #else
1670  pdriver->volume_linear = future_prefs->volume;
1671  pavol = pa_sw_volume_from_linear(pdriver->volume_linear);
1672  pa_cvolume_set(&pdriver->volume, pdriver->out_achans, pavol);
1673 
1674  // calling this may cause other streams to be interrupted temporarily
1675  // it seems impossible to avoid this
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);
1684 #endif
1685  pa_mloop_unlock();
1686 
1687  while (pa_stream_get_state(pdriver->pstream) != PA_STREAM_READY) {
1688  sched_yield();
1689  lives_usleep(prefs->sleep_time);
1690  }
1691 
1692  pdriver->volume_linear = -1;
1693 
1694 #if PA_SW_CONNECTION
1695  // get the volume from the server
1696  pa_op = pa_context_get_sink_info(pdriver->con, info_cb, &pdriver);
1697 
1698  while (pa_operation_get_state(pa_op) == PA_OPERATION_RUNNING) {
1699  sched_yield();
1700  lives_usleep(prefs->sleep_time);
1701  }
1702  pa_operation_unref(pa_op);
1703 #endif
1704  } else {
1705  // set read callback
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;
1711  prb = 0;
1712 
1713  pa_stream_set_underflow_callback(pdriver->pstream, stream_underflow_callback, pdriver);
1714  pa_stream_set_overflow_callback(pdriver->pstream, stream_overflow_callback, pdriver);
1715 
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);
1719 
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));
1726 
1727  pa_mloop_unlock();
1728  while (pa_stream_get_state(pdriver->pstream) != PA_STREAM_READY) {
1729  sched_yield();
1730  lives_usleep(prefs->sleep_time);
1731  }
1732  }
1733 
1734  return 0;
1735 }
1736 
1737 
1738 //#define DEBUG_PULSE_CORK
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);
1743 #endif
1744  pdriver->is_corked = FALSE;
1746 }
1747 
1748 
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);
1753 #endif
1754  pdriver->is_corked = TRUE;
1756  pa_threaded_mainloop_signal(pa_mloop, 0);
1757 }
1758 
1759 
1760 void pulse_driver_uncork(pulse_driver_t *pdriver) {
1761  pa_operation *paop;
1762  pdriver->abs_maxvol_heard = 0.;
1763  if (!pdriver->is_corked) return;
1764  pa_mloop_lock();
1765  paop = pa_stream_cork(pdriver->pstream, 0, uncorked_cb, pdriver);
1766  pa_mloop_unlock();
1767  if (pdriver->is_output) {
1768  pa_operation_unref(paop);
1769  return; // let it uncork in its own time...
1770  }
1771  pa_operation_unref(paop);
1772 }
1773 
1774 
1775 void pulse_driver_cork(pulse_driver_t *pdriver) {
1776  pa_operation *paop;
1777  ticks_t timeout;
1778  lives_alarm_t alarm_handle;
1779  if (pdriver->is_corked) {
1780  //g_print("IS CORKED\n");
1781  return;
1782  }
1783 
1784  do {
1785  alarm_handle = lives_alarm_set(LIVES_SHORTEST_TIMEOUT);
1786  pa_mloop_lock();
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);
1790  }
1791  pa_operation_unref(paop);
1792  pa_mloop_unlock();
1793  lives_alarm_clear(alarm_handle);
1794  } while (!timeout);
1795 
1796  pa_mloop_lock();
1797  paop = pa_stream_flush(pdriver->pstream, NULL, NULL);
1798  pa_operation_unref(paop);
1799  pa_mloop_unlock();
1800 }
1801 
1802 
1804 
1805 LIVES_GLOBAL_INLINE pulse_driver_t *pulse_get_driver(boolean is_output) {
1806  if (is_output) return &pulsed;
1807  return &pulsed_reader;
1808 }
1809 
1810 
1811 LIVES_GLOBAL_INLINE volatile aserver_message_t *pulse_get_msgq(pulse_driver_t *pulsed) {
1812  if (pulsed->pulsed_died || mainw->aplayer_broken) return NULL;
1813  return pulsed->msgq;
1814 }
1815 
1816 
1817 boolean pa_time_reset(pulse_driver_t *pulsed, ticks_t offset) {
1818  int64_t usec;
1819  pa_operation *pa_op;
1820 
1821  if (!pulsed->pstream) return FALSE;
1822 
1823  pa_mloop_lock();
1824  pa_op = pa_stream_update_timing_info(pulsed->pstream, pulse_success_cb, pa_mloop);
1825 
1826  while (pa_operation_get_state(pa_op) == PA_OPERATION_RUNNING) {
1827  pa_threaded_mainloop_wait(pa_mloop);
1828  }
1829  pa_operation_unref(pa_op);
1830  pa_mloop_unlock();
1831 
1832  while (pa_stream_get_time(pulsed->pstream, (pa_usec_t *)&usec) < 0) {
1833  lives_nanosleep(10000);
1834  }
1835  pulsed->usec_start = usec - offset / USEC_TO_TICKS;
1836  pulsed->frames_written = 0;
1837  return TRUE;
1838 }
1839 
1840 
1844 ticks_t lives_pulse_get_time(pulse_driver_t *pulsed) {
1845  // get the time in ticks since either playback started
1846  volatile aserver_message_t *msg;
1847  int64_t usec;
1848  ticks_t timeout, retval;
1849  lives_alarm_t alarm_handle;
1850 
1851  msg = pulsed->msgq;
1852  if (msg && (msg->command == ASERVER_CMD_FILE_SEEK || msg->command == ASERVER_CMD_FILE_OPEN)) {
1853  alarm_handle = lives_alarm_set(LIVES_SHORT_TIMEOUT);
1854  while ((timeout = lives_alarm_check(alarm_handle)) > 0 && pulse_get_msgq(pulsed)) {
1855  lives_nanosleep(1000);
1856  }
1857  lives_alarm_clear(alarm_handle);
1858  if (timeout == 0) return -1;
1859  }
1860  if (!CLIP_HAS_AUDIO(pulsed->playing_file) && !(LIVES_IS_PLAYING && pulsed->read_abuf > -1)) {
1861  return -1;
1862  }
1863  while (pa_stream_get_time(pulsed->pstream, (pa_usec_t *)&usec) < 0) {
1864  lives_nanosleep(10000);
1865  }
1866  retval = (ticks_t)((usec - pulsed->usec_start) * USEC_TO_TICKS);
1867  if (retval == -1) retval = 0;
1868  return retval;
1869 }
1870 
1871 
1872 double lives_pulse_get_pos(pulse_driver_t *pulsed) {
1873  // get current time position (seconds) in audio file
1874  //return (double)pulsed->real_seek_pos / (double)(afile->arps * afile->achans * afile->asampsize / 8);
1875  if (pulsed->playing_file > -1) {
1876  return (double)(fwd_seek_pos)
1877  / (double)(afile->arps * afile->achans * afile->asampsize / 8);
1878  }
1879  // from memory
1880  return (double)pulsed->frames_written / (double)pulsed->out_arate;
1881 }
1882 
1883 
1884 boolean pulse_audio_seek_frame(pulse_driver_t *pulsed, double frame) {
1885  // seek to frame "frame" in current audio file
1886  // position will be adjusted to (floor) nearest sample
1887  int64_t seekstart;
1888  double fps;
1889 
1890  if (frame > afile->frames && afile->frames > 0) frame = afile->frames;
1891  if (LIVES_IS_PLAYING) fps = fabs(afile->pb_fps);
1892  else fps = afile->fps;
1893 
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;
1898 
1899  /* g_print("vals %ld and %ld %d\n", mainw->currticks, mainw->startticks, afile->arate); */
1900  /* g_print("bytes %f %f %d %ld %f\n", frame, afile->fps, LIVES_IS_PLAYING, seekstart, */
1901  /* (double)seekstart / (double)afile->arate / 4.); */
1902  pulse_audio_seek_bytes(pulsed, seekstart, afile);
1903  return TRUE;
1904 }
1905 
1906 
1907 int64_t pulse_audio_seek_bytes(pulse_driver_t *pulsed, int64_t bytes, lives_clip_t *sfile) {
1908  // seek to position "bytes" in current audio file
1909  // position will be adjusted to (floor) nearest sample
1910 
1911  // if the position is > size of file, we will seek to the end of the file
1912  volatile aserver_message_t *pmsg;
1913  int qnt;
1914 
1915  // set this here so so that pulse_get_rev_avals returns the forward seek position
1916  fwd_seek_pos = bytes;
1917 
1918  if (!pulsed->is_corked) {
1919  ticks_t timeout;
1921  pmsg = pulse_get_msgq(pulsed);
1922  while (pmsg && pmsg->command != ASERVER_CMD_FILE_SEEK && (timeout = lives_alarm_check(alarm_handle)) > 0) {
1923  lives_nanosleep(1000);
1924  pmsg = pulse_get_msgq(pulsed);
1925  }
1926  lives_alarm_clear(alarm_handle);
1927 
1928  if (timeout == 0 || pulsed->playing_file == -1) {
1929  if (timeout == 0) LIVES_WARN("PA connect timed out");
1930  return 0;
1931  }
1932  }
1933 
1934  if (bytes < 0) bytes = 0;
1935  if (bytes > sfile->afilesize) bytes = sfile->afilesize;
1936 
1937  qnt = sfile->achans * (sfile->asampsize >> 3);
1938  bytes = ALIGN_CEIL64((int64_t)bytes, qnt);
1939 
1940  pulse_message2.command = ASERVER_CMD_FILE_SEEK;
1941  pulse_message2.next = NULL;
1942  pulse_message2.data = lives_strdup_printf("%"PRId64, bytes);
1943  pulse_message2.tc = 0;
1944  if (!pulsed->msgq) pulsed->msgq = &pulse_message2;
1945  else pulsed->msgq->next = &pulse_message2;
1946  return bytes;
1947 }
1948 
1949 
1950 boolean pulse_try_reconnect(void) {
1951  lives_alarm_t alarm_handle;
1952  do_threaded_dialog(_("Resetting pulseaudio connection..."), FALSE);
1953 
1954  pulse_shutdown();
1955  mainw->pulsed = NULL;
1956  if (prefs->pa_restart && !prefs->vj_mode) {
1957  char *com = lives_strdup_printf("%s %s", EXEC_PULSEAUDIO, prefs->pa_start_opts);
1958  lives_system(com, TRUE);
1959  lives_free(com);
1960  } else lives_system("pulseaudio -k", TRUE);
1961  alarm_handle = lives_alarm_set(LIVES_SHORT_TIMEOUT);
1962  while (lives_alarm_check(alarm_handle) > 0) {
1963  sched_yield();
1964  lives_usleep(prefs->sleep_time);
1966  }
1967  lives_alarm_clear(alarm_handle);
1968  if (!lives_pulse_init(9999)) {
1970  goto err123; // init server failed
1971  }
1972  pulse_audio_init(); // reset vars
1973  pulse_audio_read_init(); // reset vars
1974  mainw->pulsed = pulse_get_driver(TRUE);
1975  if (pulse_driver_activate(mainw->pulsed)) { // activate driver
1976  goto err123;
1977  }
1979  // create reader connection now, if permanent
1980  pulse_rec_audio_to_clip(-1, -1, RECA_EXTERNAL);
1981  }
1983  d_print(_("\nConnection to pulseaudio was reset.\n"));
1984  return TRUE;
1985 
1986 err123:
1988  mainw->pulsed = NULL;
1990  return FALSE;
1991 }
1992 
1993 
2000 void pulse_aud_pb_ready(int fileno) {
2001  char *tmpfilename = NULL;
2002  lives_clip_t *sfile = mainw->files[fileno];
2003  int asigned = !(sfile->signed_endian & AFORM_UNSIGNED);
2004  int aendian = !(sfile->signed_endian & AFORM_BIG_ENDIAN);
2005 
2006  lives_freep((void **) & (mainw->pulsed->aPlayPtr->data));
2007  mainw->pulsed->aPlayPtr->size = mainw->pulsed->aPlayPtr->max_size = 0;
2008  if (mainw->pulsed) pulse_driver_uncork(mainw->pulsed);
2009 
2010  // called at pb start and rec stop (after rec_ext_audio)
2011  if (mainw->pulsed && mainw->aud_rec_fd == -1) {
2012  mainw->pulsed->is_paused = FALSE;
2013  mainw->pulsed->mute = mainw->mute;
2016  mainw->pulsed->loop = AUDIO_LOOP_PINGPONG;
2017  else mainw->pulsed->loop = AUDIO_LOOP_FORWARD;
2018  } else mainw->pulsed->loop = AUDIO_LOOP_NONE;
2019  if (sfile->achans > 0 && (!mainw->preview || (mainw->preview && mainw->is_processing)) &&
2020  (sfile->laudio_time > 0. || sfile->opening ||
2021  (mainw->multitrack && mainw->multitrack->is_rendering &&
2022  lives_file_test((tmpfilename = lives_get_audio_file_name(fileno)), LIVES_FILE_TEST_EXISTS)))) {
2023  ticks_t timeout;
2024  lives_alarm_t alarm_handle;
2025 
2026  lives_freep((void **)&tmpfilename);
2027  mainw->pulsed->in_achans = sfile->achans;
2028  mainw->pulsed->in_asamps = sfile->asampsize;
2029  mainw->pulsed->in_arate = sfile->arate;
2030  mainw->pulsed->usigned = !asigned;
2031  mainw->pulsed->seek_end = sfile->afilesize;
2032  mainw->pulsed->seek_pos = 0;
2033 
2034  if ((aendian && (capable->byte_order == LIVES_BIG_ENDIAN)) || (!aendian && (capable->byte_order == LIVES_LITTLE_ENDIAN)))
2035  mainw->pulsed->reverse_endian = TRUE;
2036  else mainw->pulsed->reverse_endian = FALSE;
2037 
2038  alarm_handle = lives_alarm_set(LIVES_SHORTEST_TIMEOUT);
2039  while ((timeout = lives_alarm_check(alarm_handle)) > 0 && pulse_get_msgq(mainw->pulsed)) {
2040  sched_yield(); // wait for seek
2041  lives_usleep(prefs->sleep_time);
2042  }
2043  lives_alarm_clear(alarm_handle);
2044 
2045  if (timeout == 0) pulse_try_reconnect();
2046 
2047  if ((!mainw->multitrack || mainw->multitrack->is_rendering ||
2048  sfile->opening) && (!mainw->event_list || mainw->record || (mainw->preview && mainw->is_processing))) {
2049  // tell pulse server to open audio file and start playing it
2050  pulse_message.command = ASERVER_CMD_FILE_OPEN;
2051  pulse_message.data = lives_strdup_printf("%d", fileno);
2052  pulse_message.next = NULL;
2053  mainw->pulsed->msgq = &pulse_message;
2054  pulse_audio_seek_bytes(mainw->pulsed, sfile->aseek_pos, sfile);
2055  if (seek_err) {
2056  if (pulse_try_reconnect()) pulse_audio_seek_bytes(mainw->pulsed, sfile->aseek_pos, sfile);
2057  }
2058  mainw->rec_aclip = fileno;
2059  mainw->rec_avel = sfile->pb_fps / sfile->fps;
2060  mainw->rec_aseek = (double)sfile->aseek_pos / (double)(sfile->arps * sfile->achans * (sfile->asampsize / 8));
2061  }
2062  }
2063  if (mainw->agen_key != 0 && !mainw->multitrack) mainw->pulsed->in_use = TRUE; // audio generator is active
2064  }
2065 }
2066 
2067 #undef afile
2068 
2069 #endif
2070 
lives_freep
boolean lives_freep(void **ptr)
Definition: utils.c:1411
LIVES_GLOBAL_INLINE
#define LIVES_GLOBAL_INLINE
Definition: main.h:239
AFORM_UNSIGNED
#define AFORM_UNSIGNED
Definition: main.h:786
mainwindow::startticks
volatile ticks_t startticks
effective ticks when current frame was (should have been) displayed
Definition: mainwindow.h:997
LIVES_IS_PLAYING
#define LIVES_IS_PLAYING
Definition: main.h:840
get_audio_from_plugin
boolean get_audio_from_plugin(float **fbuffer, int nchans, int arate, int nsamps, boolean is_audio_thread)
Definition: audio.c:3332
lives_get_current_playback_ticks
ticks_t lives_get_current_playback_ticks(ticks_t origsecs, ticks_t origusecs, lives_time_source_t *time_source)
Definition: utils.c:1481
add_to_ascrap_mb
void add_to_ascrap_mb(uint64_t bytes)
Definition: saveplay.c:5225
mainwindow::effects_paused
boolean effects_paused
Definition: mainwindow.h:1055
sample_move_d16_d8
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
Definition: audio.c:617
ASERVER_CMD_FILE_SEEK
#define ASERVER_CMD_FILE_SEEK
Definition: audio.h:59
PRId64
#define PRId64
Definition: machinestate.h:169
lives_free
#define lives_free
Definition: machinestate.h:52
lives_clip_t::aseek_pos
volatile off64_t aseek_pos
audio seek posn. (bytes) for when we switch clips
Definition: main.h:1064
LIVES_WARN
#define LIVES_WARN(x)
Definition: main.h:1862
sample_move_d16_d16
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
Definition: audio.c:524
mainwindow::rec_samples
int64_t rec_samples
Definition: mainwindow.h:1527
lives_malloc
#define lives_malloc
Definition: machinestate.h:46
mainwindow::is_ready
boolean is_ready
Definition: mainwindow.h:787
has_audio_filters
boolean has_audio_filters(lives_af_t af_type)
Definition: effects-weed.c:3859
lives_read_buffered_eof
boolean lives_read_buffered_eof(int fd)
Definition: utils.c:1170
mainwindow::record
volatile boolean record
Definition: mainwindow.h:794
_vid_playback_plugin::render_audio_frame_float
boolean(* render_audio_frame_float)(float **audio, int nsamps)
Definition: plugins.h:175
lives_get_audio_file_name
LIVES_GLOBAL_INLINE char * lives_get_audio_file_name(int fnum)
Definition: audio.c:55
AFORM_LITTLE_ENDIAN
#define AFORM_LITTLE_ENDIAN
Definition: main.h:784
check_for_disk_space
boolean check_for_disk_space(boolean fullcheck)
Definition: saveplay.c:5416
USEC_TO_TICKS
#define USEC_TO_TICKS
multiplying factor uSec -> ticks_t (def. 100)
Definition: mainwindow.h:38
weed_layer_new
LIVES_GLOBAL_INLINE weed_layer_t * weed_layer_new(int layer_type)
Definition: colourspace.c:9655
SWAP_X_TO_L
#define SWAP_X_TO_L
endian swapping
Definition: audio.h:19
mainwindow::current_file
int current_file
Definition: mainwindow.h:727
IS_VALID_CLIP
#define IS_VALID_CLIP(clip)
Definition: main.h:808
mainwindow::vpp
_vid_playback_plugin * vpp
video plugin
Definition: mainwindow.h:1572
lives_audio_buf_t::samples_filled
volatile size_t samples_filled
number of samples filled (readonly client)
Definition: audio.h:124
lives_toggle_tool_button_set_active
WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_tool_button_set_active(LiVESToggleToolButton *button, boolean active)
Definition: widget-helper.c:4525
mainwindow::preview
boolean preview
Definition: mainwindow.h:757
effects.h
ASERVER_CMD_FILE_CLOSE
#define ASERVER_CMD_FILE_CLOSE
Definition: audio.h:58
lives_lseek_buffered_rdonly_absolute
off_t lives_lseek_buffered_rdonly_absolute(int fd, off_t offset)
Definition: utils.c:907
LIVES_ERROR
#define LIVES_ERROR(x)
Definition: main.h:1870
prefs
_prefs * prefs
Definition: preferences.h:847
audio_stream
LIVES_GLOBAL_INLINE void audio_stream(void *buff, size_t nbytes, int fd)
Definition: audio.c:3964
mainwindow::video_seek_ready
volatile boolean video_seek_ready
Definition: mainwindow.h:939
LIVES_INFO
#define LIVES_INFO(x)
Definition: main.h:1854
mainwindow::loop_video
LiVESWidget * loop_video
Definition: mainwindow.h:1173
LIVES_DIRECTION_FORWARD
@ LIVES_DIRECTION_FORWARD
Definition: main.h:854
SWAP_U_TO_S
#define SWAP_U_TO_S
sign swapping
Definition: audio.h:15
_prefs::ahold_threshold
float ahold_threshold
Definition: preferences.h:440
lives_alarm_clear
boolean lives_alarm_clear(lives_alarm_t alarm_handle)
Definition: utils.c:1732
TICKS_PER_SECOND_DBL
#define TICKS_PER_SECOND_DBL
actually microseconds / 100.
Definition: mainwindow.h:37
pad_with_silence
boolean pad_with_silence(int out_fd, void *buff, off64_t oins_size, int64_t ins_size, int asamps, int aunsigned, boolean big_endian)
Definition: audio.c:1159
lives_random
LIVES_GLOBAL_INLINE uint64_t lives_random(void)
Definition: machinestate.c:58
append_to_audio_buffer16
void append_to_audio_buffer16(void *src, uint64_t nsamples, int channum)
Definition: audio.c:118
mainwindow::ext_audio_mon
LiVESWidget * ext_audio_mon
Definition: mainwindow.h:1359
lives_buffered_rdonly_set_reversed
boolean lives_buffered_rdonly_set_reversed(int fd, boolean val)
Definition: utils.c:681
capability::mainpid
pid_t mainpid
Definition: main.h:591
mainwindow::agen_needs_reinit
volatile boolean agen_needs_reinit
Definition: mainwindow.h:1650
fastrand
LIVES_GLOBAL_INLINE uint64_t fastrand(void)
Definition: machinestate.c:40
ALIGN_CEIL64
#define ALIGN_CEIL64(a, b)
Definition: main.h:289
AUDIO_LOOP_NONE
@ AUDIO_LOOP_NONE
Definition: audio.h:146
lives_alarm_t
int lives_alarm_t
Definition: mainwindow.h:696
lives_nanosleep
#define lives_nanosleep(nanosec)
Definition: machinestate.h:307
mainwindow::event_list
weed_event_t * event_list
current event_list, for recording
Definition: mainwindow.h:803
lives_open_buffered_rdonly
int lives_open_buffered_rdonly(const char *pathname)
Definition: utils.c:636
ticks_t
int64_t ticks_t
Definition: main.h:97
mainwindow::rec_aclip
volatile int rec_aclip
recording values - to be inserted at the following video frame
Definition: mainwindow.h:967
do_error_dialog
LIVES_GLOBAL_INLINE LiVESResponseType do_error_dialog(const char *text)
Definition: dialogs.c:749
_prefs::pa_start_opts
char pa_start_opts[255]
Definition: preferences.h:473
LIVES_SHORTEST_TIMEOUT
#define LIVES_SHORTEST_TIMEOUT
Definition: mainwindow.h:41
end_threaded_dialog
void end_threaded_dialog(void)
Definition: dialogs.c:3883
threaded_dialog_spin
void threaded_dialog_spin(double fraction)
Definition: dialogs.c:3823
EXEC_PULSEAUDIO
#define EXEC_PULSEAUDIO
Definition: mainwindow.h:392
TRUE
#define TRUE
Definition: videoplugin.h:59
_prefs::pa_restart
boolean pa_restart
Definition: preferences.h:474
lives_read_buffered
ssize_t lives_read_buffered(int fd, void *buf, ssize_t count, boolean allow_less)
Definition: utils.c:924
lives_memset
#define lives_memset
Definition: machinestate.h:61
mainwindow::whentostop
volatile lives_whentostop_t whentostop
Definition: mainwindow.h:929
weed_apply_audio_effects_rt
void weed_apply_audio_effects_rt(weed_layer_t *alayer, weed_timecode_t tc, boolean analysers_only, boolean is_audio_thread)
Definition: effects-weed.c:3743
THREADVAR
#define THREADVAR(var)
Definition: machinestate.h:531
mainwindow::loop_cont
volatile boolean loop_cont
Definition: mainwindow.h:764
mainwindow::cancelled
volatile lives_cancel_t cancelled
Definition: mainwindow.h:798
AUD_WRITE_CHECK
#define AUD_WRITE_CHECK
after recording this many bytes we check disk space (default 128MB)
Definition: audio.h:49
_prefs::audio_opts
volatile uint32_t audio_opts
Definition: preferences.h:254
lives_clip_t::fps
double fps
Definition: main.h:893
sample_move_d16_float
float sample_move_d16_float(float *dst, short *src, uint64_t nsamples, uint64_t src_skip, int is_unsigned, boolean rev_endian, float vol)
Definition: audio.c:677
callbacks.h
lives_clip_t::cb_src
int cb_src
source clip for clipboard; for other clips, may be used to hold some temporary linkage
Definition: main.h:1086
_prefs::audio_src
int audio_src
Definition: preferences.h:204
mainwindow::fps_mini_measure
frames_t fps_mini_measure
show fps stats during playback
Definition: mainwindow.h:779
capable
capability * capable
Definition: main.h:627
mainwindow::preview_rendering
boolean preview_rendering
Definition: mainwindow.h:758
d_print
void d_print(const char *fmt,...)
Definition: utils.c:2542
mainwindow::rec_aseek
volatile double rec_aseek
Definition: mainwindow.h:969
mainwindow::avseek_mutex
pthread_mutex_t avseek_mutex
Definition: mainwindow.h:938
sample_move_d8_d16
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)
Definition: audio.c:459
lives_clip_t::signed_endian
uint32_t signed_endian
bitfield
Definition: main.h:909
mainwindow::origsecs
ticks_t origsecs
playback start seconds - subtracted from all other ticks to keep numbers smaller
Definition: mainwindow.h:1000
mainwindow::playing_sel
boolean playing_sel
list of set names in current workdir, mau be NULL
Definition: mainwindow.h:756
do_pulse_lost_conn_error
LIVES_GLOBAL_INLINE void do_pulse_lost_conn_error(void)
Definition: dialogs.c:4518
STOP_ON_AUD_END
@ STOP_ON_AUD_END
Definition: main.h:695
switch_aud_to_none
void switch_aud_to_none(boolean set_pref)
Definition: utils.c:4001
lives_clip_t::afilesize
size_t afilesize
Definition: main.h:912
mainwindow::playing_file
int playing_file
which number file we are playing (or -1) [generally mainw->current_file]
Definition: mainwindow.h:943
ASERVER_CMD_PROCESSED
#define ASERVER_CMD_PROCESSED
asynch msging
Definition: audio.h:56
lives_buffered_offset
off_t lives_buffered_offset(int fd)
Definition: utils.c:1364
mainwindow::files
lives_clip_t * files[MAX_FILES+1]
+1 for the clipboard
Definition: mainwindow.h:729
_future_prefs::volume
volatile float volume
audio volume level (for jack and pulse)
Definition: preferences.h:837
mainwindow::audio_seek_ready
volatile boolean audio_seek_ready
Definition: mainwindow.h:940
CANCEL_NONE
@ CANCEL_NONE
no cancel
Definition: main.h:701
PREF_MASTER_VOLUME
#define PREF_MASTER_VOLUME
Definition: preferences.h:1099
mainwindow::pulsed
void * pulsed
pulseaudio player
Definition: mainwindow.h:1463
lives_close_buffered
int lives_close_buffered(int fd)
Definition: utils.c:716
mainwindow::play_sequence
int play_sequence
currticks when last display was shown (used for fixed fps)
Definition: mainwindow.h:1013
weed_layer_set_audio_data
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)
Definition: colourspace.c:9681
on_mute_activate
void on_mute_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: callbacks.c:8399
do_threaded_dialog
void do_threaded_dialog(const char *trans_text, boolean has_cancel)
Definition: dialogs.c:3849
mainwindow::syncticks
ticks_t syncticks
adjustment to compensate for missed clock updates when switching time sources
Definition: mainwindow.h:1010
lives_clip_t::arps
int arps
audio physical sample rate (i.e the "normal" sample rate of the clip when played at 1,...
Definition: main.h:905
lives_strdup_printf
#define lives_strdup_printf(fmt,...)
Definition: support.c:27
mainwindow::ext_audio
volatile boolean ext_audio
using external video playback plugin to stream audio
Definition: mainwindow.h:774
lives_calloc
#define lives_calloc
Definition: machinestate.h:67
lives_clip_t::opening
boolean opening
Definition: main.h:946
mainwindow::audio_filewriteend_mutex
pthread_mutex_t audio_filewriteend_mutex
sync for ending writing audio to file
Definition: mainwindow.h:1503
weed_layer_t
weed_plant_t weed_layer_t
Definition: colourspace.h:71
append_to_audio_bufferf
void append_to_audio_bufferf(float *src, uint64_t nsamples, int channum)
Definition: audio.c:82
mainwindow::ascrap_file
int ascrap_file
scrap file for recording audio scraps
Definition: mainwindow.h:875
AUDIO_OPTS_FOLLOW_FPS
#define AUDIO_OPTS_FOLLOW_FPS
Definition: preferences.h:256
mainwindow::uflow_count
volatile int uflow_count
experimental values, primarily for testing
Definition: mainwindow.h:1761
sample_silence_stream
void sample_silence_stream(int nchans, int64_t nframes)
Definition: audio.c:421
mainwindow::faded
boolean faded
Definition: mainwindow.h:759
lives_memmove
#define lives_memmove
Definition: machinestate.h:64
aserver_message_t::data
volatile char * data
Definition: audio.h:65
lives_memcpy
#define lives_memcpy
Definition: machinestate.h:55
mainwindow::rec_avel
volatile double rec_avel
Definition: mainwindow.h:968
future_prefs
_future_prefs * future_prefs
Definition: preferences.h:848
AFORM_SIGNED
#define AFORM_SIGNED
Definition: main.h:783
mainwindow::multitrack
lives_mt * multitrack
holds a pointer to the entire multitrack environment; NULL in Clip Edit mode
Definition: mainwindow.h:1087
ASERVER_CMD_FILE_OPEN
#define ASERVER_CMD_FILE_OPEN
Definition: audio.h:57
lives_alarm_check
ticks_t lives_alarm_check(lives_alarm_t alarm_handle)
Definition: utils.c:1687
lives_vol_from_linear
#define lives_vol_from_linear(vol)
Definition: audio.h:269
LIVES_SHORT_TIMEOUT
#define LIVES_SHORT_TIMEOUT
Definition: mainwindow.h:42
lives_clip_t::laudio_time
double laudio_time
Definition: main.h:929
mainwindow::aud_rec_fd
int aud_rec_fd
fd of file we are recording audio to
Definition: mainwindow.h:1525
mainwindow::record_paused
volatile boolean record_paused
pause during recording
Definition: mainwindow.h:1557
filename_from_fd
char * filename_from_fd(char *val, int fd)
: return filename from an open fd, freeing val first
Definition: utils.c:60
AF_TYPE_ANY
@ AF_TYPE_ANY
Definition: effects.h:41
main.h
WEED_LAYER_TYPE_AUDIO
#define WEED_LAYER_TYPE_AUDIO
Definition: colourspace.h:222
mainwindow::play_end
frames_t play_end
Definition: mainwindow.h:931
SWAP_S_TO_U
#define SWAP_S_TO_U
signed to unsigned
Definition: audio.h:16
mainwindow::fs
boolean fs
Definition: mainwindow.h:762
_prefs::sleep_time
int sleep_time
Definition: preferences.h:176
AUDIO_SRC_EXT
#define AUDIO_SRC_EXT
Definition: preferences.h:206
_prefs::vj_mode
boolean vj_mode
Definition: preferences.h:459
aserver_message_t
Definition: audio.h:62
mainw
mainwindow * mainw
Definition: main.c:103
mainwindow::switch_during_pb
boolean switch_during_pb
Definition: mainwindow.h:792
AUDIO_LOOP_FORWARD
@ AUDIO_LOOP_FORWARD
Definition: audio.h:147
mainwindow::audio_frame_buffer
volatile lives_audio_buf_t * audio_frame_buffer
used for buffering / feeding audio to video generators
Definition: mainwindow.h:1697
_prefs::force_system_clock
boolean force_system_clock
Definition: preferences.h:366
capability::myname
char * myname
Definition: main.h:580
frames_t
int frames_t
Definition: main.h:99
lives_clip_t::pb_fps
double pb_fps
current playback rate, may vary from fps, can be 0. or negative
Definition: main.h:1007
CANCEL_KEEP
@ CANCEL_KEEP
user pressed 'Keep'
Definition: main.h:734
lives_system
int lives_system(const char *com, boolean allow_error)
Definition: utils.c:145
weed_layer_get_audio_data
LIVES_GLOBAL_INLINE float ** weed_layer_get_audio_data(weed_layer_t *layer, int *naudchans)
Definition: colourspace.c:13921
weed_layer_free
LIVES_GLOBAL_INLINE weed_layer_t * weed_layer_free(weed_layer_t *layer)
frees pixel_data for a layer, then the layer itself
Definition: colourspace.c:13883
CLIP_HAS_AUDIO
#define CLIP_HAS_AUDIO(clip)
Definition: main.h:817
mainwindow::audio_stretch
double audio_stretch
for fixed fps modes, the value is used to speed up / slow down audio
Definition: mainwindow.h:1015
mainwindow::fps_mini_ticks
ticks_t fps_mini_ticks
Definition: mainwindow.h:780
RECA_EXTERNAL
@ RECA_EXTERNAL
Definition: audio.h:200
mainwindow::aud_data_written
uint64_t aud_data_written
Definition: mainwindow.h:1720
lives_clip_t
corresponds to one clip in the GUI
Definition: main.h:877
mainwindow::is_processing
boolean is_processing
states
Definition: mainwindow.h:820
lives_calloc_safety
LIVES_GLOBAL_INLINE void * lives_calloc_safety(size_t nmemb, size_t xsize)
Definition: machinestate.c:603
sample_move_abuf_int16
int64_t sample_move_abuf_int16(short *obuf, int nchans, int nsamps, int out_arate)
copy audio data from cache into audio sound buffer
Definition: audio.c:993
effects-weed.h
mainwindow::pulsed_read
void * pulsed_read
Definition: mainwindow.h:1464
mainwindow::mute
boolean mute
Definition: mainwindow.h:770
do_abort_cancel_retry_dialog
LIVES_GLOBAL_INLINE LiVESResponseType do_abort_cancel_retry_dialog(const char *text)
Definition: dialogs.c:708
aserver_message_t::next
volatile struct _aserver_message_t * next
Definition: audio.h:66
CANCEL_AUD_END
@ CANCEL_AUD_END
video playback completed
Definition: main.h:737
mainwindow::currticks
volatile ticks_t currticks
wall clock time, updated whenever lives_get_*_ticks is called
Definition: mainwindow.h:1005
mainwindow::ping_pong
volatile boolean ping_pong
Definition: mainwindow.h:765
AUDIO_OPTS_FOLLOW_CLIPS
#define AUDIO_OPTS_FOLLOW_CLIPS
Definition: preferences.h:255
lives_clip_t::asampsize
int asampsize
audio sample size in bits (8 or 16)
Definition: main.h:908
mainwindow::agen_key
volatile int agen_key
which fx key is generating audio [1 based] (or 0 for none)
Definition: mainwindow.h:1649
mainwindow::vpp_stream_mutex
pthread_mutex_t vpp_stream_mutex
prevent from writing audio when stream is closing
Definition: mainwindow.h:1501
sample_move_float_int
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...
Definition: audio.c:793
lives_clip_t::arate
int arate
current audio playback rate (varies if the clip rate is changed)
Definition: main.h:906
_prefs::perm_audio_reader
boolean perm_audio_reader
Definition: preferences.h:426
FALSE
#define FALSE
Definition: videoplugin.h:60
clip_can_reverse
boolean clip_can_reverse(int clipno)
Definition: callbacks.c:4980
lives_alarm_set
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 ...
Definition: utils.c:1643
_
#define _(String)
Definition: support.h:44
aserver_message_t::command
volatile int command
Definition: audio.h:63
AUDIO_LOOP_PINGPONG
@ AUDIO_LOOP_PINGPONG
Definition: audio.h:148
do_error_dialogf
LiVESResponseType do_error_dialogf(const char *fmt,...)
Definition: dialogs.c:735
capability::byte_order
int byte_order
Definition: main.h:577
mainwindow::orignsecs
ticks_t orignsecs
usecs at start of playback - ditto
Definition: mainwindow.h:1001
lives_clip_t::achans
int achans
number of audio channels (0, 1 or 2)
Definition: main.h:907
AFORM_BIG_ENDIAN
#define AFORM_BIG_ENDIAN
Definition: main.h:787
SWAP_L_TO_X
#define SWAP_L_TO_X
local to other
Definition: audio.h:20
mainwindow::aplayer_broken
boolean aplayer_broken
Definition: mainwindow.h:1653
AF_TYPE_A
@ AF_TYPE_A
Definition: effects.h:42
NEVER_STOP
@ NEVER_STOP
Definition: main.h:693
pref_factory_float
boolean pref_factory_float(const char *prefidx, float newval, boolean permanent)
Definition: preferences.c:1192
mainwindow::foreign
boolean foreign
for external window capture
Definition: mainwindow.h:824
mainwindow::avseek_cond
pthread_cond_t avseek_cond
Definition: mainwindow.h:937
_prefs::show_dev_opts
boolean show_dev_opts
Definition: preferences.h:463