LiVES 3.2.0
resample.c
Go to the documentation of this file.
1// resample.c
2// LiVES
3// (c) G. Finch 2004 - 2020 <salsaman+lives@gmail.com>
4// released under the GNU GPL 3 or later
5// see file ../COPYING or www.gnu.org for licensing details
6
7// functions for reordering, resampling video and audio
8
9#include "main.h"
10#include "resample.h"
11#include "callbacks.h"
12#include "effects.h"
13#include "audio.h"
14#include "events.h"
15#include "cvirtual.h"
16
17static int reorder_width = 0;
18static int reorder_height = 0;
19static boolean reorder_leave_back = FALSE;
20
21void reorder_leave_back_set(boolean val) {reorder_leave_back = val;}
22
24
26 // quantise timecode to fps
27 if (in > (ticks_t)0) return ((((double)((ticks_t)((double)in / (double)TICKS_PER_SECOND_DBL * (double)fps + .5))) /
28 (double)fps)) * TICKS_PER_SECOND_DBL + .5; // quantise to frame timing
29
30 if (in < (ticks_t)0) return ((((double)((ticks_t)((double)in / (double)TICKS_PER_SECOND_DBL * (double)fps - .5))) /
31 (double)fps)) * TICKS_PER_SECOND_DBL - .5; // quantise to frame timing
32 return (ticks_t)0;
33}
34
36 if (in != 0) return (double)((ticks_t)((double)in / TICKS_PER_SECOND_DBL * fps + .000001)) / fps *
37 TICKS_PER_SECOND_DBL; // quantise to frame timing
38 return 0;
39}
40
41LIVES_GLOBAL_INLINE ticks_t q_dbl(double in, double fps) {
42 // quantise (double)in to fps
43 if (in > 0.) return ((ticks_t)((double)in * (double)fps + (double).5) / (double)fps) *
44 (ticks_t)TICKS_PER_SECOND; // quantise to frame timing
45 if (in < 0.) return ((ticks_t)((double)in * (double)fps - (double).5) / (double)fps) *
46 (ticks_t)TICKS_PER_SECOND; // quantise to frame timing
47 return (ticks_t)0;
48}
49
50
52LIVES_GLOBAL_INLINE size_t quant_asamps(double seek, int arate) {
53 size_t samps = (seek <= 0. || arate <= 0) ? 0 : (size_t)(seek * (double)arate + .99999);
54 return samps;
55}
56
58LIVES_GLOBAL_INLINE double quant_aseek(double seek, int arate) {
59 if (arate <= 0) return 0.;
60 else {
61 size_t samps = quant_asamps(seek, arate);
62 return (double)samps / (double)arate;
63 }
64}
65
66LIVES_GLOBAL_INLINE off_t quant_abytes(double seek, int arate, int achans, int asampsize) {
67 size_t samps = quant_asamps(seek, arate);
68 return samps * (size_t)(achans * asampsize);
69}
70
71
72LIVES_GLOBAL_INLINE int count_resampled_frames(int in_frames, double orig_fps, double resampled_fps) {
73 int res_frames;
74 if (resampled_fps < orig_fps) return ((res_frames = (int)((double)in_frames / orig_fps * resampled_fps)) < 1) ? 1 : res_frames;
75 else return ((res_frames = (int)((double)in_frames / orig_fps * resampled_fps + .49999)) < 1) ? 1 : res_frames;
76}
77
79
80boolean auto_resample_resize(int width, int height, double fps, int fps_num, int fps_denom, int arate,
81 int asigned, boolean swap_endian) {
82 // do a block atomic: resample audio, then resample video/resize or joint resample/resize
83
84 // TODO: check if we still need to letterbox here, or if the encoders handle that now
85
86 int current_file = mainw->current_file;
87 boolean audio_resampled = FALSE;
88 boolean video_resampled = FALSE;
89 boolean video_resized = FALSE;
90 boolean bad_header = FALSE;
91
92 int frames = cfile->frames;
93
94 reorder_leave_back = FALSE;
95
96 if (asigned != 0 || (arate > 0 && arate != cfile->arate) || swap_endian) {
97 cfile->undo1_int = arate;
98 cfile->undo2_int = cfile->achans;
99 cfile->undo3_int = cfile->asampsize;
100 cfile->undo1_uint = cfile->signed_endian;
101
102 if (asigned == 1 && (cfile->signed_endian & AFORM_UNSIGNED) == AFORM_UNSIGNED) cfile->undo1_uint ^= AFORM_UNSIGNED;
103 else if (asigned == 2 && (cfile->signed_endian & AFORM_UNSIGNED) != AFORM_UNSIGNED) cfile->undo1_uint |= AFORM_UNSIGNED;
104
105 if (swap_endian) {
106 if (cfile->signed_endian & AFORM_BIG_ENDIAN) cfile->undo1_uint ^= AFORM_BIG_ENDIAN;
107 else cfile->undo1_uint |= AFORM_BIG_ENDIAN;
108 }
109
110 on_resaudio_ok_clicked(NULL, NULL);
111 if (mainw->error) return FALSE;
112 audio_resampled = TRUE;
113 }
114
115 else {
116 cfile->undo1_int = cfile->arate;
117 cfile->undo2_int = cfile->achans;
118 cfile->undo3_int = cfile->asampsize;
119 cfile->undo4_int = cfile->arps;
120 cfile->undo1_uint = cfile->signed_endian;
121 }
122
123 if (fps_denom > 0) {
124 fps = (fps_num * 1.) / (fps_denom * 1.);
125 }
126 if (fps > 0. && fps != cfile->fps) {
127 // FPS CHANGE...
128 if ((width != cfile->hsize || height != cfile->vsize) && width * height > 0) {
129 // CHANGING SIZE..
130
131 if (fps > cfile->fps) {
132 // we will have more frames...
133 // ...do resize first
134 cfile->ohsize = cfile->hsize;
135 cfile->ovsize = cfile->vsize;
136
137 if (prefs->enc_letterbox) {
138 int iwidth = cfile->hsize, iheight = cfile->vsize;
139 calc_maxspect(width, height, &iwidth, &iheight);
140 width = iwidth;
141 height = iheight;
142 }
143
144 resize_all(mainw->current_file, width, height, cfile->img_type, TRUE, NULL, NULL);
145 realize_all_frames(mainw->current_file, _("Pulling frames"), FALSE);
146
147 cfile->hsize = width;
148 cfile->vsize = height;
149
150 if (!save_clip_value(mainw->current_file, CLIP_DETAILS_WIDTH, &cfile->hsize)) bad_header = TRUE;
151 if (!save_clip_value(mainw->current_file, CLIP_DETAILS_HEIGHT, &cfile->vsize)) bad_header = TRUE;
152 if (bad_header) do_header_write_error(mainw->current_file);
153
154 cfile->undo1_dbl = fps;
155 cfile->undo_start = 1;
156 cfile->undo_end = frames;
157
158 // now resample
159
160 // special "cheat" mode for LiVES
161 reorder_leave_back = TRUE;
162
163 reorder_width = width;
164 reorder_height = height;
165
167 on_resample_vid_ok(NULL, NULL);
168
169 reorder_leave_back = FALSE;
170 cfile->undo_action = UNDO_ATOMIC_RESAMPLE_RESIZE;
171 if (mainw->error) {
172 on_undo_activate(NULL, NULL);
173 return FALSE;
174 }
175
176 video_resized = TRUE;
177 video_resampled = TRUE;
178 } else {
179 // fewer frames
180 // do resample *with* resize
181 cfile->ohsize = cfile->hsize;
182 cfile->ovsize = cfile->vsize;
183 cfile->undo1_dbl = fps;
184
185 // another special "cheat" mode for LiVES
186 reorder_width = width;
187 reorder_height = height;
188
190 on_resample_vid_ok(NULL, NULL);
192
193 reorder_width = reorder_height = 0;
194 cfile->undo_action = UNDO_ATOMIC_RESAMPLE_RESIZE;
195 cfile->hsize = width;
196 cfile->vsize = height;
197
198 if (mainw->error) {
199 on_undo_activate(NULL, NULL);
200 return FALSE;
201 }
202 if (!save_clip_value(mainw->current_file, CLIP_DETAILS_WIDTH, &cfile->hsize)) bad_header = TRUE;
203 if (!save_clip_value(mainw->current_file, CLIP_DETAILS_HEIGHT, &cfile->vsize)) bad_header = TRUE;
204 if (bad_header) do_header_write_error(mainw->current_file);
205
206 video_resampled = TRUE;
207 video_resized = TRUE;
208 }
209 } else {
211 cfile->undo1_dbl = fps;
212 cfile->undo_start = 1;
213 cfile->undo_end = cfile->frames;
214
215 reorder_width = width;
216 reorder_height = height;
217
218 on_resample_vid_ok(NULL, NULL);
219
220 reorder_width = reorder_height = 0;
221 reorder_leave_back = FALSE;
222
223 if (audio_resampled) cfile->undo_action = UNDO_ATOMIC_RESAMPLE_RESIZE;
224 if (mainw->error) {
225 on_undo_activate(NULL, NULL);
226 return FALSE;
227 }
229 video_resampled = TRUE;
230 }
231 } else {
232 // NO FPS CHANGE
233 if ((width != cfile->hsize || height != cfile->vsize) && width * height > 0) {
234 // no fps change - just a normal resize
235 cfile->undo_start = 1;
236 cfile->undo_end = cfile->frames;
237 if (prefs->enc_letterbox) {
238 int iwidth = cfile->hsize, iheight = cfile->vsize;
239 calc_maxspect(width, height, &iwidth, &iheight);
240 width = iwidth;
241 height = iheight;
242 }
243
244 resize_all(mainw->current_file, width, height, cfile->img_type, TRUE, NULL, NULL);
245 realize_all_frames(mainw->current_file, _("Pulling frames"), FALSE);
246
247 cfile->hsize = width;
248 cfile->vsize = height;
249
250 if (!save_clip_value(mainw->current_file, CLIP_DETAILS_WIDTH, &cfile->hsize)) bad_header = TRUE;
251 if (!save_clip_value(mainw->current_file, CLIP_DETAILS_HEIGHT, &cfile->vsize)) bad_header = TRUE;
252 if (bad_header) do_header_write_error(mainw->current_file);
253
254 if (audio_resampled) cfile->undo_action = UNDO_ATOMIC_RESAMPLE_RESIZE;
255 else {
256 cfile->undo_action = UNDO_RESIZABLE;
257 set_undoable(_("Resize"), TRUE);
258 }
259 video_resized = TRUE;
260 if (!mainw->multitrack) {
261 switch_to_file((mainw->current_file = 0), current_file);
262 }
263 }
264 }
265
266 if (cfile->undo_action == UNDO_ATOMIC_RESAMPLE_RESIZE) {
267 // just in case we missed anything...
268
269 set_undoable(_("Resample/Resize"), TRUE);
270 if (!video_resized) {
271 cfile->ohsize = cfile->hsize;
272 cfile->ovsize = cfile->vsize;
273 }
274 if (!video_resampled) {
275 cfile->undo1_dbl = cfile->fps;
276 }
277 cfile->undo_start = 1;
278 cfile->undo_end = frames;
279 }
280 return TRUE;
281}
282
283
285
286static weed_plant_t *copy_with_check(weed_plant_t *event, weed_plant_t *out_list, weed_timecode_t tc, char *what, size_t bytes,
287 weed_plant_t **ret_event) {
288 LiVESResponseType response;
289 weed_plant_t *new_list;
290 do {
291 response = LIVES_RESPONSE_OK;
292 if (ret_event) *ret_event = NULL;
293 if ((new_list = event_copy_and_insert(event, tc, out_list, ret_event)) == NULL) {
294 response = do_memory_error_dialog(what, bytes);
295 }
296 } while (response == LIVES_RESPONSE_RETRY);
297 if (response == LIVES_RESPONSE_CANCEL) return NULL;
298 return new_list;
299}
300
301#define READJ_MAX 2.
302#define READJ_MIN 0.1
303
304#define SMTH_FRAME_LIM 8
305#define SMTH_TC_LIM (0.5 * TICKS_PER_SECOND_DBL)
306
307void pre_analyse(weed_plant_t *elist) {
308 // note, this only works when we have a single audio track
309 // if we have > 1 then we would need to do something extra, like averaging the deltas
310
311 // optionally we can also try to smooth the frames; if abs(nxt - prev) < lim, curr = av(prev, nxt)
312
313 weed_event_t *event = get_first_event(elist), *last = NULL, *xevent;
314 weed_event_t *pframev = NULL, *ppframev = NULL;
315 int pclip = 0, ppclip = 0;
316 int pframe = 0, ppframe = 0;
317 weed_timecode_t stc = 0, etc, tc, ptc = 0, pptc = 0;
318 lives_audio_track_state_t *ststate = NULL, *enstate;
319 ticks_t offs = 0;
320 int ev_api = 100;
321 int ntracks;
322
323 if (weed_plant_has_leaf(elist, WEED_LEAF_WEED_EVENT_API_VERSION))
324 ev_api = weed_get_int_value(elist, WEED_LEAF_WEED_EVENT_API_VERSION, NULL);
325
326 for (; event; event = get_next_event(event)) {
327 if (prefs->rr_pre_smooth) {
328 if (WEED_EVENT_IS_FRAME(event)) {
329 weed_timecode_t tc = weed_event_get_timecode(event);
330 int clip = get_frame_event_clip(event, 0);
331 frames_t frame = get_frame_event_frame(event, 0);
332 if (pframev && ppframev && pclip == clip && ppclip == clip) {
333 if (abs(frame - pframe) <= SMTH_FRAME_LIM && (tc - pptc) < SMTH_TC_LIM) {
334 double del1 = (double)(ptc - pptc);
335 double del2 = (double)(tc - ptc);
336 if (del1 * del2 >= 3.5) {
337 pframe = (frames_t)(((double)ppframe * del2 + (double)frame * del1) / (del1 + del2) + .5);
338 weed_set_int64_value(pframev, WEED_LEAF_FRAMES, pframe);
339 }
340 }
341 }
342 pptc = ptc; ptc = tc;
343 ppframe = pframe; pframe = frame;
344 ppclip = pclip; pclip = clip;
345 ppframev = pframev; pframev = event;
346 }
347 }
348
349 if (!WEED_EVENT_IS_AUDIO_FRAME(event)) continue;
350 if (!last) {
351 stc = weed_event_get_timecode(event);
352 ststate = audio_frame_to_atstate(event, &ntracks);
353 if (ntracks > 1) break;
354 last = event;
355 continue;
356 }
357
358 if (prefs->rr_qmode) continue;
359
360 // we know the velocity from last aud. event, and current seekpos
361 // thus we can easily calculate the theoretical time we should arrive at
362 // seekpoint, and scale all timecodes.accordingly
363
364 // after the final, we just add constat adj.
365
366 etc = weed_event_get_timecode(event);
367 enstate = audio_frame_to_atstate(event, &ntracks);
368 if (ntracks > 1) break;
369
370 if (ststate[0].vel != 0. && (enstate[0].vel != 0. || ev_api >= 122) && enstate[0].afile == ststate[0].afile) {
371 double dtime = (double)(etc - stc) / TICKS_PER_SECOND_DBL;
372
373 if (dtime <= READJ_MAX && dtime >= READJ_MIN) {
375 double tpos = ststate[0].seek + ststate[0].vel * dtime;
376 double ratio = fabs(enstate[0].seek - ststate[0].seek) / fabs(tpos - ststate[0].seek);
377 double dtime;
378 weed_timecode_t otc = 0, ntc = 0;
379 // now have calculated the ratio, we can backtrack to start audio event, and adjust tcs
380 // new_tc -> start_tc + diff * ratio
381 for (xevent = last; xevent != event; xevent = get_next_event(xevent)) {
382 otc = get_event_timecode(xevent);
383 dtime = (double)(otc - stc) / TICKS_PER_SECOND_DBL;
384 dtime *= ratio;
385 ntc = stc + offs + (ticks_t)(dtime * TICKS_PER_SECOND_DBL);
386 weed_event_set_timecode(xevent, ntc);
387 }
388 offs += ntc - otc;
389 }
390 }
392 lives_free(ststate);
393 ststate = enstate;
394 last = event;
395 stc = etc;
396 }
397
398 lives_freep((void **)&ststate);
399
400 // we hit the end, just add offs
401 for (xevent = last; xevent; xevent = get_next_event(xevent)) {
402 tc = get_event_timecode(xevent);
403 weed_event_set_timecode(xevent, tc + offs);
404 }
405}
406
407
408
453
455
456weed_plant_t *quantise_events(weed_plant_t *in_list, double qfps, boolean allow_gap) {
457 weed_timecode_t out_tc = 0, offset_tc = 0, in_tc, laud_tc = 0, nx_tc;
458 weed_timecode_t end_tc;
459
460 weed_plant_t *out_list, *xout_list;
461 weed_event_t *naudio_event = NULL;
462 weed_event_t *frame_event = NULL, *nframe_event = NULL;
463 weed_event_t *last_frame_event;
464 weed_event_t *event, *newframe = NULL;
465 weed_event_t *init_event, *filter_map = NULL, *deinit_event;
466 weed_event_t *prev_aframe, *xprev_aframe;
467 weed_timecode_t recst_tc = 0;
468
469 LiVESResponseType response;
470 LiVESList *init_events = NULL, *deinit_events = NULL, *list;
471
472 ticks_t tl;
473 double *xaseeks = NULL, *naseeks = NULL, *naccels = NULL;
474 double old_fps;
475 char *what;
476
477 boolean interpolate = TRUE;
478 int *clips = NULL, *naclips = NULL, *nclips = NULL;
479 int64_t *frames = NULL, *nframes = NULL;
480 int *xaclips = NULL;
481
482 int tracks, ntracks = 0, natracks = 0, xatracks = 0;
483 int etype;
484 int is_final = 0;
485 int ev_api = 100;
486
487 register int i, j, k;
488
489 if (!in_list) return NULL;
490 if (qfps < 1.) return NULL;
491
492 old_fps = weed_get_double_value(in_list, WEED_LEAF_FPS, NULL);
493 if (old_fps == qfps) return in_list;
494
495 tl = (TICKS_PER_SECOND_DBL / qfps + .499999);
496 what = (_("quantising the event list"));
497
498 do {
499 response = LIVES_RESPONSE_OK;
501 out_list = weed_plant_copy(in_list);
502 if (!out_list) {
503 response = do_memory_error_dialog(what, 0);
504 }
505 } while (response == LIVES_RESPONSE_RETRY);
506 if (response == LIVES_RESPONSE_CANCEL) {
507 event_list_free(out_list);
508 lives_free(what);
509 return NULL;
510 }
511
512 if (weed_plant_has_leaf(in_list, WEED_LEAF_WEED_EVENT_API_VERSION))
513 ev_api = weed_get_int_value(in_list, WEED_LEAF_WEED_EVENT_API_VERSION, NULL);
514
515 if (old_fps == 0. && prefs->rr_super && (!prefs->rr_qmode || prefs->rr_pre_smooth)) {
518 pre_analyse(in_list);
519 }
520
521 weed_set_voidptr_value(out_list, WEED_LEAF_FIRST, NULL);
522 weed_set_voidptr_value(out_list, WEED_LEAF_LAST, NULL);
523 weed_set_double_value(out_list, WEED_LEAF_FPS, qfps);
524
525 event = get_first_event(in_list);
526 if (!event) goto q_done;
527
528 last_frame_event = get_last_frame_event(in_list);
529 if (!last_frame_event) goto q_done;
530
531 if (!allow_gap) offset_tc = get_event_timecode(get_first_frame_event(in_list));
532 else out_tc = get_event_timecode(get_first_frame_event(in_list));
533 end_tc = get_event_timecode(last_frame_event) - offset_tc;
534 end_tc = q_gint64(end_tc + tl, qfps);
535
536 // tl >>2 - make sure we don't round down
537 for (; out_tc < end_tc || event; out_tc = q_gint64(out_tc + tl + (tl >> 2), qfps)) {
538 weed_timecode_t stop_tc = out_tc + offset_tc;
539 if (out_tc > end_tc) out_tc = end_tc;
540 while (1) {
547
553
555 if (event) in_tc = get_event_timecode(event);
556
557 if (event && (is_final == 2 || (in_tc <= stop_tc && is_final != 1))) {
559 etype = weed_event_get_type(event);
560 //g_print("got event type %d at tc %ld, out = %ld\n", etype, in_tc, out_tc);
561
562 switch (etype) {
563 case WEED_EVENT_TYPE_MARKER: {
564 int marker_type = weed_get_int_value(event, WEED_LEAF_LIVES_TYPE, NULL);
565 if (marker_type == EVENT_MARKER_BLOCK_START || marker_type == EVENT_MARKER_BLOCK_UNORDERED
566 || marker_type == EVENT_MARKER_RECORD_START) {
567 // if event_list started as a recording then this will have been set for previews, but we now need to discard it
568 interpolate = FALSE;
569 lives_freep((void **)&xaclips);
570 lives_freep((void **)&xaseeks);
571 lives_freep((void **)&naclips);
572 lives_freep((void **)&naseeks);
573 xatracks = natracks = 0;
574 lives_list_free(init_events);
575 lives_list_free(deinit_events);
576 init_events = deinit_events = NULL;
577 filter_map = NULL;
578 if (prefs->rr_super && prefs->rr_amicro)
579 recst_tc = get_event_timecode(event);
580 }
581 if ((allow_gap && marker_type == EVENT_MARKER_RECORD_START)
582 || marker_type == EVENT_MARKER_BLOCK_START || marker_type == EVENT_MARKER_BLOCK_UNORDERED) {
583 if (!(xout_list = copy_with_check(event, out_list, out_tc, what, 0, NULL))) {
584 event_list_free(out_list);
585 out_list = NULL;
586 goto q_done;
587 }
588 out_list = xout_list;
589 }
590 }
591 break;
592 case WEED_EVENT_TYPE_FRAME:
593 interpolate = TRUE;
594 nframe_event = get_next_frame_event(event);
595 if (!nframe_event) is_final = 1;
596
602 if (!prefs->rr_fstate) {
603 if (!is_final) {
605 if (weed_event_get_timecode(nframe_event) > stop_tc) stop_tc = -1; // force insertion now
606 }
607 }
608 /* // interpolate unadded audio */
609 if (natracks > 0) {
610 // advance the seek value, so when we do add the audio vals, the seek is to the right time
611 // we use const. accel calculated when picked up
612 double dt = (double)(in_tc - laud_tc) / TICKS_PER_SECOND_DBL;
613 for (i = 0; i < natracks; i += 2) {
614 double vel = naseeks[i + 1];
615 if (naseeks[i + 1] != 0.) {
616 naseeks[i] += vel * dt;
617 }
618 }
619 }
620
621 if (WEED_EVENT_IS_AUDIO_FRAME(event)) {
622 // update unadded audio state (natracks) from in_list
623 // TODO: make use of aframe_to_atstate();
624 int *aclips;
625 double *aseeks;
626 int atracks = weed_frame_event_get_audio_tracks(event, &aclips, &aseeks);
627 for (i = 0; i < atracks; i += 2) {
628 for (j = 0; j < natracks; j += 2) {
629 if (naclips[j] == aclips[i]) {
630 // replace (superceded)
631 naclips[j + 1] = aclips[i + 1];
632 naseeks[j] = aseeks[i];
633 naseeks[j + 1] = aseeks[i + 1];
634 break;
635 }
636 }
637
638 if (j == natracks) {
639 natracks += 2;
640 // append
641 naclips = (int *)lives_realloc(naclips, natracks * sizint);
642 naseeks = (double *)lives_realloc(naseeks, natracks * sizdbl);
643 naccels = (double *)lives_realloc(naccels, (natracks >> 1) * sizdbl);
644 naclips[natracks - 2] = aclips[j];
645 naclips[natracks - 1] = aclips[j + 1];
646 naseeks[natracks - 2] = aseeks[j];
647 naseeks[natracks - 1] = aseeks[j + 1];
648 naccels[(natracks >> 1) - 1] = 0.;
649 }
650 }
651 lives_free(aclips);
652 lives_free(aseeks);
653 if (naudio_event == event) naudio_event = NULL;
654 }
656 laud_tc = in_tc;
657 frame_event = event;
658 if (event == nframe_event) nframe_event = NULL;
659 break;
660 case WEED_EVENT_TYPE_FILTER_INIT:
661 // add to filter_inits list
662 weed_leaf_delete(event, WEED_LEAF_HOST_TAG);
663 init_events = lives_list_prepend(init_events, event);
664 break;
665 case WEED_EVENT_TYPE_FILTER_DEINIT:
667 init_event = weed_get_voidptr_value(event, WEED_LEAF_INIT_EVENT, NULL);
668 for (list = init_events; list; list = list->next) {
669 if (list->data == init_event) {
670 if (list->prev) list->prev->next = list->next;
671 else init_events = list->next;
672 if (list->next) list->next->prev = list->prev;
673 list->next = list->prev = NULL;
674 lives_list_free(list);
675 break;
676 }
677 }
678 if (!list) {
679 weed_event_t *out_event = get_last_event(out_list);
680 init_event = weed_get_voidptr_value(out_event, WEED_LEAF_INIT_EVENT, NULL);
681 weed_leaf_dup(out_event, init_event, WEED_LEAF_IN_PARAMETERS);
682 if (!is_final) deinit_events = lives_list_prepend(deinit_events, event);
683 else {
684 //g_print("adding deinit at %lld\n", out_tc);
685 if (!(xout_list = copy_with_check(event, out_list, out_tc, what, 0, NULL))) {
686 event_list_free(out_list);
687 out_list = NULL;
688 goto q_done;
689 }
690 out_list = xout_list;
691 }
692 }
693 break;
694 case WEED_EVENT_TYPE_PARAM_CHANGE:
695 if (is_final) break;
697 init_event = weed_get_voidptr_value(event, WEED_LEAF_INIT_EVENT, NULL);
698 for (list = init_events; list; list = list->next) {
699 if (list->data == init_event) break;
700 }
701 if (!list) {
702 void **pchanges;
703 weed_event_t *pch_event, *init_event, *pchange, *npchange;
704 int nchanges, pnum;
705 if (!(xout_list = copy_with_check(event, out_list, in_tc - offset_tc, what, 0, &pch_event))) {
706 event_list_free(out_list);
707 out_list = NULL;
708 goto q_done;
709 }
710 // now we need to set PREV_CHANGE and NEXT_CHANGE
711 // starting at init_event, we check all init pchanges until we fins the matching INDEX
712 // then follow the NEXT_CHANGE ptrs until we get to NULL
713 // then finally set NEXT_CHANGE to point to event, and PREV_CHANGE to point backwards
714
715 out_list = xout_list;
716
717 init_event = weed_get_voidptr_value(pch_event, WEED_LEAF_INIT_EVENT, NULL);
718 pchanges = weed_get_voidptr_array_counted(init_event, WEED_LEAF_IN_PARAMETERS, &nchanges);
719 pnum = weed_get_int_value(pch_event, WEED_LEAF_INDEX, NULL);
720 for (i = 0; i < nchanges; i++) {
721 pchange = (weed_event_t *)pchanges[i];
722 if (weed_get_int_value(pchange, WEED_LEAF_INDEX, NULL) == pnum) {
723 npchange = weed_get_voidptr_value((weed_plant_t *)pchange, WEED_LEAF_NEXT_CHANGE, NULL);
724 while (npchange) {
725 pchange = npchange;
726 npchange = weed_get_voidptr_value((weed_plant_t *)pchange, WEED_LEAF_NEXT_CHANGE, NULL);
727 }
728 weed_set_voidptr_value(pchange, WEED_LEAF_NEXT_CHANGE, pch_event);
729 weed_set_voidptr_value(pch_event, WEED_LEAF_PREV_CHANGE, pchange);
730 break;
731 }
732 }
733 lives_free(pchanges);
734 }
735 break;
736 case WEED_EVENT_TYPE_FILTER_MAP:
738 filter_map = event;
739 break;
740 default:
742 break;
743 }
744 if (event) event = get_next_event(event);
745 } else {
746 weed_timecode_t frame_tc;
748 if (init_events) {
749 void **pchanges;
750 weed_event_t *xinit_event;
751 int nchanges;
752 // insert filter_inits + init pchanges
753 for (list = init_events; list; list = list->next) {
754 init_event = (weed_event_t *)list->data;
755 //g_print("ins init %p\n", init_event);
756 if (!(xout_list = copy_with_check(init_event, out_list, out_tc, what, 0, &xinit_event))) {
757 event_list_free(out_list);
758 out_list = NULL;
759 lives_list_free(init_events);
760 goto q_done;
761 }
762 out_list = xout_list;
763 // insert init pchanges
764 pchanges = weed_get_voidptr_array_counted(init_event, WEED_LEAF_IN_PARAMETERS, &nchanges);
765 init_event = xinit_event;
766 for (i = 0; i < nchanges; i++) {
767 weed_event_t *pchange = (weed_event_t *)pchanges[i];
768 if (!(xout_list = copy_with_check(pchange, out_list, out_tc, what, 0, (weed_event_t **)&pchanges[i]))) {
769 event_list_free(out_list);
770 out_list = NULL;
771 lives_list_free(init_events);
772 lives_free(pchanges);
773 goto q_done;
774 }
775 out_list = xout_list;
776 }
777 weed_set_voidptr_array(init_event, WEED_LEAF_IN_PARAMETERS, nchanges, pchanges);
778 }
779 lives_list_free(init_events);
780 init_events = NULL;
781 lives_free(pchanges);
782 }
783
784 if (filter_map && !deinit_events) {
785 //g_print("ins filter map\n");
786 if (!(xout_list = copy_with_check(filter_map, out_list, out_tc, what, 0, NULL))) {
787 event_list_free(out_list);
788 out_list = NULL;
789 goto q_done;
790 }
791 out_list = xout_list;
792 filter_map = NULL;
793 }
795
796 tracks = weed_frame_event_get_tracks(frame_event, &clips, &frames);
797 frame_tc = get_event_timecode(frame_event);
798
799 // frame_event is always <= out_tc, nframe_event is always > out_tc
800 if (!nframe_event) nframe_event = get_next_frame_event(frame_event);
801 ntracks = weed_frame_event_get_tracks(nframe_event, &nclips, &nframes);
802 nx_tc = get_event_timecode(nframe_event);
803
804 if (nframe_event) {
805 if (mainw->scrap_file != -1 && (nclips[0] == mainw->scrap_file || clips[0] == mainw->scrap_file)) {
806 if (nx_tc - (out_tc + offset_tc) < out_tc + offset_tc - frame_tc) {
807 // scrap file
808 frame_event = nframe_event;
809 lives_free(clips);
810 lives_free(frames);
811 frames = nframes;
812 clips = nclips;
813 tracks = ntracks;
814 }
815 } else {
816 if (old_fps == 0. && prefs->rr_super && prefs->rr_qsmooth && interpolate) {
818 double ratio = (double)(out_tc - frame_tc) / (double)(nx_tc - frame_tc);
819 for (i = 0; i < tracks; i++) {
820 if (i >= ntracks) break;
821 if (clips[i] == nclips[i]) {
822 frames[i] = (int64_t)((double)frames[i] + (double)(nframes[i] - frames[i]) * ratio);
823 }
824 }
825 }
826 lives_free(nclips);
827 lives_free(nframes);
828 }
829 }
830
832 //g_print("frame with %d tracks %d %d going in at %ld\n", tracks, clips[0], frames[0], out_tc);
833 out_list = append_frame_event(out_list, out_tc, tracks, clips, frames);
834 /* if (!insert_frame_event_at(out_list, out_tc, tracks, clips, frames, &newframe)) { */
835 /* response = do_memory_error_dialog(what, 0); */
836 /* } */
837 newframe = get_last_event(out_list);
838 if (response == LIVES_RESPONSE_CANCEL) {
839 event_list_free(out_list);
840 lives_free(what);
841 return NULL;
842 }
843 if (weed_plant_has_leaf(frame_event, WEED_LEAF_HOST_SCRAP_FILE_OFFSET)) {
844 weed_leaf_dup(newframe, frame_event, WEED_LEAF_HOST_SCRAP_FILE_OFFSET);
845 }
846 weed_leaf_dup(newframe, frame_event, WEED_LEAF_OVERLAY_TEXT);
847
848 lives_freep((void **)&frames);
849 lives_freep((void **)&clips);
850
851 if (natracks > 0) {
853 // filter naclips, remove any zeros for avel when track is not in xaclips
854 for (i = 0; i < natracks; i += 2) {
855 if (naseeks[i + 1] == 0.) {
856 for (j = 0; j < xatracks; j += 2) {
857 if (xaclips[j] == naclips[i] && xaseeks[j + 1] != 0.) break;
858 }
859 if (j == xatracks) {
860 natracks -= 2;
861 if (natracks == 0) {
862 lives_freep((void **)&naclips);
863 lives_freep((void **)&naseeks);
864 lives_freep((void **)&naccels);
865 } else {
866 for (k = i; k < natracks; k += 2) {
867 naclips[k] = naclips[k + 2];
868 naclips[k + 1] = naclips[k + 3];
869 naseeks[k] = naseeks[k + 2];
870 naseeks[k + 1] = naseeks[k + 3];
871 naccels[k >> 1] = naccels[(k >> 1) + 1];
872 }
873 naclips = (int *)lives_realloc(naclips, natracks * sizint);
874 naseeks = (double *)lives_realloc(naseeks, natracks * sizdbl);
875 naccels = (double *)lives_realloc(naccels, (natracks >> 1) * sizdbl);
876 // *INDENT-OFF*
877 }}}}}
878 // *INDENT-ON*
879
880 if (natracks > 0) {
883 double dt = (double)(out_tc + offset_tc - laud_tc) / TICKS_PER_SECOND_DBL;
884 for (i = 0; i < natracks; i += 2) {
885 double vel = naseeks[i + 1];
886 if (naseeks[i + 1] != 0.) {
887 int in_arate = mainw->files[naclips[i + 1]]->arps;
888 naseeks[i] += vel * dt;
889 naseeks[i] = quant_aseek(naseeks[i], in_arate);
890 }
891 }
892
893 weed_set_int_array(newframe, WEED_LEAF_AUDIO_CLIPS, natracks, naclips);
894 weed_set_double_array(newframe, WEED_LEAF_AUDIO_SEEKS, natracks, naseeks);
895
896 if (prefs->rr_super && prefs->rr_amicro) {
902 double amicro_lim = 4. / qfps;
903 prev_aframe = get_prev_audio_frame_event(newframe);
904 if ((double)(out_tc - get_event_timecode(prev_aframe)) / TICKS_PER_SECOND_DBL <= amicro_lim) {
905 //while (prev_aframe && (double)(out_tc - get_event_timecode(prev_aframe)) / TICKS_PER_SECOND_DBL <= amicro_lim) {
906 for (i = 0; i < natracks; i += 2) {
907 // check each track in natracks (currently active) to see if it is also in xatracks (all active)
908 boolean gottrack = FALSE;
910 if (naseeks[i + 1] == 0. && ev_api < 122) continue;
911 for (k = 0; k < xatracks; k += 2) {
912 if (xaclips[k] == naclips[i]) {
913 //. track is in xatracks, so there must be a prev audio frame for the track;
914 // if the clips match then we will find
915 // the audio frame event and maybe adjust the velocity
916 if (xaclips[k + 1] == naclips[i + 1]) gottrack = TRUE;
917 break;
918 }
919 }
920 if (!gottrack) continue;
921
923 xprev_aframe = prev_aframe;
924 if (1) {
925 //while (gottrack && xprev_aframe) {
926 weed_timecode_t ptc = get_event_timecode(xprev_aframe);
927 int *paclips;
928 double *paseeks;
929 int patracks;
930 if (ptc < recst_tc) break;
931
932 patracks = weed_frame_event_get_audio_tracks(xprev_aframe, &paclips, &paseeks);
933
934 for (j = 0; j < patracks; j += 2) {
935 if (paclips[j] == naclips[i]) {
936 if (paclips[j + 1] == naclips[i + 1]) {
937 if (paseeks[j + 1] != 0.) {
938 double dt = (double)(out_tc - ptc) / TICKS_PER_SECOND_DBL;
939 //if (dt > amicro_lim) continue;
940 //else {
941 if (1) {
946 int in_arate = mainw->files[naclips[i + 1]]->arps;
947 double nvel = (naseeks[i] - paseeks[j]) / dt, seek;
948
949 if (nvel * paseeks[j + 1] < 0.) break;
950
951 if (nvel > paseeks[j + 1]) {
952 if (nvel / paseeks[j + 1] > SKJUMP_THRESH_RATIO) nvel = paseeks[j + 1] * SKJUMP_THRESH_RATIO;
953 } else {
954 if (paseeks[j + 1] / nvel > SKJUMP_THRESH_RATIO) nvel = paseeks[j + 1] / SKJUMP_THRESH_RATIO;
955 }
956
957 insert_audio_event_at(xprev_aframe, paclips[j], paclips[j + 1], paseeks[j], nvel);
958 //} else {
959 // if velocity change is too great then we may adjust the seek a little instead
960 seek = paseeks[j] + nvel * dt;
961
962 if (naseeks[i] > seek) {
963 if (naseeks[i] > seek + SKJUMP_THRESH_SECS) seek = naseeks[i] + SKJUMP_THRESH_SECS;
964 } else {
965 if (naseeks[i] < seek - SKJUMP_THRESH_SECS) seek = naseeks[i] - SKJUMP_THRESH_SECS;
966 }
967 naseeks[i] = quant_aseek(seek, in_arate);
968 weed_set_double_array(newframe, WEED_LEAF_AUDIO_SEEKS, natracks, naseeks);
969 }
970 break;
971 // *INDENT-OFF*
972 }}}}
973 // *INDENT-ON*
974 lives_freep((void **)&paclips);
975 lives_freep((void **)&paseeks);
976 // *INDENT-OFF*
977 }}}}
978 // *INDENT-ON*
979
981 for (i = 0; i < natracks; i += 2) {
982 for (j = 0; j < xatracks; j += 2) {
983 if (naclips[i] == xaclips[j]) {
984 xaclips[j + 1] = naclips[i + 1];
985 xaseeks[j] = naseeks[i];
986 xaseeks[j + 1] = naseeks[i + 1];
987 break;
988 }
989 }
990 if (j == xatracks) {
991 xatracks += 2;
992 xaclips = lives_realloc(xaclips, xatracks * sizint);
993 xaseeks = lives_realloc(xaseeks, xatracks * sizdbl);
994 xaclips[xatracks - 2] = naclips[i];
995 xaclips[xatracks - 1] = naclips[i + 1];
996 xaseeks[xatracks - 2] = naseeks[i];
997 xaseeks[xatracks - 1] = naseeks[i + 1];
998 }
999 }
1000 natracks = 0;
1001 lives_freep((void **)&naclips);
1002 lives_freep((void **)&naseeks);
1003 lives_freep((void **)&naccels);
1004 }
1005
1006 lives_freep((void **)&frames);
1007 lives_freep((void **)&clips);
1008
1010
1011 if (deinit_events) {
1012 // insert filter_deinits
1013 for (list = deinit_events; list; list = list->next) {
1014 deinit_event = (weed_event_t *)list->data;
1015 //g_print("ins deinit %p\n", deinit_event);
1016 if (!(xout_list = copy_with_check(deinit_event, out_list, out_tc, what, 0, NULL))) {
1017 event_list_free(out_list);
1018 out_list = NULL;
1019 goto q_done;
1020 }
1021 out_list = xout_list;
1022 }
1023 lives_list_free(deinit_events);
1024 deinit_events = NULL;
1025 }
1026
1027 if (filter_map) {
1028 //g_print("ins filter map\n");
1029 if (!(xout_list = copy_with_check(filter_map, out_list, out_tc, what, 0, NULL))) {
1030 event_list_free(out_list);
1031 out_list = NULL;
1032 goto q_done;
1033 }
1034 out_list = xout_list;
1035 filter_map = NULL;
1036 }
1037 if (is_final == 1) {
1038 is_final = 2;
1039 } else break;
1040 }
1041 }
1042 }
1043
1044 //g_print("RES: %p and %ld, %ld\n", event, out_tc + tl, end_tc);
1045 if (filter_map) {
1046 // insert final filter_map
1047 if (!(xout_list = copy_with_check(filter_map, out_list, end_tc, what, 0, NULL))) {
1048 event_list_free(out_list);
1049 out_list = NULL;
1050 goto q_done;
1051 }
1052 out_list = xout_list;
1053 }
1054
1055 if (!get_first_frame_event(out_list)) {
1056 // make sure we have at least one frame
1057 if ((event = get_last_frame_event(in_list))) {
1058 do {
1059 response = LIVES_RESPONSE_OK;
1060 lives_freep((void **)&clips);
1061 lives_freep((void **)&frames);
1062 tracks = weed_frame_event_get_tracks(event, &clips, &frames);
1063 if (insert_frame_event_at(out_list, 0., tracks, clips, frames, NULL) == NULL) {
1064 response = do_memory_error_dialog(what, 0);
1065 }
1066 } while (response == LIVES_RESPONSE_RETRY);
1067 if (response == LIVES_RESPONSE_CANCEL) {
1068 event_list_free(out_list);
1069 out_list = NULL;
1070 goto q_done;
1071 }
1072 }
1073 }
1074
1078
1079q_done:
1080 lives_list_free(init_events);
1081 lives_list_free(deinit_events);
1082 lives_free(what);
1083 reset_ttable();
1084 return out_list;
1085}
1086
1087
1089
1090static void on_reorder_activate(int rwidth, int rheight) {
1091 char *msg;
1092
1094 if (!check_for_layout_errors(NULL, mainw->current_file, 1, 0, &chk_mask)) {
1095 return;
1096 }
1097
1098 cfile->old_frames = cfile->frames;
1099
1100 // we do the reorder in reorder_frames()
1101 // this will clear event_list and set it in event_list_back
1102 if ((cfile->frames = reorder_frames(rwidth, rheight)) < 0) {
1103 // reordering error
1104 if (!(cfile->undo_action == UNDO_RESAMPLE)) {
1105 cfile->frames = -cfile->frames;
1106 }
1108 return;
1109 }
1110
1111 if (mainw->cancelled != CANCEL_NONE) {
1112 return;
1113 }
1114
1115 if (cfile->start > cfile->frames) {
1116 cfile->start = cfile->frames;
1117 }
1118
1119 if (cfile->end > cfile->frames) {
1120 cfile->end = cfile->frames;
1121 }
1122
1123 cfile->event_list = NULL;
1124 cfile->next_event = NULL;
1125
1127
1129 if (mainw->current_file > 0) {
1130 d_print_done();
1131 msg = lives_strdup_printf(_("Length of video is now %d frames.\n"), cfile->frames);
1132 } else {
1133 msg = lives_strdup_printf(_("Clipboard was resampled to %d frames.\n"), cfile->frames);
1134 }
1135
1136 d_print(msg);
1137 lives_free(msg);
1138
1139 if (chk_mask != 0) popup_lmap_errors(NULL, LIVES_INT_TO_POINTER(chk_mask));
1140
1141 if (mainw->sl_undo_mem && cfile->stored_layout_frame != 0) {
1142 // need to invalidate undo/redo stack, in case file was used in some layout undo
1144 }
1145}
1146
1147
1148void on_resample_audio_activate(LiVESMenuItem * menuitem, livespointer user_data) {
1149 // show the playback rate - real audio rate is cfile->arps
1150 mainw->fx1_val = cfile->arate;
1151 mainw->fx2_val = cfile->achans;
1152 mainw->fx3_val = cfile->asampsize;
1153 mainw->fx4_val = cfile->signed_endian;
1154 resaudw = create_resaudw(1, NULL, NULL);
1156}
1157
1158
1159void on_resaudio_ok_clicked(LiVESButton * button, LiVESEntry * entry) {
1160 char *com;
1161
1162 int arate, achans, asampsize, arps;
1163 int asigned = 1, aendian = 1;
1164 int cur_signed, cur_endian;
1165 int i;
1166
1167 if (button) {
1168 arps = arate = (int)atoi(lives_entry_get_text(LIVES_ENTRY(resaudw->entry_arate)));
1169 achans = (int)atoi(lives_entry_get_text(LIVES_ENTRY(resaudw->entry_achans)));
1170 asampsize = (int)atoi(lives_entry_get_text(LIVES_ENTRY(resaudw->entry_asamps)));
1171 if (lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(resaudw->rb_unsigned))) {
1172 asigned = 0;
1173 }
1174 if (lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(resaudw->rb_bigend))) {
1175 aendian = 0;
1176 }
1177
1181
1182 if (arate <= 0) {
1183 // TODO - show error icon1280
1185 do_error_dialog(_("\n\nNew rate must be greater than 0\n"));
1187 return;
1188 }
1189 } else {
1190 // called from on_redo or other places
1191 arate = arps = cfile->undo1_int;
1192 achans = cfile->undo2_int;
1193 asampsize = cfile->undo3_int;
1194 asigned = !(cfile->undo1_uint & AFORM_UNSIGNED);
1195 aendian = !(cfile->undo1_uint & AFORM_BIG_ENDIAN);
1196 }
1197
1199 if (!check_for_layout_errors(NULL, mainw->current_file, 1, 0, &chk_mask)) {
1200 return;
1201 }
1202
1203 // store old values for undo/redo
1204 cfile->undo1_int = cfile->arate;
1205 cfile->undo2_int = cfile->achans;
1206 cfile->undo3_int = cfile->asampsize;
1207 cfile->undo4_int = cfile->arps;
1208 cfile->undo1_uint = cfile->signed_endian;
1209
1210 cur_signed = !(cfile->signed_endian & AFORM_UNSIGNED);
1211 cur_endian = !(cfile->signed_endian & AFORM_BIG_ENDIAN);
1212
1213 if (!(arate == cfile->arate && arps == cfile->arps && achans == cfile->achans && asampsize == cfile->asampsize &&
1214 asigned == cur_signed && aendian == cur_endian)) {
1215 if (cfile->arps != cfile->arate) {
1216 double audio_stretch = (double)cfile->arps / (double)cfile->arate;
1217 // pb rate != real rate - stretch to pb rate and resample
1218 lives_rm(cfile->info_file);
1219 com = lives_strdup_printf("%s resample_audio \"%s\" %d %d %d %d %d %d %d %d %d %d %.4f", prefs->backend,
1220 cfile->handle, cfile->arps,
1221 cfile->achans, cfile->asampsize, cur_signed, cur_endian, arps, cfile->achans, cfile->asampsize,
1222 cur_signed, cur_endian, audio_stretch);
1223 lives_system(com, FALSE);
1224 if (THREADVAR(com_failed)) {
1226 return;
1227 }
1228 do_progress_dialog(TRUE, FALSE, _("Resampling audio")); // TODO - allow cancel ??
1229 lives_free(com);
1230 cfile->arate = cfile->arps = arps;
1231 } else {
1232 lives_rm(cfile->info_file);
1233 com = lives_strdup_printf("%s resample_audio \"%s\" %d %d %d %d %d %d %d %d %d %d", prefs->backend,
1234 cfile->handle, cfile->arps,
1235 cfile->achans, cfile->asampsize, cur_signed, cur_endian, arps, achans, asampsize,
1236 asigned, aendian);
1238 mainw->error = FALSE;
1239 lives_rm(cfile->info_file);
1240 THREADVAR(com_failed) = FALSE;
1241 lives_system(com, FALSE);
1243 if (THREADVAR(com_failed)) {
1245 return;
1246 }
1247 do_progress_dialog(TRUE, FALSE, _("Resampling audio"));
1248 lives_free(com);
1249 }
1250 }
1251
1252 if (cfile->audio_waveform) {
1253 for (i = 0; i < cfile->achans; lives_freep((void **)&cfile->audio_waveform[i++]));
1254 lives_freep((void **)&cfile->audio_waveform);
1255 lives_freep((void **)&cfile->aw_sizes);
1256 }
1257
1258 cfile->arate = arate;
1259 cfile->achans = achans;
1260 cfile->asampsize = asampsize;
1261 cfile->arps = arps;
1262 cfile->signed_endian = get_signed_endian(asigned, aendian);
1263 cfile->changed = TRUE;
1264
1265 cfile->undo_action = UNDO_AUDIO_RESAMPLE;
1266 mainw->error = FALSE;
1268
1269 if (cfile->afilesize == 0l) {
1271 do_error_dialog(_("LiVES was unable to resample the audio as requested.\n"));
1273 on_undo_activate(NULL, NULL);
1274 set_undoable(_("Resample Audio"), FALSE);
1275 mainw->error = TRUE;
1277 return;
1278 }
1279 set_undoable(_("Resample Audio"), !prefs->conserve_space);
1280
1282
1284
1285 d_print(""); // force printing of switch message
1286
1287 d_print(_("Audio was resampled to %d Hz, %d channels, %d bit"), arate, achans, asampsize);
1288
1289 if (cur_signed != asigned) {
1290 if (asigned == 1) {
1291 d_print(_(", signed"));
1292 } else {
1293 d_print(_(", unsigned"));
1294 }
1295 }
1296 if (cur_endian != aendian) {
1297 if (aendian == 1) {
1298 d_print(_(", little-endian"));
1299 } else {
1300 d_print(_(", big-endian"));
1301 }
1302 }
1303 d_print("\n");
1304
1305 if (chk_mask != 0) popup_lmap_errors(NULL, LIVES_INT_TO_POINTER(chk_mask));
1306
1307 if (mainw->sl_undo_mem && cfile->stored_layout_audio > 0.) {
1308 // need to invalidate undo/redo stack, in case file was used in some layout undo
1310 }
1311}
1312
1313
1314static void on_resaudw_achans_changed(LiVESWidget * widg, livespointer user_data) {
1315 _resaudw *resaudw = (_resaudw *)user_data;
1316 //char *tmp;
1317
1318 if (!lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(widg))) {
1326 if (prefsw) {
1329 } else if (rdet) {
1332 }
1333 } else {
1334 if (atoi(lives_entry_get_text(LIVES_ENTRY(resaudw->entry_asamps))) != 8) {
1337 }
1341 if (prefsw) {
1344 }
1345 if (rdet) {
1348 }
1349 }
1350}
1351
1352
1353void on_resaudw_asamps_changed(LiVESWidget * irrelevant, livespointer rubbish) {
1354 if (atoi(lives_entry_get_text(LIVES_ENTRY(resaudw->entry_asamps))) == 8) {
1360 } else {
1363 if (atoi(lives_entry_get_text(LIVES_ENTRY(resaudw->entry_asamps))) == 16) {
1366 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(resaudw->rb_signed), TRUE);
1367 }
1368 }
1369}
1370
1371
1372void on_resample_video_activate(LiVESMenuItem * menuitem, livespointer user_data) {
1373 // change speed from the menu
1375 mainw->fx1_val = cfile->fps;
1376}
1377
1378
1379void on_resample_vid_ok(LiVESButton * button, LiVESEntry * entry) {
1380 weed_plant_t *real_back_list = NULL;
1381 weed_plant_t *new_event_list = NULL;
1382 double oundo1_dbl = cfile->undo1_dbl;
1383 LiVESResponseType response;
1384 ticks_t in_time = 0;
1385 double old_fps = cfile->fps;
1386 char *msg;
1387 char *what;
1388 boolean ratio_fps;
1389 boolean bad_header = FALSE;
1390 int old_frames;
1391 int ostart = cfile->start;
1392 int oend = cfile->end;
1393
1394 mainw->error = FALSE;
1395
1396 if (button) {
1397 lives_general_button_clicked(button, NULL);
1398 if (mainw->fx1_val == 0.) mainw->fx1_val = 1.;
1399 } else {
1400 mainw->fx1_val = cfile->undo1_dbl;
1401 }
1402
1403 if (mainw->current_file < 0 || cfile->frames == 0) return;
1404
1405 if (mainw->fx1_val == cfile->fps && !cfile->event_list) return;
1406
1407 real_back_list = cfile->event_list;
1408 what = (_("creating the event list for resampling"));
1409
1410 if (!cfile->event_list) {
1411 /* new_event_list = lives_event_list_new(NULL, 0); */
1412 /* weed_set_double_value(new_event_list, WEED_LEAF_FPS, cfile->fps); */
1413 for (int64_t i64 = 1; i64 <= (int64_t)cfile->frames; i64++) {
1414 do {
1415 response = LIVES_RESPONSE_OK;
1416 new_event_list = append_frame_event(new_event_list, in_time, 1, &(mainw->current_file), &i64);
1417 if (!new_event_list) {
1418 response = do_memory_error_dialog(what, 0);
1419 }
1420 } while (response == LIVES_RESPONSE_RETRY);
1421 if (response == LIVES_RESPONSE_CANCEL) {
1422 lives_free(what);
1423 return;
1424 }
1425 in_time += (ticks_t)(1. / cfile->fps * TICKS_PER_SECOND_DBL + .5);
1426 }
1427 cfile->event_list = new_event_list;
1428 }
1429 cfile->undo1_dbl = cfile->fps;
1430
1431 if (cfile->event_list_back) event_list_free(cfile->event_list_back);
1432 cfile->event_list_back = cfile->event_list;
1433
1434 //QUANTISE
1435 new_event_list = quantise_events(cfile->event_list_back, mainw->fx1_val, real_back_list != NULL);
1436 cfile->event_list = new_event_list;
1437
1438 if (!real_back_list) event_list_free(cfile->event_list_back);
1439 cfile->event_list_back = NULL;
1440
1441 if (!cfile->event_list) {
1442 cfile->event_list = real_back_list;
1443 cfile->undo1_dbl = oundo1_dbl;
1444 mainw->error = TRUE;
1445 return;
1446 }
1447
1448 if (mainw->multitrack) return;
1449
1450 ratio_fps = check_for_ratio_fps(mainw->fx1_val);
1451
1452 // we have now quantised to fixed fps; we have come here from reorder
1453
1454 if (ratio_fps) {
1455 // got a ratio
1456 msg = lives_strdup_printf(_("Resampling video at %.8f frames per second..."), mainw->fx1_val);
1457 } else {
1458 msg = lives_strdup_printf(_("Resampling video at %.3f frames per second..."), mainw->fx1_val);
1459 }
1460 if (mainw->current_file > 0) {
1461 d_print(msg);
1462 }
1463 lives_free(msg);
1464
1465 old_frames = cfile->frames;
1466
1467 // must set these before calling reorder
1468 cfile->start = (int)((cfile->start - 1.) / old_fps * mainw->fx1_val + 1.);
1469 if ((cfile->end = (int)((cfile->end * mainw->fx1_val) / old_fps + .49999)) < cfile->start) cfile->end = cfile->start;
1470
1471 cfile->undo_action = UNDO_RESAMPLE;
1472 // REORDER
1473 // this calls reorder_frames, which sets event_list_back==event_list, and clears event_list
1474 on_reorder_activate(reorder_width, reorder_height);
1475
1476 if (cfile->frames <= 0 || mainw->cancelled != CANCEL_NONE) {
1477 // reordering error...
1478 cfile->event_list = real_back_list;
1479 if (cfile->event_list_back) event_list_free(cfile->event_list_back);
1480 cfile->event_list_back = NULL;
1481 cfile->frames = old_frames;
1482 cfile->start = ostart;
1483 cfile->end = oend;
1484 load_end_image(cfile->end);
1485 load_start_image(cfile->start);
1486 cfile->undo1_dbl = oundo1_dbl;
1487 sensitize();
1488 mainw->error = TRUE;
1490 if (cfile->frames < 0) do_error_dialog(_("Reordering error !\n"));
1492 return;
1493 }
1494
1495 if (cfile->event_list_back) event_list_free(cfile->event_list_back);
1496 cfile->event_list_back = real_back_list;
1497
1498 cfile->ratio_fps = ratio_fps;
1499 cfile->pb_fps = cfile->fps = mainw->fx1_val;
1500 cfile->old_frames = old_frames;
1501
1502 set_undoable(_("Resample"), TRUE);
1503 if (cfile->clip_type == CLIP_TYPE_FILE && cfile->ext_src) {
1504 lives_clip_data_t *cdata = ((lives_decoder_t *)cfile->ext_src)->cdata;
1505 double dfps = (double)cdata->fps;
1506 if (!save_clip_value(mainw->current_file, CLIP_DETAILS_FPS, &dfps)) bad_header = TRUE;
1507 if (!save_clip_value(mainw->current_file, CLIP_DETAILS_PB_FPS, &cfile->fps)) bad_header = TRUE;
1508 } else {
1509 if (!save_clip_value(mainw->current_file, CLIP_DETAILS_FPS, &cfile->fps)) bad_header = TRUE;
1510 if (!save_clip_value(mainw->current_file, CLIP_DETAILS_PB_FPS, &cfile->pb_fps)) bad_header = TRUE;
1511 }
1512
1513 if (bad_header) do_header_write_error(mainw->current_file);
1514
1516}
1517
1518
1520
1521_resaudw *create_resaudw(short type, render_details * rdet, LiVESWidget * top_vbox) {
1522 // type 1 == resample
1523 // type 2 == insert silence
1524 // type 3 == enter multitrack
1525 // type 4 == prefs/multitrack
1526 // type 5 == new clip record/record to selection with no existing audio
1527 // type 6 == record to clip with no existing audio
1528 // type 7 == record to clip with existing audio (show time only)
1529 // type 8 == grab external window, with audio
1530 // type 9 == grab external, no audio
1531 // type 10 == change inside multitrack / render to clip (embedded) [resets to 3]
1532 // type 11 == rte audio gen as rfx
1533
1534 LiVESWidget *dialog_vbox = NULL;
1535 LiVESWidget *vboxx;
1536 LiVESWidget *frame;
1537 LiVESWidget *combo_entry2;
1538 LiVESWidget *combo_entry3;
1539 LiVESWidget *combo_entry1;
1540 LiVESWidget *vseparator;
1541 LiVESWidget *radiobutton_u1;
1542 LiVESWidget *radiobutton_s1;
1543 LiVESWidget *vbox;
1544 LiVESWidget *radiobutton_b1;
1545 LiVESWidget *radiobutton_l1;
1546 LiVESWidget *combo4;
1547 LiVESWidget *combo5;
1548 LiVESWidget *combo6;
1549 LiVESWidget *cancelbutton;
1550 LiVESWidget *okbutton;
1551 LiVESWidget *label;
1552 LiVESWidget *hseparator;
1553 LiVESWidget *radiobutton;
1554 LiVESWidget *hbox;
1555 LiVESWidget *hbox2;
1556
1557 LiVESAccelGroup *accel_group = NULL;
1558
1559 LiVESSList *s1_group = NULL;
1560 LiVESSList *e1_group = NULL;
1561 LiVESSList *s2_group = NULL;
1562 LiVESSList *e2_group = NULL;
1563 LiVESSList *rbgroup = NULL;
1564
1565 LiVESList *channels = NULL;
1566 LiVESList *sampsize = NULL;
1567 LiVESList *rate = NULL;
1568
1569 double secs = 0.;
1570
1571 char *tmp;
1572
1573 int hours = 0, mins = 0;
1574 int aendian;
1575
1576 boolean chans_fixed = FALSE;
1577 boolean is_8bit;
1578
1580
1581 if (type == 10) {
1582 chans_fixed = TRUE;
1583 type = 3;
1584 }
1585
1586 if (type > 5 && type != 11 && mainw->rec_end_time != -1.) {
1587 hours = (int)(mainw->rec_end_time / 3600.);
1588 mins = (int)((mainw->rec_end_time - (hours * 3600.)) / 60.);
1589 secs = mainw->rec_end_time - hours * 3600. - mins * 60.;
1590 }
1591
1592 channels = lives_list_append(channels, (livespointer)"1");
1593 channels = lives_list_append(channels, (livespointer)"2");
1594
1595 sampsize = lives_list_append(sampsize, (livespointer)"8");
1596 sampsize = lives_list_append(sampsize, (livespointer)"16");
1597
1598 rate = lives_list_append(rate, (livespointer)"5512");
1599 rate = lives_list_append(rate, (livespointer)"8000");
1600 rate = lives_list_append(rate, (livespointer)"11025");
1601 rate = lives_list_append(rate, (livespointer)"22050");
1602 rate = lives_list_append(rate, (livespointer)"32000");
1603 rate = lives_list_append(rate, (livespointer)"44100");
1604 rate = lives_list_append(rate, (livespointer)"48000");
1605 rate = lives_list_append(rate, (livespointer)"88200");
1606 rate = lives_list_append(rate, (livespointer)"96000");
1607 rate = lives_list_append(rate, (livespointer)"128000");
1608
1609 if (type < 3 || type > 4) {
1610 char *title = NULL;
1611
1612 if (type == 1) {
1613 title = (_("Resample Audio"));
1614 } else if (type == 2) {
1615 title = (_("Insert Silence"));
1616 } else if (type == 5 || type == 11 || type == 6 || type == 7) {
1617 title = (_("New Clip Audio"));
1618 } else if (type == 9 || type == 8) {
1619 title = (_("External Clip Settings"));
1620 }
1621
1623 lives_signal_handlers_disconnect_by_func(resaudw->dialog, LIVES_GUI_CALLBACK(return_true), NULL);
1624 lives_free(title);
1625
1626 accel_group = LIVES_ACCEL_GROUP(lives_accel_group_new());
1627 lives_window_add_accel_group(LIVES_WINDOW(resaudw->dialog), accel_group);
1628
1629 dialog_vbox = lives_dialog_get_content_area(LIVES_DIALOG(resaudw->dialog));
1630
1631 vboxx = lives_vbox_new(FALSE, 0);
1632
1633 lives_box_pack_start(LIVES_BOX(dialog_vbox), vboxx, TRUE, TRUE, 0);
1634 } else vboxx = top_vbox;
1635
1636 if (type == 1) {
1637 frame = lives_standard_frame_new(_("Current"), 0., FALSE);
1638
1639 lives_box_pack_start(LIVES_BOX(vboxx), frame, FALSE, TRUE, 0);
1640
1641 hbox2 = lives_hbox_new(FALSE, 0);
1642 lives_container_add(LIVES_CONTAINER(frame), hbox2);
1643 //lives_container_set_border_width(LIVES_CONTAINER(hbox2), widget_opts.packing_width);
1644
1645 tmp = lives_strdup_printf("%d", (int)mainw->fx1_val);
1646
1647 combo_entry2 = lives_standard_entry_new(_("Rate (Hz) "), tmp, 10, 6, LIVES_BOX(hbox2), NULL);
1648 lives_free(tmp);
1649
1650 lives_editable_set_editable(LIVES_EDITABLE(combo_entry2), FALSE);
1651 lives_widget_set_can_focus(combo_entry2, FALSE);
1652
1653 tmp = lives_strdup_printf("%d", (int)mainw->fx2_val);
1654 combo_entry3 = lives_standard_entry_new(_("Channels"), tmp, 6, 2, LIVES_BOX(hbox2), NULL);
1655 lives_free(tmp);
1656
1657 lives_editable_set_editable(LIVES_EDITABLE(combo_entry3), FALSE);
1658 lives_widget_set_can_focus(combo_entry3, FALSE);
1659
1660 tmp = lives_strdup_printf("%d", (int)mainw->fx3_val);
1661 combo_entry1 = lives_standard_entry_new(_("Sample Size "), tmp, 6, 2, LIVES_BOX(hbox2), NULL);
1662 lives_free(tmp);
1663
1664 lives_editable_set_editable(LIVES_EDITABLE(combo_entry1), FALSE);
1665 lives_widget_set_can_focus(combo_entry1, FALSE);
1666
1667 vseparator = lives_vseparator_new();
1668 lives_box_pack_start(LIVES_BOX(hbox2), vseparator, FALSE, FALSE, 0);
1669
1670 vbox = lives_vbox_new(FALSE, 0);
1671 lives_box_pack_start(LIVES_BOX(hbox2), vbox, FALSE, FALSE, 0);
1672
1673 hbox = lives_hbox_new(FALSE, 0);
1674 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
1675
1676 radiobutton_s1 = lives_standard_radio_button_new(_("Signed"), &s1_group, LIVES_BOX(hbox), NULL);
1677
1678 hbox = lives_hbox_new(FALSE, 0);
1679 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
1680
1681 radiobutton_u1 = lives_standard_radio_button_new(_("Unsigned"), &s1_group, LIVES_BOX(hbox), NULL);
1682
1683 aendian = mainw->fx4_val;
1684
1685 if (aendian & AFORM_UNSIGNED) {
1686 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(radiobutton_u1), TRUE);
1687 } else {
1688 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(radiobutton_s1), TRUE);
1689 }
1690
1691 lives_widget_set_sensitive(radiobutton_u1, FALSE);
1692 lives_widget_set_sensitive(radiobutton_s1, FALSE);
1693
1694 vseparator = lives_vseparator_new();
1695 lives_box_pack_start(LIVES_BOX(hbox2), vseparator, FALSE, FALSE, 0);
1696
1697 vbox = lives_vbox_new(FALSE, 0);
1698 lives_box_pack_start(LIVES_BOX(hbox2), vbox, FALSE, FALSE, 0);
1699
1700 hbox = lives_hbox_new(FALSE, 0);
1701 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
1702
1703 radiobutton_l1 = lives_standard_radio_button_new(_("Little Endian"), &e1_group, LIVES_BOX(hbox), NULL);
1704
1705 hbox = lives_hbox_new(FALSE, 0);
1706 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
1707
1708 radiobutton_b1 = lives_standard_radio_button_new(_("Big Endian"), &e1_group, LIVES_BOX(hbox), NULL);
1709
1710 if (aendian & AFORM_BIG_ENDIAN) {
1711 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(radiobutton_b1), TRUE);
1712 } else {
1713 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(radiobutton_l1), TRUE);
1714 }
1715
1716 lives_widget_set_sensitive(radiobutton_b1, FALSE);
1717 lives_widget_set_sensitive(radiobutton_l1, FALSE);
1718 }
1719
1720 resaudw->aud_checkbutton = NULL;
1721
1722 if (type < 9 || type == 11) {
1723 if (type >= 3 && type != 11) tmp = (_("Audio"));
1724 else if (type == 2) tmp = (_("New Audio Details"));
1725 else tmp = (_("New"));
1726
1727 frame = lives_standard_frame_new(tmp, 0., FALSE);
1728 lives_free(tmp);
1729
1730 if (type == 4) lives_box_pack_start(LIVES_BOX(vboxx), frame, FALSE, FALSE, widget_opts.packing_height);
1731 else lives_box_pack_start(LIVES_BOX(vboxx), frame, FALSE, TRUE, 0);
1732
1734 lives_container_add(LIVES_CONTAINER(frame), resaudw->vbox);
1735
1736 if (type > 2 && type < 5 && !chans_fixed) {
1739
1740 resaudw->aud_checkbutton = lives_standard_check_button_new(_("_Enable audio"), FALSE, LIVES_BOX(resaudw->aud_hbox), NULL);
1741
1742 if (rdet) lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(resaudw->aud_checkbutton), rdet->achans > 0);
1743 else lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(resaudw->aud_checkbutton),
1744 !mainw->multitrack ? prefs->mt_def_achans > 0 : cfile->achans > 0);
1745 if (type == 4) {
1746 lives_signal_sync_connect(LIVES_GUI_OBJECT(resaudw->aud_checkbutton), LIVES_WIDGET_TOGGLED_SIGNAL,
1747 LIVES_GUI_CALLBACK(apply_button_set_enabled), NULL);
1748 }
1749 }
1750
1751 hbox2 = lives_hbox_new(FALSE, 0);
1754
1755 vbox = lives_vbox_new(FALSE, 0);
1756 lives_box_pack_start(LIVES_BOX(hbox2), vbox, FALSE, FALSE, widget_opts.packing_width);
1757
1758 hbox = lives_hbox_new(FALSE, 0);
1759 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
1761
1762 combo4 = lives_standard_combo_new(_("Rate (Hz) "), rate, LIVES_BOX(hbox), NULL);
1763
1764 resaudw->entry_arate = lives_combo_get_entry(LIVES_COMBO(combo4));
1765
1767 if (type == 7) lives_widget_set_sensitive(combo4, FALSE);
1768
1769 if (type < 3 || (type > 4 && type < 8) || type == 11) tmp = lives_strdup_printf("%d", (int)mainw->fx1_val);
1770 else if (type == 8) tmp = lives_strdup_printf("%d", DEFAULT_AUDIO_RATE);
1771 else if (type == 3) tmp = lives_strdup_printf("%d", rdet->arate);
1772 else tmp = (!mainw->multitrack || cfile->achans == 0)
1774 lives_entry_set_text(LIVES_ENTRY(resaudw->entry_arate), tmp);
1775 lives_free(tmp);
1776
1777 if (type == 4) {
1778 lives_signal_sync_connect(LIVES_GUI_OBJECT(combo4), LIVES_WIDGET_CHANGED_SIGNAL,
1779 LIVES_GUI_CALLBACK(apply_button_set_enabled), NULL);
1780 }
1781
1782 combo5 = lives_standard_combo_new((type >= 3 && type != 11 ? (_("_Channels")) : (_("Channels"))),
1783 channels, LIVES_BOX(hbox), NULL);
1784
1785 if (type == 7) lives_widget_set_sensitive(combo5, FALSE);
1786
1787 resaudw->entry_achans = lives_combo_get_entry(LIVES_COMBO(combo5));
1789
1790 if (type < 3 || (type > 4 && type < 8) || type == 11) tmp = lives_strdup_printf("%d", (int)mainw->fx2_val);
1791 else if (type == 8) tmp = lives_strdup_printf("%d", DEFAULT_AUDIO_CHANS);
1792 else if (type == 3) tmp = lives_strdup_printf("%d", rdet->achans);
1793 else tmp = lives_strdup_printf("%d", (!mainw->multitrack || cfile->achans == 0)
1795 : prefs->mt_def_achans) : cfile->achans);
1796 lives_entry_set_text(LIVES_ENTRY(resaudw->entry_achans), tmp);
1797 lives_free(tmp);
1798
1799 if (chans_fixed) {
1802 }
1803
1804 if (type == 4) {
1805 lives_signal_sync_connect(LIVES_GUI_OBJECT(combo5), LIVES_WIDGET_CHANGED_SIGNAL,
1806 LIVES_GUI_CALLBACK(apply_button_set_enabled), NULL);
1807 }
1808
1809 combo6 = lives_standard_combo_new((type >= 3 && type != 11 ? (_("_Sample Size")) : (_("Sample Size"))),
1810 sampsize, LIVES_BOX(hbox), NULL);
1811
1812 if (type == 7) lives_widget_set_sensitive(combo6, FALSE);
1813
1814 resaudw->entry_asamps = lives_combo_get_entry(LIVES_COMBO(combo6));
1818
1819 if (type < 3 || (type > 4 && type < 8) || type == 11) tmp = lives_strdup_printf("%d", (int)mainw->fx3_val);
1820 else if (type == 8) tmp = lives_strdup_printf("%d", DEFAULT_AUDIO_SAMPS);
1821 else if (type == 3) tmp = lives_strdup_printf("%d", rdet->asamps);
1822 else tmp = lives_strdup_printf("%d", (!mainw->multitrack || cfile->achans == 0) ? prefs->mt_def_asamps : cfile->asampsize);
1823 lives_entry_set_text(LIVES_ENTRY(resaudw->entry_asamps), tmp);
1824
1825 if (!strcmp(tmp, "8")) is_8bit = TRUE;
1826 else is_8bit = FALSE;
1827
1828 lives_free(tmp);
1829
1830 if (type == 4) {
1831 lives_signal_sync_connect(LIVES_GUI_OBJECT(combo6), LIVES_WIDGET_CHANGED_SIGNAL,
1832 LIVES_GUI_CALLBACK(apply_button_set_enabled), NULL);
1833 }
1834
1835 vbox = lives_vbox_new(FALSE, 0);
1836 if (type != 4) lives_box_pack_start(LIVES_BOX(hbox2), vbox, FALSE, FALSE, 0);
1837
1838 hbox = lives_hbox_new(FALSE, 0);
1839 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
1840
1841 resaudw->rb_signed = lives_standard_radio_button_new(_("Signed"), &s2_group, LIVES_BOX(hbox), NULL);
1842
1843 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(resaudw->rb_signed), TRUE);
1844 if (type == 7 || is_8bit) lives_widget_set_sensitive(resaudw->rb_signed, FALSE);
1845
1846 hbox = lives_hbox_new(FALSE, 0);
1847 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
1848
1849 resaudw->rb_unsigned = lives_standard_radio_button_new(_("Unsigned"), &s2_group, LIVES_BOX(hbox), NULL);
1850
1851 if (type == 7 || !is_8bit) lives_widget_set_sensitive(resaudw->rb_unsigned, FALSE);
1852
1853 if (type < 3 || (type > 4 && type < 8) || type == 11) aendian = mainw->fx4_val;
1854 else if (type == 8) aendian = DEFAULT_AUDIO_SIGNED16 | ((capable->byte_order == LIVES_BIG_ENDIAN) ? AFORM_BIG_ENDIAN : 0);
1855 else if (type == 3) aendian = rdet->aendian;
1856 else aendian = (!mainw->multitrack || cfile->achans == 0) ? prefs->mt_def_signed_endian : cfile->signed_endian;
1857
1858 if (aendian & AFORM_UNSIGNED) {
1860 } else {
1861 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(resaudw->rb_signed), TRUE);
1862 }
1863
1864 if (type == 4) {
1865 lives_signal_sync_connect(LIVES_GUI_OBJECT(resaudw->rb_signed), LIVES_WIDGET_TOGGLED_SIGNAL,
1866 LIVES_GUI_CALLBACK(apply_button_set_enabled), NULL);
1867 lives_signal_sync_connect(LIVES_GUI_OBJECT(resaudw->rb_unsigned), LIVES_WIDGET_TOGGLED_SIGNAL,
1868 LIVES_GUI_CALLBACK(apply_button_set_enabled), NULL);
1869 }
1870
1871 vbox = lives_vbox_new(FALSE, 0);
1872 lives_box_pack_start(LIVES_BOX(hbox2), vbox, FALSE, FALSE, 0);
1873
1874 hbox = lives_hbox_new(FALSE, 0);
1875 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
1876
1877 resaudw->rb_littleend = lives_standard_radio_button_new(_("Little Endian"), &e2_group, LIVES_BOX(hbox), NULL);
1878
1880
1881 hbox = lives_hbox_new(FALSE, 0);
1882 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
1883
1884 resaudw->rb_bigend = lives_standard_radio_button_new(_("Big Endian"), &e2_group, LIVES_BOX(hbox), NULL);
1885
1887
1888 if (aendian & AFORM_BIG_ENDIAN) {
1889 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(resaudw->rb_bigend), TRUE);
1890 } else {
1892 }
1893
1894 if (!strcmp(lives_entry_get_text(LIVES_ENTRY(resaudw->entry_asamps)), "8")) {
1897 }
1898
1899 lives_signal_sync_connect(LIVES_GUI_OBJECT(resaudw->entry_asamps), LIVES_WIDGET_CHANGED_SIGNAL,
1900 LIVES_GUI_CALLBACK(on_resaudw_asamps_changed), NULL);
1901 }
1902
1903 if (type == 4) {
1904 lives_signal_sync_connect(LIVES_GUI_OBJECT(resaudw->rb_littleend), LIVES_WIDGET_TOGGLED_SIGNAL,
1905 LIVES_GUI_CALLBACK(apply_button_set_enabled), NULL);
1906 lives_signal_sync_connect(LIVES_GUI_OBJECT(resaudw->rb_bigend), LIVES_WIDGET_TOGGLED_SIGNAL,
1907 LIVES_GUI_CALLBACK(apply_button_set_enabled), NULL);
1908 }
1909
1910 if (type > 7 && type != 11) {
1911 frame = lives_standard_frame_new(_("Video"), 0., FALSE);
1912 lives_box_pack_start(LIVES_BOX(vboxx), frame, TRUE, TRUE, 0);
1913
1914 hbox = lives_hbox_new(FALSE, 0);
1915 lives_container_add(LIVES_CONTAINER(frame), hbox);
1917
1918 resaudw->fps_spinbutton = lives_standard_spin_button_new(_("_Frames Per Second "),
1919 prefs->default_fps, 1., FPS_MAX, 1., 1., 3, LIVES_BOX(hbox), NULL);
1920 }
1921
1922 if (type > 4 && type != 11) {
1923 lives_box_set_spacing(LIVES_BOX(dialog_vbox), widget_opts.packing_height * 3);
1924
1925 hbox = lives_hbox_new(FALSE, 0);
1926 lives_box_pack_start(LIVES_BOX(dialog_vbox), hbox, TRUE, TRUE, widget_opts.packing_height);
1927
1928 if (type != 6 && type != 7) {
1929 radiobutton = lives_standard_radio_button_new(_("Record for maximum: "), &rbgroup, LIVES_BOX(hbox), NULL);
1930
1932 0., hours > 23 ? hours : 23, 1., 1., 0, LIVES_BOX(hbox), NULL);
1933
1935 0., 59., 1., 10., 0, LIVES_BOX(hbox), NULL);
1936
1938 0., 59., 1., 10., 0, LIVES_BOX(hbox), NULL);
1939
1940 hbox = lives_hbox_new(FALSE, 0);
1941 lives_box_pack_start(LIVES_BOX(dialog_vbox), hbox, TRUE, TRUE, widget_opts.packing_height);
1942
1943 resaudw->unlim_radiobutton = lives_standard_radio_button_new(_("Unlimited"), &rbgroup, LIVES_BOX(hbox), NULL);
1944
1945 lives_signal_sync_connect(LIVES_GUI_OBJECT(radiobutton), LIVES_WIDGET_TOGGLED_SIGNAL,
1946 LIVES_GUI_CALLBACK(on_rb_audrec_time_toggled),
1947 (livespointer)resaudw);
1948
1949 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(resaudw->unlim_radiobutton), (type == 5 || type > 7) && type != 11);
1950
1951 }
1952
1953 if (type < 8 || type == 11) {
1954 hseparator = lives_hseparator_new();
1955 lives_box_pack_start(LIVES_BOX(dialog_vbox), hseparator, TRUE, TRUE, 0);
1956
1957 label = lives_standard_label_new(_("Click OK to begin recording, or Cancel to quit."));
1958
1959 lives_box_pack_start(LIVES_BOX(dialog_vbox), label, TRUE, TRUE, 0);
1960 }
1961 }
1962
1963 if (type < 3 || type > 4) {
1964 cancelbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(resaudw->dialog), LIVES_STOCK_CANCEL, NULL,
1965 LIVES_RESPONSE_CANCEL);
1966
1967 if (accel_group) lives_widget_add_accelerator(cancelbutton, LIVES_WIDGET_CLICKED_SIGNAL, accel_group,
1968 LIVES_KEY_Escape, (LiVESXModifierType)0, (LiVESAccelFlags)0);
1969
1970
1971 okbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(resaudw->dialog), LIVES_STOCK_OK, NULL,
1972 LIVES_RESPONSE_OK);
1973
1975
1976 if (type < 8 || type == 11) {
1977 lives_signal_sync_connect(LIVES_GUI_OBJECT(cancelbutton), LIVES_WIDGET_CLICKED_SIGNAL,
1978 LIVES_GUI_CALLBACK(lives_general_button_clicked), resaudw);
1979
1980 if (type == 1) {
1981 lives_signal_sync_connect(LIVES_GUI_OBJECT(okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
1982 LIVES_GUI_CALLBACK(on_resaudio_ok_clicked), NULL);
1983 } else if (type == 2 || type == 11) {
1984 lives_signal_sync_connect(LIVES_GUI_OBJECT(okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
1985 LIVES_GUI_CALLBACK(on_ins_silence_details_clicked), NULL);
1986 } else if (type == 5) {
1987 lives_signal_sync_connect(LIVES_GUI_OBJECT(okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
1988 LIVES_GUI_CALLBACK(on_recaudclip_ok_clicked),
1989 LIVES_INT_TO_POINTER(0));
1990 } else if (type == 6 || type == 7) {
1991 lives_signal_sync_connect(LIVES_GUI_OBJECT(okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
1992 LIVES_GUI_CALLBACK(on_recaudclip_ok_clicked),
1993 LIVES_INT_TO_POINTER(1));
1994 }
1995
1996 }
1997
1999 } else {
2000 if (resaudw->aud_checkbutton) {
2001 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(resaudw->aud_checkbutton), LIVES_WIDGET_TOGGLED_SIGNAL,
2002 LIVES_GUI_CALLBACK(on_resaudw_achans_changed), (livespointer)resaudw);
2003 on_resaudw_achans_changed(resaudw->aud_checkbutton, (livespointer)resaudw);
2004 }
2005 }
2006
2007 lives_widget_show_all(vboxx);
2008
2009 lives_list_free(channels);
2010 lives_list_free(sampsize);
2011 lives_list_free(rate);
2012
2013 return resaudw;
2014}
2015
2016
2017void on_change_speed_activate(LiVESMenuItem * menuitem, livespointer user_data) {
2018 // change speed from the menu
2021 mainw->fx1_val = cfile->fps;
2022}
2023
2024
2025void on_change_speed_ok_clicked(LiVESButton * button, livespointer user_data) {
2026 double arate = cfile->arate / cfile->fps;
2027 char *msg;
2028 boolean bad_header = FALSE;
2029 //int new_frames = count_resampled_frames(cfile->frames, mainw->fx1_val, cfile->fps);
2030
2031 // change playback rate
2032 if (button) {
2033 lives_general_button_clicked(button, NULL);
2034 }
2035
2036 if (mainw->fx2_bool) {
2037 mainw->fx1_val = (double)((int)((double)cfile->frames / mainw->fx2_val * 1000. + .5)) / 1000.;
2038 if (mainw->fx1_val < 1.) mainw->fx1_val = 1.;
2040 }
2041
2042 char *tmp = (_("Changing the clip fps"));
2047 if (!check_for_layout_errors(tmp, mainw->current_file, 1, 0, &chk_mask)) {
2048 lives_free(tmp);
2049 return;
2050 }
2051 lives_free(tmp);
2052
2053 if (button == NULL) {
2054 mainw->fx1_bool = !(cfile->undo1_int == cfile->arate);
2055 mainw->fx1_val = cfile->undo1_dbl;
2056 }
2057
2058 set_undoable(_("Speed Change"), TRUE);
2059 cfile->undo1_dbl = cfile->fps;
2060 cfile->undo1_int = cfile->arate;
2061 cfile->undo_action = UNDO_CHANGE_SPEED;
2062
2063 if (mainw->fx1_val == 0.) mainw->fx1_val = 1.;
2064
2065 // update the frame rate
2066 cfile->pb_fps = cfile->fps = mainw->fx1_val;
2067
2068 lives_spin_button_set_value(LIVES_SPIN_BUTTON(mainw->spinbutton_pb_fps), cfile->pb_fps);
2069
2070 if (mainw->fx1_bool) {
2071 cfile->arate = (int)(arate * cfile->fps + .5);
2072 msg = lives_strdup_printf(_("Changed playback speed to %.3f frames per second and audio to %d Hz.\n"), cfile->fps,
2073 cfile->arate);
2074 } else {
2075 msg = lives_strdup_printf(_("Changed playback speed to %.3f frames per second.\n"), cfile->fps);
2076 }
2077 d_print(msg);
2078 lives_free(msg);
2079
2080 cfile->ratio_fps = FALSE;
2081
2082 if (cfile->clip_type == CLIP_TYPE_FILE && cfile->ext_src) {
2083 lives_clip_data_t *cdata = ((lives_decoder_t *)cfile->ext_src)->cdata;
2084 double dfps = (double)cdata->fps;
2085 if (!save_clip_value(mainw->current_file, CLIP_DETAILS_FPS, &dfps)) bad_header = TRUE;
2086 if (!save_clip_value(mainw->current_file, CLIP_DETAILS_PB_FPS, &cfile->fps)) bad_header = TRUE;
2087 } else {
2088 if (!save_clip_value(mainw->current_file, CLIP_DETAILS_FPS, &cfile->fps)) bad_header = TRUE;
2089 if (!save_clip_value(mainw->current_file, CLIP_DETAILS_PB_FPS, &cfile->pb_fps)) bad_header = TRUE;
2090 }
2091
2092 if (!save_clip_value(mainw->current_file, CLIP_DETAILS_PB_ARATE, &cfile->arate)) bad_header = TRUE;
2093 if (bad_header) do_header_write_error(mainw->current_file);
2094
2096
2097 if (chk_mask != 0) popup_lmap_errors(NULL, LIVES_INT_TO_POINTER(chk_mask));
2098
2099 if (mainw->sl_undo_mem && cfile->stored_layout_frame != 0) {
2100 // need to invalidate undo/redo stack, in case file was used in some layout undo
2102 }
2103}
2104
2105
2106int reorder_frames(int rwidth, int rheight) {
2107 int new_frames = cfile->old_frames;
2108 int cur_frames = cfile->frames;
2109 char **array;
2110 char *com;
2111
2112 if (rwidth * rheight == 0) com = lives_strdup_printf("%s reorder \"%s\" \"%s\" %d 0 0 %d %d", prefs->backend, cfile->handle,
2114 reorder_leave_back, cfile->frames);
2115 else {
2116 if (!prefs->enc_letterbox) {
2117 com = lives_strdup_printf("%s reorder \"%s\" \"%s\" %d %d %d 0 %d", prefs->backend, cfile->handle,
2118 get_image_ext_for_type(cfile->img_type), !mainw->endian, rwidth, rheight, cfile->frames);
2119 } else {
2120 int iwidth = cfile->hsize, iheight = cfile->vsize;
2121 calc_maxspect(rwidth, rheight, &iwidth, &iheight);
2122
2123 if (iwidth == cfile->hsize && iheight == cfile->vsize) {
2124 iwidth = -iwidth;
2125 iheight = -iheight;
2126 }
2127
2128 else {
2131 return -cur_frames;
2132 }
2133
2136 return -cur_frames;
2137 }
2138 }
2139 com = lives_strdup_printf("%s reorder \"%s\" \"%s\" %d %d %d %d %d %d %d", prefs->backend, cfile->handle,
2140 get_image_ext_for_type(cfile->img_type), !mainw->endian, rwidth, rheight,
2141 reorder_leave_back, cfile->frames, iwidth, iheight);
2142 }
2143 }
2144
2145 cfile->frames = 0;
2146
2147 cfile->progress_start = 1;
2148 cfile->progress_end = save_event_frames(); // we convert cfile->event_list to a block and save it
2149
2150 if (cfile->progress_end == -1) return -cur_frames; // save_event_frames failed
2151
2152 if (cur_frames > cfile->progress_end) cfile->progress_end = cur_frames;
2153
2154 cfile->next_event = NULL;
2155 if (cfile->event_list) {
2156 if (cfile->event_list_back) event_list_free(cfile->event_list_back);
2157 cfile->event_list_back = cfile->event_list;
2158 cfile->event_list = NULL;
2159 }
2160
2161 lives_rm(cfile->info_file);
2162 mainw->error = FALSE;
2163 lives_system(com, FALSE);
2164 if (THREADVAR(com_failed)) return -cur_frames;
2165
2166 if (cfile->undo_action == UNDO_RESAMPLE) {
2167 if (mainw->current_file > 0) {
2168 cfile->nopreview = cfile->nokeep = TRUE;
2169 if (!do_progress_dialog(TRUE, TRUE, _("Resampling video"))) {
2170 cfile->nopreview = cfile->nokeep = FALSE;
2171 return cur_frames;
2172 }
2173 cfile->nopreview = cfile->nokeep = FALSE;
2174 } else {
2175 do_progress_dialog(TRUE, FALSE, _("Resampling clipboard video"));
2176 }
2177 } else {
2178 cfile->nopreview = cfile->nokeep = TRUE;
2179 if (!do_progress_dialog(TRUE, TRUE, _("Reordering frames"))) {
2180 cfile->nopreview = cfile->nokeep = FALSE;
2181 return cur_frames;
2182 }
2183 cfile->nopreview = cfile->nokeep = FALSE;
2184 }
2185 lives_free(com);
2186
2187 if (mainw->error) {
2189 if (mainw->cancelled != CANCEL_ERROR) do_error_dialog(_("\n\nLiVES was unable to reorder the frames."));
2191 deorder_frames(new_frames, FALSE);
2192 new_frames = -new_frames;
2193 } else {
2194 array = lives_strsplit(mainw->msg, "|", 2);
2195
2196 new_frames = atoi(array[1]);
2197 lives_strfreev(array);
2198
2199 if (cfile->frames > new_frames) {
2200 new_frames = cfile->frames;
2201 }
2202 }
2203
2204 return new_frames;
2205}
2206
2207
2208int deorder_frames(int old_frames, boolean leave_bak) {
2209 char *com;
2210 ticks_t time_start;
2211 int perf_start, perf_end;
2212
2213 if (cfile->event_list) return cfile->frames;
2214
2215 cfile->event_list = cfile->event_list_back;
2216 cfile->event_list_back = NULL;
2217
2218 if (cfile->event_list == NULL) {
2219 perf_start = 1;
2220 perf_end = old_frames;
2221 } else {
2222 time_start = get_event_timecode(get_first_event(cfile->event_list));
2223 perf_start = (int)(cfile->fps * (double)time_start / TICKS_PER_SECOND_DBL) + 1;
2224 perf_end = perf_start + count_events(cfile->event_list, FALSE, 0, 0) - 1;
2225 }
2226 com = lives_strdup_printf("%s deorder \"%s\" %d %d %d \"%s\" %d", prefs->backend, cfile->handle,
2227 perf_start, cfile->frames, perf_end,
2228 get_image_ext_for_type(cfile->img_type), leave_bak);
2229
2230 lives_rm(cfile->info_file);
2231 lives_system(com, TRUE);
2232 if (THREADVAR(com_failed)) return cfile->frames;
2233
2234 do_progress_dialog(TRUE, FALSE, _("Deordering frames"));
2235 lives_free(com);
2236
2237 // check for EOF
2238
2239 if (cfile->frame_index_back) {
2240 int current_frames = cfile->frames;
2241 cfile->frames = old_frames;
2243 cfile->frames = current_frames;
2244 }
2245
2246 return old_frames;
2247}
2248
2249
2250boolean resample_clipboard(double new_fps) {
2251 // resample the clipboard video - if we already did it once, it is
2252 // quicker the second time
2253 char *com;
2254 int current_file = mainw->current_file;
2255
2257
2258 if (clipboard->undo1_dbl == new_fps && !prefs->conserve_space) {
2259 int new_frames;
2260 double old_fps = clipboard->fps;
2261
2262 if (new_fps == clipboard->fps) {
2264 return TRUE;
2265 }
2266
2267 // we already resampled to this fps
2268 new_frames = count_resampled_frames(clipboard->frames, clipboard->fps, new_fps);
2269
2270 mainw->current_file = 0;
2271
2272 // copy .mgk to .img_ext and .img_ext to .bak (i.e redo the resample)
2273 com = lives_strdup_printf("%s redo \"%s\" %d %d \"%s\"", prefs->backend, cfile->handle, 1, new_frames,
2274 get_image_ext_for_type(cfile->img_type));
2275 lives_rm(cfile->info_file);
2276 lives_system(com, FALSE);
2277
2278 if (THREADVAR(com_failed)) {
2281 return FALSE;
2282 }
2283
2284 cfile->progress_start = 1;
2285 cfile->progress_end = new_frames;
2286 cfile->old_frames = cfile->frames;
2287 // show a progress dialog, not cancellable
2288 do_progress_dialog(TRUE, FALSE, _("Resampling clipboard video"));
2289 lives_free(com);
2290 cfile->frames = new_frames;
2291 cfile->undo_action = UNDO_RESAMPLE;
2292 cfile->fps = cfile->undo1_dbl;
2293 lives_spin_button_set_value(LIVES_SPIN_BUTTON(mainw->spinbutton_pb_fps), cfile->fps);
2294 cfile->undo1_dbl = old_fps;
2295 d_print(_("Clipboard was resampled to %d frames.\n"), cfile->frames);
2296 mainw->current_file = current_file;
2297 } else {
2298 if (clipboard->undo1_dbl < clipboard->fps) {
2299 int old_frames = count_resampled_frames(clipboard->frames, clipboard->fps, clipboard->undo1_dbl);
2300 mainw->current_file = 0;
2301 com = lives_strdup_printf("%s undo \"%s\" %d %d \"%s\"", prefs->backend, cfile->handle, old_frames + 1, cfile->frames,
2302 get_image_ext_for_type(cfile->img_type));
2303 lives_rm(cfile->info_file);
2304 lives_system(com, FALSE);
2305 cfile->progress_start = old_frames + 1;
2306 cfile->progress_end = cfile->frames;
2307 // show a progress dialog, not cancellable
2308 do_progress_dialog(TRUE, FALSE, _("Resampling clipboard video"));
2309 lives_free(com);
2310 }
2311
2312 // resample to cfile fps
2313 mainw->current_file = current_file;
2314 clipboard->undo1_dbl = new_fps;
2315
2316 if (new_fps == clipboard->fps) {
2318 return TRUE;
2319 }
2320
2321 mainw->current_file = 0;
2322 on_resample_vid_ok(NULL, NULL);
2323 mainw->current_file = current_file;
2324 if (clipboard->fps != new_fps) {
2325 d_print(_("resampling error..."));
2326 mainw->error = 1;
2328 return FALSE;
2329 }
2330 // clipboard->fps now holds new_fps, clipboard->undo1_dbl holds orig fps
2331 // BUT we will later undo this, then clipboard->fps will hold orig fps,
2332 // clipboard->undo1_dbl will hold resampled fps
2333
2334 }
2335
2337 return TRUE;
2338}
LIVES_GLOBAL_INLINE lives_audio_track_state_t * audio_frame_to_atstate(weed_event_t *event, int *ntracks)
Definition: audio.c:2405
#define DEFAULT_AUDIO_SIGNED16
Definition: audio.h:27
#define DEFAULT_AUDIO_SAMPS
Definition: audio.h:25
#define DEFAULT_AUDIO_CHANS
Definition: audio.h:24
#define DEFAULT_AUDIO_RATE
defaults for when not specifed
Definition: audio.h:23
void on_ins_silence_details_clicked(LiVESButton *button, livespointer user_data)
Definition: callbacks.c:12830
void on_recaudclip_ok_clicked(LiVESButton *button, livespointer user_data)
Definition: callbacks.c:12446
void on_rb_audrec_time_toggled(LiVESToggleButton *togglebutton, livespointer user_data)
Definition: callbacks.c:12378
void popup_lmap_errors(LiVESMenuItem *menuitem, livespointer user_data)
Definition: callbacks.c:9335
void on_undo_activate(LiVESWidget *menuitem, livespointer user_data)
Definition: callbacks.c:2275
boolean check_for_layout_errors(const char *operation, int fileno, int start, int end, uint32_t *in_mask)
check for layout errors, using in_mask as a guide (mask values are taken from prefs->warn_mask,...
Definition: callbacks.c:4059
int resize_all(int fileno, int width, int height, lives_img_type_t imgtype, boolean do_back, int *nbad, int *nmiss)
utility funcs for GUI
void restore_frame_index_back(int sfileno)
Definition: cvirtual.c:1000
frames_t realize_all_frames(int clipno, const char *msg, boolean enough)
Definition: cvirtual.c:849
boolean do_header_write_error(int clip)
Definition: dialogs.c:4169
LIVES_GLOBAL_INLINE void do_lb_convert_error(void)
Definition: dialogs.c:3652
LiVESResponseType do_memory_error_dialog(char *op, size_t bytes)
Definition: dialogs.c:904
LIVES_GLOBAL_INLINE void do_lb_composite_error(void)
Definition: dialogs.c:3645
LIVES_GLOBAL_INLINE LiVESResponseType do_error_dialog(const char *text)
Definition: dialogs.c:749
boolean do_progress_dialog(boolean visible, boolean cancellable, const char *text)
Definition: dialogs.c:2274
boolean check_backend_return(lives_clip_t *sfile)
Definition: dialogs.c:1009
#define WEED_LEAF_HOST_SCRAP_FILE_OFFSET
Definition: effects-weed.h:88
#define WEED_LEAF_HOST_TAG
Definition: effects-weed.h:66
weed_plant_t * get_last_frame_event(weed_plant_t *event_list)
Definition: events.c:419
LIVES_GLOBAL_INLINE weed_timecode_t weed_event_get_timecode(weed_event_t *event)
Definition: events.c:89
frames_t get_frame_event_frame(weed_plant_t *event, int layer)
Definition: events.c:224
int get_frame_event_clip(weed_plant_t *event, int layer)
Definition: events.c:209
LIVES_GLOBAL_INLINE int weed_event_get_type(weed_event_t *event)
Definition: events.c:31
weed_plant_t * insert_frame_event_at(weed_plant_t *event_list, weed_timecode_t tc, int numframes, int *clips, int64_t *frames, weed_plant_t **shortcut)
Definition: events.c:1144
void insert_audio_event_at(weed_plant_t *event, int track, int clipnum, double seek, double vel)
Definition: events.c:1243
LIVES_GLOBAL_INLINE weed_plant_t * get_first_event(weed_plant_t *event_list)
Definition: events.c:119
int count_events(weed_plant_t *event_list, boolean all_events, weed_timecode_t start_tc, weed_timecode_t end_tc)
Definition: events.c:4542
LIVES_GLOBAL_INLINE weed_timecode_t get_event_timecode(weed_plant_t *plant)
Definition: events.c:98
LIVES_GLOBAL_INLINE weed_plant_t * get_last_event(weed_plant_t *event_list)
Definition: events.c:124
void reset_ttable(void)
Definition: events.c:486
LIVES_GLOBAL_INLINE int weed_frame_event_get_tracks(weed_event_t *event, int **clips, int64_t **frames)
Definition: events.c:36
void event_list_free(weed_plant_t *event_list)
Definition: events.c:2313
weed_plant_t * get_first_frame_event(weed_plant_t *event_list)
Definition: events.c:404
weed_plant_t * get_prev_audio_frame_event(weed_plant_t *event)
Definition: events.c:392
weed_plant_t * append_frame_event(weed_plant_t *event_list, weed_timecode_t tc, int numframes, int *clips, int64_t *frames)
Definition: events.c:2610
LIVES_GLOBAL_INLINE weed_plant_t * get_next_event(weed_plant_t *event)
Definition: events.c:114
weed_plant_t * get_next_frame_event(weed_plant_t *event)
Definition: events.c:356
LIVES_GLOBAL_INLINE weed_timecode_t weed_event_set_timecode(weed_event_t *event, weed_timecode_t tc)
Definition: events.c:83
weed_plant_t * event_copy_and_insert(weed_plant_t *in_event, weed_timecode_t out_tc, weed_plant_t *event_list, weed_event_t **ret_event)
copy (duplicate) in_event and append it to event_list, changing the timecode to out_tc this is called...
Definition: events.c:622
LIVES_GLOBAL_INLINE int weed_frame_event_get_audio_tracks(weed_event_t *event, int **clips, double **seeks)
Definition: events.c:59
#define WEED_LEAF_FIRST
Definition: events.h:64
#define EVENT_MARKER_RECORD_START
Definition: events.h:355
#define WEED_EVENT_IS_FRAME(event)
Definition: events.h:361
#define WEED_LEAF_LAST
Definition: events.h:65
#define WEED_LEAF_PREV_CHANGE
Definition: events.h:72
#define WEED_LEAF_AUDIO_SEEKS
Definition: events.h:41
#define WEED_EVENT_IS_AUDIO_FRAME(event)
Definition: events.h:362
#define WEED_LEAF_NEXT_CHANGE
Definition: events.h:71
#define WEED_LEAF_AUDIO_CLIPS
Definition: events.h:40
#define WEED_LEAF_INIT_EVENT
Definition: events.h:52
#define WEED_LEAF_WEED_EVENT_API_VERSION
parts of this may eventually become libweed-events
Definition: events.h:18
render_details * rdet
Definition: events.h:256
#define WEED_LEAF_LIVES_TYPE
Definition: events.h:79
weed_plant_t weed_event_t
Definition: events.h:97
#define WEED_LEAF_OVERLAY_TEXT
Definition: events.h:90
#define WEED_LEAF_INDEX
Definition: events.h:58
#define EVENT_MARKER_BLOCK_START
Definition: events.h:353
#define WEED_LEAF_FRAMES
Definition: events.h:38
#define EVENT_MARKER_BLOCK_UNORDERED
Definition: events.h:354
void create_new_pb_speed(short type)
window change speed from Tools menu
Definition: interface.c:3464
void reget_afilesize(int fileno)
Definition: machinestate.c:972
#define THREADVAR(var)
Definition: machinestate.h:531
#define lives_free
Definition: machinestate.h:52
#define lives_malloc
Definition: machinestate.h:46
#define lives_realloc
Definition: machinestate.h:49
void load_end_image(int frame)
Definition: main.c:5922
void sensitize(void)
Definition: main.c:5078
void load_start_image(int frame)
Definition: main.c:5650
ssize_t sizdbl
Definition: main.c:102
ssize_t sizint
type sizes
Definition: main.c:102
mainwindow * mainw
Definition: main.c:103
void switch_to_file(int old_file, int new_file)
Definition: main.c:9646
int frames_t
Definition: main.h:99
#define clipboard
Definition: main.h:1835
@ UNDO_AUDIO_RESAMPLE
Definition: main.h:667
@ UNDO_CHANGE_SPEED
Definition: main.h:666
@ UNDO_RESIZABLE
Definition: main.h:662
@ UNDO_RESAMPLE
Definition: main.h:664
@ UNDO_ATOMIC_RESAMPLE_RESIZE
resample/resize and resample audio for encoding
Definition: main.h:677
#define LIVES_GLOBAL_INLINE
Definition: main.h:239
boolean check_for_ratio_fps(double fps)
Definition: utils.c:5361
int lives_system(const char *com, boolean allow_error)
Definition: utils.c:145
void set_undoable(const char *what, boolean sensitive)
Definition: utils.c:4784
#define AFORM_UNSIGNED
Definition: main.h:786
const char * get_image_ext_for_type(lives_img_type_t imgtype)
Definition: utils.c:3025
#define FPS_MAX
maximum fps we will allow (double)
Definition: main.h:218
boolean save_clip_values(int which_file)
Definition: saveplay.c:103
@ CLIP_DETAILS_PB_FPS
Definition: main.h:1144
@ CLIP_DETAILS_HEIGHT
Definition: main.h:1146
@ CLIP_DETAILS_FPS
Definition: main.h:1143
@ CLIP_DETAILS_WIDTH
Definition: main.h:1145
@ CLIP_DETAILS_PB_ARATE
Definition: main.h:1149
@ CLIP_DETAILS_FRAMES
Definition: main.h:1154
int lives_rm(const char *file)
Definition: utils.c:4395
int64_t ticks_t
Definition: main.h:97
void d_print_failed(void)
Definition: utils.c:2615
capability * capable
Definition: main.h:627
#define cfile
Definition: main.h:1833
void d_print(const char *fmt,...)
Definition: utils.c:2542
int save_event_frames(void)
Definition: saveplay.c:5121
#define AFORM_BIG_ENDIAN
Definition: main.h:787
void unbuffer_lmap_errors(boolean add)
Definition: utils.c:2656
uint32_t get_signed_endian(boolean is_signed, boolean little_endian)
produce bitmapped value
Definition: utils.c:5408
void calc_maxspect(int rwidth, int rheight, int *cwidth, int *cheight)
Definition: utils.c:2174
void d_print_done(void)
Definition: utils.c:2620
boolean lives_freep(void **ptr)
Definition: utils.c:1411
@ CLIP_TYPE_FILE
unimported video, not or partially broken in frames
Definition: main.h:765
boolean save_clip_value(int which, lives_clip_details_t, void *val)
Definition: utils.c:5175
@ CANCEL_NONE
no cancel
Definition: main.h:701
@ CANCEL_ERROR
cancelled because of error
Definition: main.h:740
#define DEF_DIALOG_HEIGHT
Definition: mainwindow.h:186
#define TICKS_PER_SECOND
ticks per second - GLOBAL TIMEBASE
Definition: mainwindow.h:36
#define TICKS_PER_SECOND_DBL
actually microseconds / 100.
Definition: mainwindow.h:37
#define DEF_DIALOG_WIDTH
Definition: mainwindow.h:185
void stored_event_list_free_undos(void)
Definition: multitrack.c:5842
void apply_button_set_enabled(LiVESWidget *widget, livespointer func_data)
Definition: preferences.c:2911
#define WARN_MASK_LAYOUT_DELETE_FRAMES
Definition: preferences.h:96
_prefs * prefs
Definition: preferences.h:847
#define WARN_MASK_LAYOUT_DELETE_AUDIO
Definition: preferences.h:110
#define WARN_MASK_LAYOUT_ALTER_FRAMES
off by default on a fresh install
Definition: preferences.h:102
#define WARN_MASK_LAYOUT_ALTER_AUDIO
off by default on a fresh install
Definition: preferences.h:116
_prefsw * prefsw
Definition: preferences.h:849
#define WARN_MASK_LAYOUT_SHIFT_FRAMES
off by default on a fresh install
Definition: preferences.h:99
#define WARN_MASK_LAYOUT_SHIFT_AUDIO
off by default on a fresh install
Definition: preferences.h:113
void on_change_speed_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: resample.c:2017
#define SMTH_TC_LIM
Definition: resample.c:305
void on_resaudio_ok_clicked(LiVESButton *button, LiVESEntry *entry)
Definition: resample.c:1159
_resaudw * create_resaudw(short type, render_details *rdet, LiVESWidget *top_vbox)
resample audio window
Definition: resample.c:1521
void on_resample_vid_ok(LiVESButton *button, LiVESEntry *entry)
Definition: resample.c:1379
LIVES_GLOBAL_INLINE ticks_t q_gint64_floor(ticks_t in, double fps)
Definition: resample.c:35
int deorder_frames(int old_frames, boolean leave_bak)
leave_bak is a special mode for the clipboard
Definition: resample.c:2208
void on_resample_video_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: resample.c:1372
weed_plant_t * quantise_events(weed_plant_t *in_list, double qfps, boolean allow_gap)
quantise from event_list_t *in_list to *out_list at the new rate of qfps
Definition: resample.c:456
int reorder_frames(int rwidth, int rheight)
Definition: resample.c:2106
void on_change_speed_ok_clicked(LiVESButton *button, livespointer user_data)
Definition: resample.c:2025
void on_resaudw_asamps_changed(LiVESWidget *irrelevant, livespointer rubbish)
Definition: resample.c:1353
LIVES_GLOBAL_INLINE ticks_t q_gint64(ticks_t in, double fps)
Definition: resample.c:25
LIVES_GLOBAL_INLINE int count_resampled_frames(int in_frames, double orig_fps, double resampled_fps)
Definition: resample.c:72
void pre_analyse(weed_plant_t *elist)
Definition: resample.c:307
#define READJ_MIN
Definition: resample.c:302
LIVES_GLOBAL_INLINE ticks_t q_dbl(double in, double fps)
Definition: resample.c:41
boolean auto_resample_resize(int width, int height, double fps, int fps_num, int fps_denom, int arate, int asigned, boolean swap_endian)
Definition: resample.c:80
LIVES_GLOBAL_INLINE double quant_aseek(double seek, int arate)
convert seek time (secs) to an (almost) integer number of samples
Definition: resample.c:58
LIVES_GLOBAL_INLINE size_t quant_asamps(double seek, int arate)
convert seek time to an integer number of samples
Definition: resample.c:52
void on_resample_audio_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: resample.c:1148
boolean resample_clipboard(double new_fps)
call this to resample clipboard video
Definition: resample.c:2250
LIVES_GLOBAL_INLINE off_t quant_abytes(double seek, int arate, int achans, int asampsize)
Definition: resample.c:66
void reorder_leave_back_set(boolean val)
Definition: resample.c:21
#define SMTH_FRAME_LIM
Definition: resample.c:304
#define LETTERBOX_NEEDS_COMPOSITE
Definition: resample.h:14
#define SKJUMP_THRESH_RATIO
Definition: resample.h:50
_resaudw * resaudw
Definition: resample.h:38
#define SKJUMP_THRESH_SECS
Definition: resample.h:51
#define LETTERBOX_NEEDS_CONVERT
Definition: resample.h:15
char backend[PATH_MAX *4]
Definition: preferences.h:411
int rr_fstate
Definition: preferences.h:493
int mt_def_arate
Definition: preferences.h:273
boolean rr_pre_smooth
Definition: preferences.h:491
boolean rr_super
Definition: preferences.h:490
double default_fps
Definition: preferences.h:173
int mt_def_signed_endian
Definition: preferences.h:273
int rr_qmode
Definition: preferences.h:489
boolean enc_letterbox
encode with letterbox
Definition: preferences.h:364
int mt_def_achans
Definition: preferences.h:273
int mt_def_asamps
Definition: preferences.h:273
boolean rr_qsmooth
Definition: preferences.h:492
boolean conserve_space
Definition: preferences.h:183
boolean rr_amicro
Definition: preferences.h:494
LiVESWidget * backaudio_checkbutton
Definition: preferences.h:725
LiVESWidget * pertrack_checkbutton
Definition: preferences.h:724
resample audio window
Definition: resample.h:18
LiVESWidget * aud_checkbutton
Definition: resample.h:32
LiVESWidget * minute_spinbutton
Definition: resample.h:29
LiVESWidget * hour_spinbutton
Definition: resample.h:28
LiVESWidget * rb_signed
Definition: resample.h:23
LiVESWidget * vbox
Definition: resample.h:34
LiVESWidget * entry_asamps
Definition: resample.h:22
LiVESWidget * second_spinbutton
Definition: resample.h:30
LiVESWidget * rb_littleend
Definition: resample.h:26
LiVESWidget * fps_spinbutton
Definition: resample.h:31
LiVESWidget * rb_unsigned
Definition: resample.h:24
LiVESWidget * unlim_radiobutton
Definition: resample.h:27
LiVESWidget * rb_bigend
Definition: resample.h:25
LiVESWidget * aud_hbox
Definition: resample.h:33
LiVESWidget * entry_arate
Definition: resample.h:20
LiVESWidget * entry_achans
Definition: resample.h:21
LiVESWidget * dialog
Definition: resample.h:19
int byte_order
Definition: main.h:577
lives_checkstatus_t has_composite
Definition: main.h:515
lives_checkstatus_t has_convert
Definition: main.h:514
int arps
audio physical sample rate (i.e the "normal" sample rate of the clip when played at 1,...
Definition: main.h:905
char msg[MAINW_MSG_SIZE]
Definition: mainwindow.h:724
boolean fx1_bool
Definition: mainwindow.h:1053
unsigned char * sl_undo_mem
Definition: mainwindow.h:812
boolean resizing
Definition: mainwindow.h:822
lives_clip_t * files[MAX_FILES+1]
+1 for the clipboard
Definition: mainwindow.h:729
boolean fx2_bool
Definition: mainwindow.h:1053
double fx2_val
Definition: mainwindow.h:1049
volatile lives_cancel_t cancelled
Definition: mainwindow.h:798
int current_file
Definition: mainwindow.h:727
short endian
Definition: mainwindow.h:817
int scrap_file
we throw odd sized frames here when recording in real time; used if a source is a generator or stream
Definition: mainwindow.h:874
LiVESWidget * spinbutton_pb_fps
Definition: mainwindow.h:1391
boolean no_switch_dprint
Definition: mainwindow.h:1536
double fx1_val
Definition: mainwindow.h:1049
double rec_end_time
Definition: mainwindow.h:1526
boolean error
Definition: mainwindow.h:801
double fx4_val
Definition: mainwindow.h:1049
lives_mt * multitrack
holds a pointer to the entire multitrack environment; NULL in Clip Edit mode
Definition: mainwindow.h:1087
double fx3_val
Definition: mainwindow.h:1049
LiVESWidget * pertrack_checkbutton
Definition: events.h:231
LiVESWidget * backaudio_checkbutton
Definition: events.h:232
boolean non_modal
non-modal for dialogs
int packing_height
vertical pixels between widgets
int packing_width
horizontal pixels between widgets
int border_width
border width in pixels
#define lives_strdup_printf(fmt,...)
Definition: support.c:27
#define _(String)
Definition: support.h:44
#define TRUE
Definition: videoplugin.h:59
#define FALSE
Definition: videoplugin.h:60
WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_value(LiVESSpinButton *button, double value)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_vbox_new(boolean homogeneous, int spacing)
WIDGET_HELPER_GLOBAL_INLINE LiVESAccelGroup * lives_accel_group_new(void)
LiVESWidget * lives_standard_entry_new(const char *labeltext, const char *txt, int dispwidth, int maxchars, LiVESBox *box, const char *tooltip)
boolean lives_button_grab_default_special(LiVESWidget *button)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_button_get_active(LiVESToggleButton *button)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_box_pack_start(LiVESBox *box, LiVESWidget *child, boolean expand, boolean fill, uint32_t padding)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_combo_get_entry(LiVESCombo *widget)
LiVESWidget * lives_standard_dialog_new(const char *title, boolean add_std_buttons, int width, int height)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_box_set_spacing(LiVESBox *box, int spacing)
WIDGET_HELPER_GLOBAL_INLINE const char * lives_entry_get_text(LiVESEntry *entry)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_sensitive(LiVESWidget *widget, boolean state)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_show(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_dialog_get_content_area(LiVESDialog *dialog)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_container_set_border_width(LiVESContainer *container, uint32_t width)
LIVES_GLOBAL_INLINE boolean lives_widget_destroy(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_vseparator_new(void)
LiVESWidget * lives_dialog_add_button_from_stock(LiVESDialog *dialog, const char *stock_id, const char *label, int response_id)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_container_add(LiVESContainer *container, LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_button_set_active(LiVESToggleButton *button, boolean active)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_show_all(LiVESWidget *widget)
LiVESWidget * lives_standard_frame_new(const char *labeltext, float xalign, boolean invis)
boolean lives_widget_context_update(void)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_can_focus(LiVESWidget *widget, boolean state)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_hseparator_new(void)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handlers_disconnect_by_func(livespointer instance, LiVESGuiCallback func, livespointer data)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_hbox_new(boolean homogeneous, int spacing)
LiVESWidget * lives_standard_label_new(const char *text)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_width_chars(LiVESEntry *entry, int nchars)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_text(LiVESEntry *entry, const char *text)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_editable_set_editable(LiVESEditable *editable, boolean is_editable)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_max_length(LiVESEntry *entry, int len)
LiVESWidget * lives_standard_check_button_new(const char *labeltext, boolean active, LiVESBox *box, const char *tooltip)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_add_accelerator(LiVESWidget *widget, const char *accel_signal, LiVESAccelGroup *accel_group, uint32_t accel_key, LiVESXModifierType accel_mods, LiVESAccelFlags accel_flags)
LiVESWidget * lives_standard_spin_button_new(const char *labeltext, double val, double min, double max, double step, double page, int dp, LiVESBox *box, const char *tooltip)
LiVESWidget * lives_standard_combo_new(const char *labeltext, LiVESList *list, LiVESBox *box, const char *tooltip)
void lives_general_button_clicked(LiVESButton *button, livespointer data_to_free)
LiVESWidget * lives_standard_radio_button_new(const char *labeltext, LiVESSList **rbgroup, LiVESBox *box, const char *tooltip)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_add_accel_group(LiVESWindow *window, LiVESAccelGroup *group)
widget_opts_t widget_opts