LiVES 3.2.0
saveplay.c
Go to the documentation of this file.
1// saveplay.c
2// LiVES (lives-exe)
3// (c) G. Finch 2003 - 2018 (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#include <fcntl.h>
8#include <glib.h>
9
10#include "main.h"
11#include "callbacks.h"
12#include "resample.h"
13#include "effects.h"
14#include "audio.h"
15#include "htmsocket.h"
16#include "cvirtual.h"
17#include "interface.h"
18
19boolean _start_playback(livespointer data) {
20 int new_file, old_file;
21 int play_type = LIVES_POINTER_TO_INT(data);
22 if (play_type != 8 && mainw->noswitch) return TRUE;
23 switch (play_type) {
24 case 8: case 6: case 0:
26 play_all(play_type == 8);
27 if (play_type == 6) {
29 // need to set this after playback ends; this stops the key from being activated (again) in effects.c
30 // also stops the (now defunct instance being unreffed)
32 }
33 break;
34 case 1:
36 if (!mainw->multitrack) play_sel();
38 break;
39 case 2:
41 mainw->play_start = 1;
42 mainw->play_end = INT_MAX;
43 play_file();
44 break;
45 case 3:
47 mainw->osc_auto = 1;
49 mainw->osc_auto = 0;
50 break;
51 case 4:
53 mainw->osc_auto = 1;
54 if (!mainw->multitrack) play_sel();
56 mainw->osc_auto = 0;
57 break;
58 case 5:
60 play_file();
63
64 if (mainw->pre_play_file > 0) {
66 } else {
67 mainw->current_file = -1;
69 }
73 }
74 break;
75 case 7:
77 new_file = mainw->current_file;
78 old_file = mainw->pre_play_file;
79 play_file();
80 if (mainw->current_file != old_file && mainw->current_file != new_file)
81 old_file = mainw->current_file; // we could have rendered to a new file
82 mainw->current_file = new_file;
83 // close this temporary clip
84 close_current_file(old_file);
85 mainw->pre_play_file = -1;
86 break;
87 default:
89 break;
90 }
91 return FALSE;
92}
93
94LIVES_GLOBAL_INLINE boolean start_playback(int type) {return _start_playback(LIVES_INT_TO_POINTER(type));}
95
97 lives_idle_add(_start_playback, LIVES_INT_TO_POINTER(type));
98 //lives_proc_thread_create(0, (lives_funcptr_t)_start_playback, 0, "i", type);
99 //_start_playback(LIVES_INT_TO_POINTER(type));
100}
101
102
103boolean save_clip_values(int which) {
104 lives_clip_t *sfile = mainw->files[which];
105 char *lives_header_new;
106 boolean all_ok = FALSE;
107 int asigned, endian;
108 int retval;
109
110 if (which == 0 || which == mainw->scrap_file || which == mainw->ascrap_file) return TRUE;
111
113
114 asigned = !(sfile->signed_endian & AFORM_UNSIGNED);
115 endian = sfile->signed_endian & AFORM_BIG_ENDIAN;
116 if (which == mainw->ascrap_file)
117 lives_header_new = lives_build_filename(prefs->workdir, sfile->handle, LIVES_ACLIP_HEADER_NEW, NULL);
118 else
119 lives_header_new = lives_build_filename(prefs->workdir, sfile->handle, LIVES_CLIP_HEADER_NEW, NULL);
120
121 do {
122 THREADVAR(com_failed) = THREADVAR(write_failed) = FALSE;
123 mainw->clip_header = fopen(lives_header_new, "w");
124 if (!mainw->clip_header) {
125 retval = do_write_failed_error_s_with_retry(lives_header_new, lives_strerror(errno));
126 if (retval == LIVES_RESPONSE_CANCEL) {
129 lives_free(lives_header_new);
130 return FALSE;
131 }
132 } else {
134 do {
135 retval = 0;
137 if (!save_clip_value(which, CLIP_DETAILS_BPP, &sfile->bpp)) break;
138 if (sfile->clip_type == CLIP_TYPE_FILE && sfile->ext_src) {
139 lives_clip_data_t *cdata = ((lives_decoder_t *)sfile->ext_src)->cdata;
140 double dfps = (double)cdata->fps;
141 if (!save_clip_value(which, CLIP_DETAILS_FPS, &dfps)) break;
142 if (!save_clip_value(which, CLIP_DETAILS_PB_FPS, &sfile->fps)) break;
143 } else {
144 if (!save_clip_value(which, CLIP_DETAILS_FPS, &sfile->fps)) break;
145 if (!save_clip_value(which, CLIP_DETAILS_PB_FPS, &sfile->pb_fps)) break;
146 }
147 if (!save_clip_value(which, CLIP_DETAILS_WIDTH, &sfile->hsize)) break;
148 if (!save_clip_value(which, CLIP_DETAILS_HEIGHT, &sfile->vsize)) break;
149 if (!save_clip_value(which, CLIP_DETAILS_INTERLACE, &sfile->interlace)) break;
150 if (!save_clip_value(which, CLIP_DETAILS_UNIQUE_ID, &sfile->unique_id)) break;
151 if (!save_clip_value(which, CLIP_DETAILS_ARATE, &sfile->arps)) break;
152 if (!save_clip_value(which, CLIP_DETAILS_PB_ARATE, &sfile->arate)) break;
153 if (!save_clip_value(which, CLIP_DETAILS_ACHANS, &sfile->achans)) break;
154 if (sfile->achans > 0) {
155 if (!save_clip_value(which, CLIP_DETAILS_ASIGNED, &asigned)) break;
156 if (!save_clip_value(which, CLIP_DETAILS_AENDIAN, &endian)) break;
157 }
158 if (!save_clip_value(which, CLIP_DETAILS_ASAMPS, &sfile->asampsize)) break;
159 if (!save_clip_value(which, CLIP_DETAILS_FRAMES, &sfile->frames)) break;
160 if (!save_clip_value(which, CLIP_DETAILS_GAMMA_TYPE, &sfile->gamma_type)) break;
161 if (!save_clip_value(which, CLIP_DETAILS_TITLE, sfile->title)) break;
162 if (!save_clip_value(which, CLIP_DETAILS_AUTHOR, sfile->author)) break;
163 if (!save_clip_value(which, CLIP_DETAILS_COMMENT, sfile->comment)) break;
164 if (!save_clip_value(which, CLIP_DETAILS_PB_FRAMENO, &sfile->frameno)) break;
165 if (!save_clip_value(which, CLIP_DETAILS_CLIPNAME, sfile->name)) break;
166 if (!save_clip_value(which, CLIP_DETAILS_FILENAME, sfile->file_name)) break;
167 if (!save_clip_value(which, CLIP_DETAILS_KEYWORDS, sfile->keywords)) break;
168 if (sfile->clip_type == CLIP_TYPE_FILE && sfile->ext_src) {
169 lives_decoder_t *dplug = (lives_decoder_t *)sfile->ext_src;
170 if (!save_clip_value(which, CLIP_DETAILS_DECODER_NAME, (void *)dplug->decoder->name)) break;
171 }
172 all_ok = TRUE;
173 } while (FALSE);
174
175 fclose(mainw->clip_header);
176
177 if (!all_ok) {
178 retval = do_write_failed_error_s_with_retry(lives_header_new, NULL);
179 } else {
180 char *lives_header;
181 if (which == mainw->ascrap_file)
182 lives_header = lives_build_filename(prefs->workdir, sfile->handle, LIVES_ACLIP_HEADER, NULL);
183 else
184 lives_header = lives_build_filename(prefs->workdir, sfile->handle, LIVES_CLIP_HEADER, NULL);
185 // TODO - check the sizes before and after
186 lives_cp(lives_header_new, lives_header);
187 lives_free(lives_header);
188 if (THREADVAR(com_failed) || THREADVAR(write_failed)) {
189 retval = do_write_failed_error_s_with_retry(lives_header_new, NULL);
190 } else lives_rm(lives_header_new);
191 }
192 }
193 } while (retval == LIVES_RESPONSE_RETRY);
194
197
198 lives_free(lives_header_new);
199 mainw->clip_header = NULL;
200
201 if (retval == LIVES_RESPONSE_CANCEL) return FALSE;
202
203 return TRUE;
204}
205
206
207boolean read_file_details(const char *file_name, boolean is_audio, boolean is_img) {
208 // get preliminary details
209
210 // is_audio set to TRUE prevents us from checking for images, and deleting the (existing) first frame
211 // therefore it is IMPORTANT to set it when loading new audio for an existing clip !
212
213 // is_img will force unpacking of img into frames and return the count
214
215 char *tmp, *com = lives_strdup_printf("%s get_details \"%s\" \"%s\" \"%s\" %d", prefs->backend_sync, cfile->handle,
216 (tmp = lives_filename_from_utf8(file_name, -1, NULL, NULL, NULL)),
218 is_audio ? 2 : is_img ? 4 : 0);
219 lives_free(tmp);
221 lives_free(com);
222 if (THREADVAR(com_failed)) {
223 THREADVAR(com_failed) = FALSE;
224 return FALSE;
225 }
226 return TRUE;
227}
228
229
230const char *get_deinterlace_string(void) {
231 if (mainw->open_deint) {
232 if (USE_MPV) return "--deinterlace=yes";
233 return "-vf pp=ci";
234 } else return "";
235}
236
237
238ulong deduce_file(const char *file_name, double start, int end) {
239 // this is a utility function to deduce whether we are dealing with a file,
240 // a selection, a backup, or a location
241 char short_file_name[PATH_MAX];
242 ulong uid;
244
245 if (lives_strrstr(file_name, "://") && strncmp(file_name, "dvd://", 6)) {
247 uid = open_file(file_name);
249 } else {
250 lives_snprintf(short_file_name, PATH_MAX, "%s", file_name);
251 if (!(strcmp(file_name + strlen(file_name) - 4, "."LIVES_FILE_EXT_BACKUP))) {
252 uid = restore_file(file_name);
253 } else {
254 uid = open_file_sel(file_name, start, end);
255 }
256 }
257 return uid;
258}
259
260
261ulong open_file(const char *file_name) {
262 // this function should be called to open a whole file
263 return open_file_sel(file_name, 0., 0);
264}
265
266
267static boolean rip_audio_cancelled(int old_file, weed_plant_t *mt_pb_start_event,
268 boolean mt_has_audio_file) {
269
270 if (mainw->cancelled == CANCEL_KEEP) {
271 // user clicked "enough"
273 return TRUE;
274 }
275
277
278 d_print("\n");
280 close_current_file(old_file);
281
282 if (mainw->multitrack) {
283 mainw->multitrack->pb_start_event = mt_pb_start_event;
284 mainw->multitrack->has_audio_file = mt_has_audio_file;
285 }
286
289 return FALSE;
290}
291
292
294 cfile->undo1_dbl = 0.;
295 cfile->undo2_dbl = CLIP_TOTAL_TIME(mainw->current_file) - cfile->laudio_time;
296 cfile->undo_arate = cfile->arate;
297 cfile->undo_signed_endian = cfile->signed_endian;
298 cfile->undo_achans = cfile->achans;
299 cfile->undo_asampsize = cfile->asampsize;
300 cfile->undo_arps = cfile->arps;
301 d_print(_("Auto padding with %.4f seconds of silence at start..."), cfile->undo2_dbl);
302 if (on_ins_silence_activate(NULL, NULL)) d_print_done();
303 else d_print("\n");
304}
305
306
307#define AUDIO_FRAMES_TO_READ 100
308
309ulong open_file_sel(const char *file_name, double start, int frames) {
310 LiVESResponseType response;
311 char msg[256], loc[PATH_MAX];
312 char *tmp = NULL;
313 char *isubfname = NULL;
314 char *fname = lives_strdup(file_name), *msgstr;
315 char *com, *what;
316
317 int withsound = 1;
318 int old_file = mainw->current_file;
319 int new_file = old_file;
320
321 int achans, arate, arps, asampsize;
322 int current_file;
323 int extra_frames = 0;
324 int probed_achans = 0;
325
326 boolean mt_has_audio_file = TRUE;
327
328 const lives_clip_data_t *cdata;
329
330 weed_plant_t *mt_pb_start_event = NULL;
331
332 if (!lives_file_test(fname, LIVES_FILE_TEST_EXISTS)) {
334 lives_free(fname);
335 return 0;
336 }
337
338 if (old_file == -1 || !CURRENT_CLIP_IS_VALID || !cfile->opening) {
339 new_file = mainw->first_free_file;
340
341 if (!get_new_handle(new_file, fname)) {
342 lives_free(fname);
343 return 0;
344 }
345 lives_free(fname);
346
349
350 if (frames == 0) {
351 com = lives_strdup_printf(_("Opening %s"), file_name);
352 } else {
353 com = lives_strdup_printf(_("Opening %s start time %.2f sec. frames %d"), file_name, start, frames);
354 }
355 d_print(""); // exhaust "switch" message
356
357 d_print(com);
358 lives_free(com);
359
360 if (!mainw->save_with_sound) {
361 d_print(_(" without sound"));
362 withsound = 0;
363 }
364
365 mainw->current_file = new_file;
366
368 read_file_details(file_name, FALSE, FALSE);
369 lives_rm(cfile->info_file);
370 if (THREADVAR(com_failed)) return 0;
371
372 if (*mainw->msg) add_file_info(cfile->handle, FALSE);
373
374 if (mainw->multitrack) {
375 // set up for opening preview
376 mt_pb_start_event = mainw->multitrack->pb_start_event;
377 mt_has_audio_file = mainw->multitrack->has_audio_file;
378 mainw->multitrack->pb_start_event = NULL;
379 mainw->multitrack->has_audio_file = TRUE;
380 }
381
383 if ((!strcmp(cfile->type, LIVES_IMAGE_TYPE_JPEG) || !strcmp(cfile->type, LIVES_IMAGE_TYPE_PNG))) {
384 read_file_details(file_name, FALSE, TRUE);
385 add_file_info(cfile->handle, FALSE);
386 if (cfile->frames == 0) {
388 close_current_file(old_file);
389 if (mainw->multitrack) {
390 mainw->multitrack->pb_start_event = mt_pb_start_event;
391 mainw->multitrack->has_audio_file = mt_has_audio_file;
392 }
395 return 0;
396 }
397 goto img_load;
398 }
399
401 // cd to clip directory - so decoder plugins can write temp files
402 char *ppath = lives_build_filename(prefs->workdir, cfile->handle, NULL);
403 char *cwd = lives_get_current_dir();
404
405 if (!mainw->decoders_loaded) {
408 }
409
410 lives_chdir(ppath, FALSE);
411 lives_free(ppath);
412
414
415 lives_chdir(cwd, FALSE);
416 lives_free(cwd);
417
418 if (cfile->ext_src) {
419 lives_decoder_t *dplug = (lives_decoder_t *)cfile->ext_src;
420 cfile->opening = TRUE;
421 cfile->clip_type = CLIP_TYPE_FILE;
422 cfile->img_type = IMG_TYPE_BEST; // override the pref
423
424 if (cdata->frame_width > 0) {
425 cfile->hsize = cdata->frame_width;
426 cfile->vsize = cdata->frame_height;
427 } else {
428 cfile->hsize = cdata->width;
429 cfile->vsize = cdata->height;
430 }
431
432 if (cfile->frames > cdata->nframes && cfile->frames != 123456789) {
433 extra_frames = cfile->frames - cdata->nframes;
434 }
435 cfile->frames = cdata->nframes;
436 if (!*cfile->author)
437 lives_snprintf(cfile->author, 1024, "%s", cdata->author);
438 if (!*cfile->title)
439 lives_snprintf(cfile->title, 1024, "%s", cdata->title);
440 if (!*cfile->comment)
441 lives_snprintf(cfile->comment, 1024, "%s", cdata->comment);
442
443 if (frames > 0 && cfile->frames > frames) {
444 cfile->frames = frames;
445 extra_frames = 0;
446 }
447
448 cfile->start = 1;
449 cfile->end = cfile->frames;
450
451 what = (_("creating the frame index for the clip"));
452
453 do {
454 response = LIVES_RESPONSE_OK;
455 create_frame_index(mainw->current_file, TRUE, cfile->fps * (start == 0 ? 0 : start - 1),
456 frames == 0 ? cfile->frames : frames);
457 if (!cfile->frame_index) {
458 response = do_memory_error_dialog(what, (frames == 0 ? cfile->frames : frames) * 4);
459 }
460 } while (response == LIVES_RESPONSE_RETRY);
461 lives_free(what);
462 if (response == LIVES_RESPONSE_CANCEL) {
463 return 0;
464 }
465 probed_achans = cfile->achans;
466 cfile->arate = cfile->arps = cdata->arate;
467 cfile->achans = cdata->achans;
468 cfile->asampsize = cdata->asamps;
469
470 cfile->signed_endian = get_signed_endian(cdata->asigned, capable->byte_order == LIVES_LITTLE_ENDIAN);
471
472 if (cfile->achans > 0 && (dplug->decoder->rip_audio) && withsound == 1) {
473 // call rip_audio() in the decoder plugin
474 // the plugin gets a chance to do any internal cleanup in rip_audio_cleanup()
475
476 int64_t stframe = cfile->fps * start + .5;
477 int64_t maxframe = (stframe + (frames == 0)) ? cfile->frames : frames;
478 int64_t nframes = AUDIO_FRAMES_TO_READ;
480
481 msgstr = lives_strdup_printf(_("Opening audio for %s"), file_name);
482
483 if (!LIVES_IS_PLAYING) resize(1);
484
486
487 if (!LIVES_IS_PLAYING) {
489 do_threaded_dialog(msgstr, TRUE);
491 }
492
493 do {
494 if (stframe + nframes > maxframe) nframes = maxframe - stframe;
495 if (nframes <= 0) break;
496 (dplug->decoder->rip_audio)(cdata, afile, stframe, nframes, NULL);
498 stframe += nframes;
499 } while (mainw->cancelled == CANCEL_NONE);
500
501 if (dplug->decoder->rip_audio_cleanup) {
502 (dplug->decoder->rip_audio_cleanup)(cdata);
503 }
504
505 if (mainw->cancelled != CANCEL_NONE) {
506 if (!rip_audio_cancelled(old_file, mt_pb_start_event, mt_has_audio_file)) {
507 lives_free(afile);
508 return 0;
509 }
510 }
512 lives_free(msgstr);
513 lives_free(afile);
514 } else {
515 cfile->arate = 0.;
516 cfile->achans = cfile->asampsize = 0;
517 }
518
519 cfile->fps = cfile->pb_fps = cdata->fps;
520 d_print("\n");
521
522 if (cfile->achans == 0 && probed_achans > 0 && withsound == 1) {
523 // plugin returned no audio, try with mplayer / mpv
524 if (probed_achans > MAX_ACHANS) {
525 probed_achans = MAX_ACHANS;
526 d_print(_("Forcing audio channels to %d\n"), MAX_ACHANS);
527 }
528
529 if (!mainw->file_open_params) {
530#if 1
531 mainw->file_open_params = lives_strdup("alang eng");
532#else
533 mainw->file_open_params = lives_strdup("");
534#endif
535 }
536 com = lives_strdup_printf("%s open \"%s\" \"%s\" %d %s:%s %.2f %d %d \"%s\"", prefs->backend, cfile->handle,
537 (tmp = lives_filename_from_utf8(file_name, -1, NULL, NULL, NULL)), -1,
538 prefs->image_ext, get_image_ext_for_type(IMG_TYPE_BEST), start, frames, probed_achans,
540
541 lives_free(tmp);
542
543 lives_rm(cfile->info_file);
544 lives_system(com, FALSE);
545 lives_free(com);
546
547 // if we have a quick-opening file, display the first and last frames now
548 // for some codecs this can be helpful since we can locate the last frame while audio is loading
549 if (cfile->clip_type == CLIP_TYPE_FILE && !LIVES_IS_PLAYING) resize(1);
550
551 mainw->effects_paused = FALSE; // set to TRUE if user clicks "Enough"
552
553 msgstr = lives_strdup_printf(_("Opening audio"), file_name);
554 if (!do_progress_dialog(TRUE, TRUE, msgstr)) {
555 // error or user cancelled or switched to another clip
556 lives_free(msgstr);
557
558 cfile->opening_frames = -1;
559
560 if (mainw->multitrack) {
561 mainw->multitrack->pb_start_event = mt_pb_start_event;
562 mainw->multitrack->has_audio_file = mt_has_audio_file;
563 }
564
568 return 0;
569 }
570
571 // cancelled
572 if (mainw->cancelled != CANCEL_ERROR) {
574 }
575
577 close_current_file(old_file);
579 if (mainw->error) {
581 mainw->error = 0;
583 }
584 sensitize();
585 return 0;
586 }
587 lives_free(msgstr);
588
589 cfile->opening = FALSE;
590
592 if (mainw->error == 0) add_file_info(cfile->handle, TRUE);
593 mainw->error = 0;
595
596 if (prefs->auto_trim_audio) {
597 if ((cdata->sync_hint & SYNC_HINT_VIDEO_PAD_START) && cdata->video_start_time <= 1.) {
598 // pad with blank frames at start
599 int st_extra_frames = cdata->video_start_time * cfile->fps;
600 insert_blank_frames(mainw->current_file, st_extra_frames, 0, WEED_PALETTE_RGB24);
601 cfile->video_time += st_extra_frames / cfile->fps;
602 extra_frames -= st_extra_frames;
603 showclipimgs();
604 if (!mainw->multitrack)
606 }
607
608 if ((cfile->frames + extra_frames) / cfile->fps > cfile->laudio_time) {
609 extra_frames = (cfile->laudio_time - (double)cfile->frames / cfile->fps) * cfile->fps;
610 }
611
612 if (extra_frames > 0 || ((cdata->sync_hint & SYNC_HINT_VIDEO_PAD_END)
613 && (double)cfile->frames / cfile->fps < cfile->laudio_time)) {
614 // pad with blank frames at end
615 if (cdata->sync_hint & SYNC_HINT_VIDEO_PAD_END) {
616 int xextra_frames = (cfile->laudio_time - (double)cfile->frames / cfile->fps) * cfile->fps;
617 if (xextra_frames > extra_frames) extra_frames = xextra_frames;
618 }
619 insert_blank_frames(mainw->current_file, extra_frames, cfile->frames, WEED_PALETTE_RGB24);
620 cfile->video_time += extra_frames / cfile->fps;
621 load_end_image(cfile->end);
622 }
623 if (cfile->laudio_time > cfile->video_time + AV_TRACK_MIN_DIFF && cfile->frames > 0) {
625 cfile->undo1_dbl = 0.;
626 cfile->undo2_dbl = cfile->laudio_time - cfile->video_time;
627 d_print(_("Auto trimming %.4f seconds of audio at start..."), cfile->undo2_dbl);
628 if (on_del_audio_activate(NULL, NULL)) d_print_done();
629 else d_print("\n");
630 cfile->changed = FALSE;
631 }
632 }
633 if (cfile->laudio_time > cfile->video_time + AV_TRACK_MIN_DIFF && cfile->frames > 0) {
634 if (cdata->sync_hint & SYNC_HINT_AUDIO_TRIM_END) {
635 cfile->end = cfile->frames;
636 d_print(_("Auto trimming %.4f seconds of audio at end..."), cfile->laudio_time - cfile->video_time);
637 if (on_trim_audio_activate(NULL, LIVES_INT_TO_POINTER(0))) d_print_done();
638 else d_print("\n");
639 cfile->changed = FALSE;
640 }
641 }
642 if (!mainw->effects_paused && cfile->afilesize > 0 && cfile->achans > 0
646 cfile->changed = FALSE;
647 }
648 if (cdata->sync_hint & SYNC_HINT_AUDIO_PAD_END) {
649 cfile->undo1_dbl = cfile->laudio_time;
650 cfile->undo2_dbl = CLIP_TOTAL_TIME(mainw->current_file) - cfile->laudio_time;
651 cfile->undo_arate = cfile->arate;
652 cfile->undo_signed_endian = cfile->signed_endian;
653 cfile->undo_achans = cfile->achans;
654 cfile->undo_asampsize = cfile->asampsize;
655 cfile->undo_arps = cfile->arps;
656 d_print(_("Auto padding with %.4f seconds of silence at end..."), cfile->undo2_dbl);
657 if (on_ins_silence_activate(NULL, NULL)) d_print_done();
658 else d_print("\n");
659 cfile->changed = FALSE;
660 // *INDENT-OFF*
661 }}}}
662 // *INDENT-ON*
663
664 get_mime_type(cfile->type, 40, cdata);
666 }
667 }
668
669 if (cfile->ext_src) {
670 if (mainw->open_deint) {
671 // override what the plugin says
672 cfile->deinterlace = TRUE;
673 cfile->interlace = LIVES_INTERLACE_TOP_FIRST; // guessing
675 if (THREADVAR(com_failed) || THREADVAR(write_failed)) do_header_write_error(mainw->current_file);
676 }
677 } else {
678 // be careful, here we switch from mainw->opening_loc to cfile->opening_loc
679 if (mainw->opening_loc) {
680 cfile->opening_loc = TRUE;
682 } else {
683 if (cfile->f_size > prefs->warn_file_size * 1000000. && mainw->is_ready && frames == 0) {
684 char *fsize_ds = lives_format_storage_space_string((uint64_t)cfile->f_size);
685 char *warn = lives_strdup_printf(
686 _("\nLiVES cannot Instant Open this file, it may take some time to load.\n"
687 "Are you sure you wish to continue ?"),
688 fsize_ds);
689 lives_free(fsize_ds);
691 lives_free(warn);
692 close_current_file(old_file);
693 if (mainw->multitrack) {
694 mainw->multitrack->pb_start_event = mt_pb_start_event;
695 mainw->multitrack->has_audio_file = mt_has_audio_file;
696 }
698 return 0;
699 }
700 lives_free(warn);
701 d_print(_(" - please be patient."));
702
703 }
704 d_print("\n");
705#if defined DEBUG
706 g_print("open_file: dpd in\n");
707#endif
708 }
709 }
710
711 // set undo_start and undo_end for preview
712 cfile->undo_start = 1;
713 cfile->undo_end = cfile->frames;
714
715 if (cfile->achans > 0) {
716 cfile->opening_audio = TRUE;
717 }
718
719 // these will get reset as we have no audio file yet, so preserve them
720 achans = cfile->achans;
721 arate = cfile->arate;
722 arps = cfile->arps;
723 asampsize = cfile->asampsize;
724 cfile->old_frames = cfile->frames;
725 cfile->frames = 0;
726
727 // we need this FALSE here, otherwise we will switch straight back here...
728 cfile->opening = FALSE;
729
730 // force a resize
731 current_file = mainw->current_file;
732
733 cfile->opening = TRUE;
734 cfile->achans = achans;
735 cfile->arate = arate;
736 cfile->arps = arps;
737 cfile->asampsize = asampsize;
738 cfile->frames = cfile->old_frames;
739
740 if (cfile->frames <= 0) {
741 cfile->undo_end = cfile->frames = 123456789;
742 }
743 if (cfile->hsize * cfile->vsize == 0) {
744 cfile->frames = 0;
745 }
746
748
750 set_main_title(cfile->file_name, 0);
751
753
754 if (!cfile->ext_src) {
755 if (!mainw->file_open_params) mainw->file_open_params = lives_strdup("");
756
757 tmp = lives_strconcat(mainw->file_open_params, get_deinterlace_string(), NULL);
759 mainw->file_open_params = tmp;
760
761 if (cfile->achans > MAX_ACHANS) {
762 cfile->achans = MAX_ACHANS;
763 d_print(_("Forcing audio channels to %d\n"), MAX_ACHANS);
764 }
765
766 com = lives_strdup_printf("%s open \"%s\" \"%s\" %d %s:%s %.2f %d %d \"%s\"", prefs->backend, cfile->handle,
767 (tmp = lives_filename_from_utf8(file_name, -1, NULL, NULL, NULL)), withsound,
768 prefs->image_ext, get_image_ext_for_type(IMG_TYPE_BEST), start, frames, cfile->achans,
770
771 lives_rm(cfile->info_file);
772 lives_system(com, FALSE);
773 lives_free(com);
774 lives_free(tmp);
775
776 if (mainw->toy_type == LIVES_TOY_TV) {
777 // for LiVES TV we do an auto-preview
778 mainw->play_start = cfile->start = cfile->undo_start;
779 mainw->play_end = cfile->end = cfile->undo_end;
780 mainw->preview = TRUE;
781 do {
782 desensitize();
784 on_playsel_activate(NULL, NULL);
785 } while (mainw->cancelled == CANCEL_KEEP_LOOPING);
787 on_toy_activate(NULL, LIVES_INT_TO_POINTER(LIVES_TOY_NONE));
791 return 0;
792 }
793 }
794
795 // loading:
796
797 // 'entry point' when we switch back
798
799 // spin until loading is complete
800 // afterwards, mainw->msg will contain file details
801 cfile->progress_start = cfile->progress_end = 0;
802
803 // (also check for cancel)
804 msgstr = lives_strdup_printf(_("Opening %s"), file_name);
805
806 if (!cfile->ext_src && mainw->toy_type != LIVES_TOY_TV) {
809 if (!do_progress_dialog(TRUE, TRUE, msgstr)) {
810 // user cancelled or switched to another clip
812 mainw->disk_mon = 0;
813
814 lives_free(msgstr);
816
820 return 0;
821 }
822
823 // cancelled
824 // clean up our temp files
825 if (IS_VALID_CLIP(current_file)) mainw->current_file = current_file;
828 close_current_file(old_file);
829 if (mainw->multitrack) {
830 mainw->multitrack->pb_start_event = mt_pb_start_event;
831 mainw->multitrack->has_audio_file = mt_has_audio_file;
832 }
834
835 // mainw->error is TRUE if we could not open the file
836 if (mainw->error) {
839 }
840 if (!mainw->multitrack)
842 showclipimgs();
843 return 0;
844 }
846 mainw->disk_mon = 0;
847 }
848 lives_free(msgstr);
849 }
850
851 if (cfile->ext_src && cfile->achans > 0) {
854 rename(afile, ofile);
855 lives_free(afile);
856 lives_free(ofile);
857 }
858
859 cfile->opening = cfile->opening_audio = cfile->opening_only_audio = FALSE;
860 cfile->opening_frames = -1;
862
863#if defined DEBUG
864 g_print("Out of dpd\n");
865#endif
866
867 if (mainw->multitrack) {
868 mainw->multitrack->pb_start_event = mt_pb_start_event;
869 mainw->multitrack->has_audio_file = mt_has_audio_file;
870 }
871
872 // mainw->error is TRUE if we could not open the file
873 if (mainw->error) {
876 close_current_file(old_file);
879 return 0;
880 }
881
882 if (cfile->opening_loc) {
883 cfile->changed = TRUE;
884 cfile->opening_loc = FALSE;
885 } else {
886 if (prefs->autoload_subs) {
887 char filename[512];
888 char *subfname;
890
891 lives_snprintf(filename, 512, "%s", file_name);
892 get_filename(filename, FALSE); // strip extension
893 isubfname = lives_strdup_printf("%s.%s", filename, LIVES_FILE_EXT_SRT);
894 if (lives_file_test(isubfname, LIVES_FILE_TEST_EXISTS)) {
895 subfname = lives_build_filename(prefs->workdir, cfile->handle, SUBS_FILENAME "." LIVES_FILE_EXT_SRT, NULL);
896 subtype = SUBTITLE_TYPE_SRT;
897 } else {
898 lives_free(isubfname);
899 isubfname = lives_strdup_printf("%s.%s", filename, LIVES_FILE_EXT_SUB);
900 if (lives_file_test(isubfname, LIVES_FILE_TEST_EXISTS)) {
901 subfname = lives_build_filename(prefs->workdir, cfile->handle, SUBS_FILENAME "." LIVES_FILE_EXT_SUB, NULL);
902 subtype = SUBTITLE_TYPE_SUB;
903 }
904 }
905 if (subtype != SUBTITLE_TYPE_NONE) {
906 lives_cp(isubfname, subfname);
907 if (!THREADVAR(com_failed))
908 subtitles_init(cfile, subfname, subtype);
909 lives_free(subfname);
910 } else {
911 lives_freep((void **)&isubfname);
912 }
913 }
914 }
915
916 // now file should be loaded...get full details
917 if (!cfile->ext_src) add_file_info(cfile->handle, FALSE);
918 cfile->is_loaded = TRUE;
919
920 if (cfile->frames <= 0) {
921 if (cfile->afilesize == 0l) {
922 // we got neither video nor audio...
923 lives_snprintf(msg, 256, "%s", _
924 ("\n\nLiVES was unable to extract either video or audio.\n"
925 "Please check the terminal window for more details.\n"));
926
928 lives_strappend(msg, 256, _("\n\nYou may need to install mplayer, mplayer2 or mpv to open this file.\n"));
929 } else {
930 if (capable->has_mplayer) {
932 } else if (capable->has_mplayer2) {
934 } else if (capable->has_mpv) {
936 }
937
938 if (strcmp(prefs->video_open_command, loc) && strncmp(prefs->video_open_command + 1, loc, strlen(loc))) {
939 lives_strappend(msg, 256, _("\n\nPlease check the setting of Video Open Command in\nTools|Preferences|Decoding\n"));
940 }
941 }
943 do_error_dialog(msg);
946 close_current_file(old_file);
947 if (mainw->multitrack) {
948 mainw->multitrack->pb_start_event = mt_pb_start_event;
949 mainw->multitrack->has_audio_file = mt_has_audio_file;
950 }
953 return 0;
954 }
955 cfile->frames = 0;
956 }
957
958 if (!cfile->ext_src) {
959 extra_frames = cfile->frames;
960 add_file_info(cfile->handle, FALSE);
961 extra_frames -= cfile->frames;
962 cfile->end = cfile->frames;
963 cfile->video_time = cfile->frames / cfile->fps;
964 } else {
965 add_file_info(NULL, FALSE);
966 if (cfile->f_size == 0) {
967 off_t fsize = sget_file_size((char *)file_name);
968 if (fsize < 0) fsize = 0;
969 cfile->f_size = (size_t)fsize;
970 }
971 }
972
973 if (!cfile->ext_src) {
976 if (cfile->laudio_time > cfile->video_time && cfile->frames > 0) {
977 if (!prefs->keep_all_audio || start != 0. || extra_frames <= 0) {
978 d_print(_("Auto trimming %.2f seconds of audio at end..."), cfile->laudio_time - cfile->video_time);
979 if (on_trim_audio_activate(NULL, LIVES_INT_TO_POINTER(0))) d_print_done();
980 else d_print("\n");
981 cfile->changed = FALSE;
982 } else {
984 if (prefs->keep_all_audio && (cfile->laudio_time - cfile->video_time) * cfile->fps > extra_frames)
985 extra_frames = (cfile->laudio_time - cfile->video_time) * cfile->fps;
986 insert_blank_frames(mainw->current_file, extra_frames, cfile->frames, WEED_PALETTE_RGB24);
987 cfile->video_time += extra_frames / cfile->fps;
988 cfile->end = cfile->frames;
989 showclipimgs();
990 if (!mainw->multitrack)
992 }
993 }
994 if (cfile->laudio_time < cfile->video_time && cfile->achans > 0) {
995 cfile->undo1_dbl = cfile->laudio_time;
996 cfile->undo2_dbl = CLIP_TOTAL_TIME(mainw->current_file) - cfile->laudio_time;
997 cfile->undo_arate = cfile->arate;
998 cfile->undo_signed_endian = cfile->signed_endian;
999 cfile->undo_achans = cfile->achans;
1000 cfile->undo_asampsize = cfile->asampsize;
1001 cfile->undo_arps = cfile->arps;
1002 d_print(_("Auto padding with %.2f seconds of silence at end..."), cfile->undo2_dbl);
1003 if (on_ins_silence_activate(NULL, NULL)) d_print_done();
1004 else d_print("\n");
1005 cfile->changed = FALSE;
1006 }
1007 }
1008 }
1009
1010 if (isubfname) {
1011 d_print(_("Loaded subtitle file: %s\n"), isubfname);
1012 lives_free(isubfname);
1013 }
1014
1015img_load:
1016 current_file = mainw->current_file;
1017
1018#ifdef GET_MD5
1019 g_print("md5sum is %s\n", get_md5sum(file_name));
1020#endif
1021
1022 // TODO - prompt for copy to origs (unless it is already there)
1023
1025
1027 add_to_recent(file_name, start, frames, mainw->file_open_params);
1028 }
1030
1031 if (!strcmp(cfile->type, "Frames") || !strcmp(cfile->type, LIVES_IMAGE_TYPE_JPEG) ||
1032 !strcmp(cfile->type, LIVES_IMAGE_TYPE_PNG) ||
1033 !strcmp(cfile->type, "Audio")) {
1034 cfile->is_untitled = TRUE;
1035 }
1036
1037 if ((!strcmp(cfile->type, LIVES_IMAGE_TYPE_JPEG) || !strcmp(cfile->type, LIVES_IMAGE_TYPE_PNG))) {
1038 if (mainw->img_concat_clip == -1) {
1039 cfile->img_type = lives_image_type_to_img_type(cfile->type);
1042 set_main_title(cfile->file_name, 0);
1043 cfile->opening = cfile->opening_audio = cfile->opening_only_audio = FALSE;
1044 cfile->opening_frames = -1;
1046 cfile->is_loaded = TRUE;
1047 } else if (prefs->concat_images) {
1048 // insert this image into our image clip, close this file
1049
1050 com = lives_strdup_printf("%s insert \"%s\" \"%s\" %d 1 1 \"%s\" 0 %d %d %d", prefs->backend,
1056
1058
1059 lives_rm(cfile->info_file);
1060
1062 mainw->error = FALSE;
1063 lives_system(com, FALSE);
1064 lives_free(com);
1065
1066 do_auto_dialog(_("Adding image..."), 2);
1067
1068 if (current_file != mainw->img_concat_clip) {
1069 mainw->current_file = current_file;
1071 }
1072
1073 if (mainw->cancelled || mainw->error) {
1074 goto load_done;
1075 }
1076
1077 cfile->frames++;
1078 cfile->end++;
1079
1081 lives_spin_button_set_range(LIVES_SPIN_BUTTON(mainw->spinbutton_end), cfile->frames == 0 ? 0 : 1, cfile->frames);
1082 lives_spin_button_set_value(LIVES_SPIN_BUTTON(mainw->spinbutton_end), cfile->end);
1084
1086 lives_spin_button_set_range(LIVES_SPIN_BUTTON(mainw->spinbutton_start), cfile->frames == 0 ? 0 : 1, cfile->frames);
1087 lives_spin_button_set_value(LIVES_SPIN_BUTTON(mainw->spinbutton_start), cfile->start);
1090 return 0;
1091 }
1092 }
1093
1094 // set new style file details
1095 if (!save_clip_values(current_file)) {
1096 close_current_file(old_file);
1097 return 0;
1098 }
1099
1101
1102load_done:
1103 if (!mainw->multitrack) {
1104 // update widgets
1105 switch_to_file((mainw->current_file = 0), current_file);
1107 } else {
1108 lives_mt *multi = mainw->multitrack;
1109 mainw->multitrack = NULL; // allow getting of afilesize
1110 current_file = mainw->current_file;
1111 mainw->current_file = -1; // stop framebars from being drawn
1112 reget_afilesize(current_file);
1113 mainw->current_file = current_file;
1114 mainw->multitrack = multi;
1116 if (!mainw->is_generating) mainw->current_file = mainw->multitrack->render_file;
1117 mt_init_clips(mainw->multitrack, current_file, TRUE);
1120 }
1123 return cfile->unique_id;
1124}
1125
1126
1127static void save_subs_to_file(lives_clip_t *sfile, char *fname) {
1128 char *ext;
1129 lives_subtitle_type_t otype, itype;
1130
1131 if (!sfile->subt) return;
1132
1133 itype = sfile->subt->type;
1134
1135 ext = get_extension(fname);
1136
1137 if (!strcmp(ext, LIVES_FILE_EXT_SUB)) otype = SUBTITLE_TYPE_SUB;
1138 else if (!strcmp(ext, LIVES_FILE_EXT_SRT)) otype = SUBTITLE_TYPE_SRT;
1139 else otype = itype;
1140
1141 lives_free(ext);
1142
1143 // TODO - use sfile->subt->save_fn
1144 switch (otype) {
1145 case SUBTITLE_TYPE_SUB:
1146 save_sub_subtitles(sfile, (double)(sfile->start - 1) / sfile->fps, (double)sfile->end / sfile->fps,
1147 (double)(sfile->start - 1) / sfile->fps, fname);
1148 break;
1149
1150 case SUBTITLE_TYPE_SRT:
1151 save_srt_subtitles(sfile, (double)(sfile->start - 1) / sfile->fps, (double)sfile->end / sfile->fps,
1152 (double)(sfile->start - 1) / sfile->fps, fname);
1153 break;
1154
1155 default:
1156 return;
1157 }
1158
1159 d_print(_("Subtitles were saved as %s\n"), mainw->subt_save_file);
1160}
1161
1162
1163boolean get_handle_from_info_file(int index) {
1164 // called from get_new_handle to get the 'real' file handle
1165 // because until we know the handle we can't use the normal info file yet
1166 char *com = lives_strdup_printf("%s new", prefs->backend_sync);
1167
1169 lives_free(com);
1170
1171 if (!strncmp(mainw->msg, "error|", 6)) {
1173 return FALSE;
1174 }
1175
1176 if (!mainw->files[index]) {
1177 mainw->files[index] = (lives_clip_t *)(lives_calloc(1, sizeof(lives_clip_t)));
1178 mainw->files[index]->clip_type = CLIP_TYPE_DISK; // the default
1179 }
1180 lives_snprintf(mainw->files[index]->handle, 256, "%s", mainw->msg);
1181
1182 return TRUE;
1183}
1184
1185
1186void save_frame(LiVESMenuItem * menuitem, livespointer user_data) {
1187 int frame;
1188 // save a single frame from a clip
1189 char *filt[2];
1190 char *ttl;
1191 char *filename, *defname;
1192
1193 filt[0] = lives_strdup_printf("*.%s", get_image_ext_for_type(cfile->img_type));
1194 filt[1] = NULL;
1195
1196 frame = LIVES_POINTER_TO_INT(user_data);
1197
1198 if (frame > 0)
1199 ttl = lives_strdup_printf(_("Save Frame %d"), frame);
1200
1201 else
1202 ttl = (_("Save Frame"));
1203
1204 defname = lives_strdup_printf("frame%08d.%s", frame, get_image_ext_for_type(cfile->img_type));
1205
1206 filename = choose_file(*mainw->image_dir ? mainw->image_dir : NULL, defname,
1207 filt, LIVES_FILE_CHOOSER_ACTION_SAVE, ttl, NULL);
1208
1209 lives_free(defname); lives_free(filt[0]); lives_free(ttl);
1210
1211 if (!filename) return;
1212 if (!*filename) {
1213 lives_free(filename);
1214 return;
1215 }
1216
1217 if (!save_frame_inner(mainw->current_file, frame, filename, -1, -1, FALSE)) {
1218 lives_free(filename);
1219 return;
1220 }
1221
1222 lives_snprintf(mainw->image_dir, PATH_MAX, "%s", filename);
1223 lives_free(filename);
1225 if (prefs->save_directories) {
1227 }
1228}
1229
1230
1231static void save_log_file(const char *prefix) {
1232 int logfd;
1233
1234 // save the logfile in workdir
1235#ifndef IS_MINGW
1236 char *logfile = lives_strdup_printf("%s/%s_%d_%d.txt", prefs->workdir, prefix, lives_getuid(), lives_getgid());
1237 if ((logfd = creat(logfile, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) != -1) {
1238#else
1239 char *logfile = lives_strdup_printf("%s\\%s_%d_%d.txt", prefs->workdir, prefix, lives_getuid(), lives_getgid());
1240 if ((logfd = creat(logfile, S_IRUSR | S_IWUSR)) != -1) {
1241#endif
1243 lives_write(logfd, btext, strlen(btext), TRUE); // not really important if it fails
1244 lives_free(btext);
1245 close(logfd);
1246 }
1247 lives_free(logfile);
1248}
1249
1250
1251LIVES_GLOBAL_INLINE void set_default_comment(lives_clip_t *sfile, const char *extrat) {
1252 if (!*sfile->comment)
1253 lives_snprintf(sfile->comment, 1024, "Created with LiVES version %s.\nSee: %s\n%s",
1254 LiVES_VERSION, LIVES_WEBSITE, extrat);
1255 if (!*sfile->author && *prefs->def_author)
1256 lives_snprintf(sfile->author, 1024, "%s", prefs->def_author);
1257}
1258
1259
1260void save_file(int clip, int start, int end, const char *filename) {
1261 // save clip from frame start to frame end
1262 lives_clip_t *sfile = mainw->files[clip], *nfile = NULL;
1263 double aud_start = 0., aud_end = 0.;
1264
1265 char *n_file_name = NULL;
1266 char *fps_string;
1267 char *extra_params = NULL;
1268 char *redir = lives_strdup("1>&2 2>"LIVES_DEVNULL);
1269 char *new_stderr_name = NULL;
1270 char *mesg, *bit, *tmp;
1271 char *com, *msg;
1272 char *full_file_name = NULL;
1273 char *enc_exec_name = NULL;
1274 char *clipdir;
1275 char *cwd;
1276
1277 boolean recheck_name = FALSE;
1278
1279 int new_stderr = -1;
1280 int retval;
1281 int startframe = 1;
1282 int current_file = mainw->current_file;
1283 int asigned = !(sfile->signed_endian & AFORM_UNSIGNED); // 1 is signed (in backend)
1284 int aendian = (sfile->signed_endian & AFORM_BIG_ENDIAN); // 2 is bigend
1285 int arate;
1286 int new_file = -1;
1287
1288#ifdef GUI_GTK
1289 GError *gerr = NULL;
1290#endif
1291
1292 struct stat filestat;
1293
1294 off_t fsize;
1295
1296 LiVESWidget *hbox;
1297 frames_t res;
1298
1299 boolean safe_symlinks = prefs->safe_symlinks;
1300 boolean not_cancelled = FALSE;
1301 boolean output_exists = FALSE;
1302 boolean save_all = FALSE;
1303 boolean debug_mode = FALSE;
1304
1306
1309
1310 if (start == 1 && end == sfile->frames) save_all = TRUE;
1311
1312 // new handling for save selection:
1313 // symlink images 1 - n to the encoded frames
1314 // symlinks are now created in /tmp (for dynebolic)
1315 // then encode the symlinked frames
1316
1317 if (!filename) {
1318 // prompt for encoder type/output format
1319 if (prefs->show_rdet) {
1320 int response;
1321 rdet = create_render_details(1); // WARNING !! - rdet is global in events.h
1322
1323 while (1) {
1324 response = lives_dialog_run(LIVES_DIALOG(rdet->dialog));
1327
1328 if (response == LIVES_RESPONSE_CANCEL) {
1331 lives_freep((void **)&rdet);
1332 lives_freep((void **)&resaudw);
1333 return;
1334 }
1335
1337 // initialise new plugin
1338
1339 if (enc_exec_name) lives_free(enc_exec_name);
1340 enc_exec_name = lives_build_filename(prefs->lib_dir, PLUGIN_EXEC_DIR, PLUGIN_ENCODERS, prefs->encoder.name, NULL);
1341
1342 com = lives_strdup_printf("\"%s\" init", enc_exec_name);
1344 lives_free(com);
1345
1346 if (strcmp(mainw->msg, "initialised\n")) {
1347 if (*mainw->msg) {
1348 msg = lives_strdup_printf(_("\n\nThe '%s' plugin reports:\n%s\n"), prefs->encoder.name, mainw->msg);
1349 } else {
1351 (_("\n\nUnable to find the 'init' method in the %s plugin.\n"
1352 "The plugin may be broken or not installed correctly."), prefs->encoder.name);
1353 }
1354 do_error_dialog(msg);
1355 lives_free(msg);
1356 } else break;
1357 }
1358 if (rdet->debug && lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(rdet->debug)))
1359 debug_mode = TRUE;
1360 }
1361 }
1362
1363 if (!enc_exec_name)
1364 enc_exec_name = lives_build_filename(prefs->lib_dir, PLUGIN_EXEC_DIR, PLUGIN_ENCODERS, prefs->encoder.name, NULL);
1365
1366 // get file extension
1368
1369 hbox = lives_hbox_new(FALSE, 0);
1370 mainw->fx1_bool = TRUE;
1371 add_suffix_check(LIVES_BOX(hbox), prefs->encoder.of_def_ext);
1373
1374 if (palette->style & STYLE_1) {
1375 lives_widget_set_fg_color(hbox, LIVES_WIDGET_STATE_NORMAL, &palette->normal_fore);
1376 lives_widget_set_bg_color(hbox, LIVES_WIDGET_STATE_NORMAL, &palette->normal_back);
1377 }
1378
1379 if (!filename) {
1380 char *ttl = (_("Save Clip"));
1381 do {
1382 lives_freep((void **)&n_file_name);
1383 n_file_name = choose_file_bg(mainw->vid_save_dir, NULL, NULL, LIVES_FILE_CHOOSER_ACTION_SAVE, ttl, hbox);
1384 if (mainw->fc_buttonresponse == LIVES_RESPONSE_CANCEL) return;
1385 } while (!*n_file_name);
1386 lives_snprintf(mainw->vid_save_dir, PATH_MAX, "%s", n_file_name);
1388 if (prefs->save_directories) {
1390 }
1391 lives_free(ttl);
1392 } else n_file_name = lives_strdup(filename);
1393
1394 //append default extension (if necessary)
1395 if (!*prefs->encoder.of_def_ext) {
1396 // encoder adds its own extension
1397 get_filename(n_file_name, FALSE);
1398 } else {
1399 if (mainw->fx1_bool && (strlen(n_file_name) <= strlen(prefs->encoder.of_def_ext) ||
1400 strncmp(n_file_name + strlen(n_file_name) - strlen(prefs->encoder.of_def_ext) - 1, ".", 1) ||
1401 strcmp(n_file_name + strlen(n_file_name) - strlen(prefs->encoder.of_def_ext),
1403 full_file_name = lives_strconcat(n_file_name, ".", prefs->encoder.of_def_ext, NULL);
1404 recheck_name = TRUE;
1405 }
1406 }
1407
1408 if (!full_file_name) {
1409 full_file_name = lives_strdup(n_file_name);
1410 }
1411
1412 if (!filename && recheck_name) {
1413 if (!check_file(full_file_name, strcmp(full_file_name, n_file_name))) {
1414 lives_free(full_file_name);
1415 lives_free(n_file_name);
1416 if (rdet) {
1419 lives_freep((void **)&rdet);
1420 lives_freep((void **)&resaudw);
1421 }
1422 return;
1423 }
1424 sfile->orig_file_name = FALSE;
1425 }
1426
1427 if (!*sfile->comment) set_default_comment(sfile, NULL);
1428
1429 if (!do_comments_dialog(clip, full_file_name)) {
1430 lives_free(full_file_name);
1431 if (rdet) {
1434 lives_freep((void **)&rdet);
1435 lives_freep((void **)&resaudw);
1436 }
1437 lives_freep((void **)&mainw->subt_save_file);
1438 return;
1439 }
1440
1441 if (rdet) {
1443 lives_freep((void **)&rdet->encoder_name);
1444 lives_freep((void **)&rdet);
1445 lives_freep((void **)&resaudw);
1446 }
1447
1448 if (sfile->arate * sfile->achans != 0) {
1449 aud_start = calc_time_from_frame(clip, start) * sfile->arps / sfile->arate;
1450 aud_end = calc_time_from_frame(clip, end + 1) * sfile->arps / sfile->arate;
1451 }
1452
1453 // get extra params for encoder
1454
1455 if (!sfile->ratio_fps) {
1456 fps_string = lives_strdup_printf("%.3f", sfile->fps);
1457 } else {
1458 fps_string = lives_strdup_printf("%.8f", sfile->fps);
1459 }
1460
1461 arate = sfile->arate;
1462
1464 arate = 0;
1465 }
1466
1469 char buff[65536];
1470
1471 com = lives_strdup_printf("\"%s\" get_rfx %s %d %d %d", enc_exec_name, prefs->encoder.of_name,
1472 prefs->encoder.audio_codec, cfile->hsize, cfile->vsize);
1473 if (debug_mode) {
1474 fprintf(stderr, "Running command: %s\n", com);
1475 }
1476 lives_popen(com, TRUE, buff, 65536);
1477 lives_free(com);
1478
1479 if (!THREADVAR(com_failed)) {
1480 extra_params = plugin_run_param_window(buff, NULL, NULL);
1481 }
1482 if (!extra_params) {
1483 lives_free(fps_string);
1484 if (!mainw->multitrack) {
1485 switch_to_file(mainw->current_file, current_file);
1486 }
1487 lives_freep((void **)&mainw->subt_save_file);
1488 return;
1489 }
1490 }
1491
1492 if (!save_all && !safe_symlinks) {
1493 // we are saving a selection - make symlinks from a temporary clip
1494
1495 if ((new_file = mainw->first_free_file) == ALL_USED) {
1497 lives_freep((void **)&mainw->subt_save_file);
1498 return;
1499 }
1500
1501 // create new clip
1502 if (!get_new_handle(new_file, (_("selection")))) {
1503 lives_freep((void **)&mainw->subt_save_file);
1504 return;
1505 }
1506
1507 if (sfile->clip_type == CLIP_TYPE_FILE) {
1509 cfile->progress_start = 1;
1510 cfile->progress_end = count_virtual_frames(sfile->frame_index, start, end);
1511 do_threaded_dialog(_("Pulling frames from clip..."), TRUE);
1512 res = virtual_to_images(clip, start, end, TRUE, NULL);
1514
1515 if (mainw->cancelled != CANCEL_NONE || res < 0) {
1517 lives_freep((void **)&mainw->subt_save_file);
1518 if (res <= 0) d_print_file_error_failed();
1519 return;
1520 }
1521 }
1522
1524
1525 nfile = mainw->files[new_file];
1526 nfile->hsize = sfile->hsize;
1527 nfile->vsize = sfile->vsize;
1528 cfile->progress_start = nfile->start = 1;
1529 cfile->progress_end = nfile->frames = nfile->end = end - start + 1;
1530 nfile->fps = sfile->fps;
1531 nfile->arps = sfile->arps;
1532 nfile->arate = sfile->arate;
1533 nfile->achans = sfile->achans;
1534 nfile->asampsize = sfile->asampsize;
1535 nfile->signed_endian = sfile->signed_endian;
1536 nfile->img_type = sfile->img_type;
1537
1538 com = lives_strdup_printf("%s link_frames \"%s\" %d %d %.8f %.8f %d %d %d %d %d \"%s\"", prefs->backend, nfile->handle,
1539 start, end, aud_start, aud_end, nfile->arate, nfile->achans, nfile->asampsize,
1540 !(nfile->signed_endian & AFORM_UNSIGNED), !(nfile->signed_endian & AFORM_BIG_ENDIAN),
1541 sfile->handle);
1542
1543 lives_rm(nfile->info_file);
1544 lives_system(com, FALSE);
1545 lives_free(com);
1546
1547 // TODO - eliminate this
1548 mainw->current_file = new_file;
1549
1550 if (THREADVAR(com_failed)) {
1551 char *permitname = lives_build_filename(prefs->workdir, cfile->handle, TEMPFILE_MARKER "." LIVES_FILE_EXT_TMP, NULL);
1552#ifdef IS_MINGW
1553 // kill any active processes: for other OSes the backend does this
1555#endif
1556 lives_touch(permitname);
1557 lives_free(permitname);
1558 lives_system(lives_strdup_printf("%s close \"%s\"", prefs->backend, cfile->handle), TRUE);
1559 lives_freep((void **)&cfile);
1560 if (mainw->first_free_file == ALL_USED || mainw->first_free_file > new_file)
1561 mainw->first_free_file = new_file;
1562 if (!mainw->multitrack) {
1563 switch_to_file(mainw->current_file, current_file);
1564 }
1566 lives_freep((void **)&mainw->subt_save_file);
1567 return;
1568 }
1569
1570 cfile->nopreview = TRUE;
1571 if (!(do_progress_dialog(TRUE, TRUE, _("Linking selection")))) {
1572 char *permitname = lives_build_filename(prefs->workdir, cfile->handle, TEMPFILE_MARKER "." LIVES_FILE_EXT_TMP, NULL);
1573#ifdef IS_MINGW
1574 // kill any active processes: for other OSes the backend does this
1576#endif
1577 lives_touch(permitname);
1578 lives_free(permitname);
1579 lives_system((tmp = lives_strdup_printf("%s close \"%s\"", prefs->backend, cfile->handle)), TRUE);
1580 lives_free(tmp);
1581 lives_freep((void **)&cfile);
1582 if (mainw->first_free_file == ALL_USED || mainw->first_free_file > new_file)
1583 mainw->first_free_file = new_file;
1584
1585 if (!mainw->multitrack) {
1586 switch_to_file(mainw->current_file, current_file);
1587 }
1588 if (mainw->error) d_print_failed();
1589 else d_print_cancelled();
1590 lives_freep((void **)&mainw->subt_save_file);
1591 return;
1592 }
1593
1594 // cfile->arate, etc., would have been reset by calls to do_progress_dialog() which calls get_total_time() [since cfile->afilesize==0]
1595 // so we need to set these again now that link_frames has provided an actual audio clip
1596
1597 nfile->arps = sfile->arps;
1598 nfile->arate = sfile->arate;
1599 nfile->achans = sfile->achans;
1600 nfile->asampsize = sfile->asampsize;
1601 nfile->signed_endian = sfile->signed_endian;
1602
1603 reget_afilesize(new_file);
1604
1605 aud_start = calc_time_from_frame(new_file, 1) * nfile->arps / nfile->arate;
1606 aud_end = calc_time_from_frame(new_file, nfile->frames + 1) * nfile->arps / nfile->arate;
1607 cfile->nopreview = FALSE;
1608 } else mainw->current_file = clip; // for encoder restns
1609
1610 if (rdet) rdet->is_encoding = TRUE;
1611
1612 if (!check_encoder_restrictions(FALSE, FALSE, save_all)) {
1613 if (!save_all && !safe_symlinks) {
1614 char *permitname = lives_build_filename(prefs->workdir, nfile->handle, TEMPFILE_MARKER "." LIVES_FILE_EXT_TMP, NULL);
1615#ifdef IS_MINGW
1616 lives_kill_subprocesses(nfile->handle, TRUE);
1617#endif
1618 lives_touch(permitname);
1619 lives_free(permitname);
1620 lives_system((com = lives_strdup_printf("%s close \"%s\"", prefs->backend, nfile->handle)), TRUE);
1621 lives_free(com);
1622 lives_free(nfile);
1623 mainw->files[new_file] = NULL;
1624 if (mainw->first_free_file == ALL_USED || new_file) mainw->first_free_file = new_file;
1625 }
1626 if (!mainw->multitrack) {
1627 switch_to_file(mainw->current_file, current_file);
1628 }
1630 lives_freep((void **)&mainw->subt_save_file);
1631 return;
1632 }
1633
1634 if (!save_all && safe_symlinks) {
1635 int xarps, xarate, xachans, xasamps, xasigned_endian;
1636 // we are saving a selection - make symlinks in /tmp
1637
1638 startframe = -1;
1639
1640 if (sfile->clip_type == CLIP_TYPE_FILE) {
1642 cfile->progress_start = 1;
1643 cfile->progress_end = count_virtual_frames(sfile->frame_index, start, end);
1644 do_threaded_dialog(_("Pulling frames from clip..."), TRUE);
1645 res = virtual_to_images(clip, start, end, TRUE, NULL);
1647
1648 if (mainw->cancelled != CANCEL_NONE || res <= 0) {
1650 lives_freep((void **)&mainw->subt_save_file);
1651 if (res <= 0) d_print_file_error_failed();
1652 return;
1653 }
1654 }
1655
1656 com = lives_strdup_printf("%s link_frames \"%s\" %d %d %.8f %.8f %d %d %d %d %d", prefs->backend, sfile->handle,
1657 start, end, aud_start, aud_end, sfile->arate, sfile->achans, sfile->asampsize,
1659
1660 lives_rm(sfile->info_file);
1661 lives_system(com, FALSE);
1662 lives_free(com);
1663
1664 mainw->current_file = clip;
1665
1666 xarps = sfile->arps;
1667 xarate = sfile->arate;
1668 xachans = sfile->achans;
1669 xasamps = sfile->asampsize;
1670 xasigned_endian = sfile->signed_endian;
1671
1672 if (THREADVAR(com_failed)) {
1673 com = lives_strdup_printf("%s clear_symlinks \"%s\"", prefs->backend_sync, cfile->handle);
1674 lives_system(com, TRUE);
1675 lives_free(com);
1676 cfile->nopreview = FALSE;
1677 if (!mainw->multitrack) {
1678 switch_to_file(mainw->current_file, current_file);
1679 }
1681 lives_freep((void **)&mainw->subt_save_file);
1682 return;
1683 }
1684
1685 cfile->nopreview = TRUE;
1686 if (!(do_progress_dialog(TRUE, TRUE, _("Linking selection")))) {
1687 com = lives_strdup_printf("%s clear_symlinks \"%s\"", prefs->backend_sync, cfile->handle);
1688 lives_system(com, TRUE);
1689 lives_free(com);
1690 cfile->nopreview = FALSE;
1691 if (!mainw->multitrack) {
1692 switch_to_file(mainw->current_file, current_file);
1693 }
1694 if (mainw->error) d_print_failed();
1695 else d_print_cancelled();
1696 lives_freep((void **)&mainw->subt_save_file);
1697 return;
1698 }
1699
1700 // cfile->arate, etc., would have been reset by calls to do_progress_dialog() which calls get_total_time() [since cfile->afilesize==0]
1701 // so we need to set these again now that link_frames has provided an actual audio clip
1702
1703 sfile->arps = xarps;
1704 sfile->arate = xarate;
1705 sfile->achans = xachans;
1706 sfile->asampsize = xasamps;
1707 sfile->signed_endian = xasigned_endian;
1708
1709 reget_afilesize(clip);
1710
1711 aud_start = calc_time_from_frame(clip, 1) * sfile->arps / sfile->arate;
1712 aud_end = calc_time_from_frame(clip, end - start + 1) * sfile->arps / sfile->arate;
1713 cfile->nopreview = FALSE;
1714 }
1715
1716 if (save_all) {
1717 if (sfile->clip_type == CLIP_TYPE_FILE) {
1718 frames_t ret;
1719 char *msg = (_("Pulling frames from clip..."));
1720 if ((ret = realize_all_frames(clip, msg, FALSE)) < sfile->frames) {
1721 lives_free(msg);
1722 lives_freep((void **)&mainw->subt_save_file);
1723 if (ret > 0) d_print_cancelled();
1724 if (!mainw->multitrack) {
1725 switch_to_file(mainw->current_file, current_file);
1726 }
1727 return;
1728 }
1729 lives_free(msg);
1730 }
1731 }
1732
1734 bit = (_(" (with no sound)\n"));
1735 } else {
1736 bit = lives_strdup("\n");
1737 }
1738
1739 if (!save_all) {
1740 mesg = lives_strdup_printf(_("Saving frames %d to %d%s as \"%s\" : encoder = %s : format = %s..."),
1741 start, end, bit, full_file_name, prefs->encoder.name, prefs->encoder.of_desc);
1742 } // end selection
1743 else {
1744 mesg = lives_strdup_printf(_("Saving frames 1 to %d%s as \"%s\" : encoder %s : format = %s..."),
1745 sfile->frames, bit, full_file_name, prefs->encoder.name, prefs->encoder.of_desc);
1746 }
1747 lives_free(bit);
1748
1750 d_print(mesg);
1752 lives_free(mesg);
1753
1754 if (prefs->show_gui && !debug_mode) {
1755 // open a file for stderr
1756 new_stderr_name = lives_build_filename(prefs->workdir, cfile->handle, LIVES_ENC_DEBUG_FILE_NAME, NULL);
1757 lives_free(redir);
1758
1759 do {
1760 retval = 0;
1761 new_stderr = lives_open3(new_stderr_name, O_CREAT | O_RDONLY | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR);
1762 if (new_stderr < 0) {
1763 retval = do_write_failed_error_s_with_retry(new_stderr_name, lives_strerror(errno));
1764 if (retval == LIVES_RESPONSE_CANCEL) redir = lives_strdup("1>&2");
1765 } else {
1766
1767#ifdef IS_MINGW
1768
1769#ifdef GUI_GTK
1770 mainw->iochan = g_io_channel_win32_new_fd(new_stderr);
1771#endif
1772 redir = lives_strdup_printf("2>&1 >\"%s\"", new_stderr_name);
1773#else
1774#ifdef GUI_GTK
1775 mainw->iochan = g_io_channel_unix_new(new_stderr);
1776#endif
1777 redir = lives_strdup_printf("2>\"%s\"", new_stderr_name);
1778#endif
1779
1780#ifdef GUI_QT
1781 mainw->iochan = new QFile;
1782 mainw->iochan->open(new_stderr, QIODevice::ReadOnly);
1783#endif
1784
1785#ifdef GUI_GTK
1786 g_io_channel_set_encoding(mainw->iochan, NULL, NULL);
1787 g_io_channel_set_buffer_size(mainw->iochan, 0);
1788 g_io_channel_set_flags(mainw->iochan, G_IO_FLAG_NONBLOCK, &gerr);
1789 if (gerr) lives_error_free(gerr);
1790 gerr = NULL;
1791#endif
1793 }
1794 } while (retval == LIVES_RESPONSE_RETRY);
1795 } else {
1796 lives_free(redir);
1797 redir = lives_strdup("1>&2");
1798 }
1799
1800 if (lives_file_test((tmp = lives_filename_from_utf8(full_file_name, -1, NULL, NULL, NULL)), LIVES_FILE_TEST_EXISTS)) {
1801 lives_rm(tmp);
1802 }
1803 lives_free(tmp);
1804
1806
1807 if (arate != 0) arate = cfile->arate;
1808
1809 if (!cfile->ratio_fps) {
1810 fps_string = lives_strdup_printf("%.3f", cfile->fps);
1811 } else {
1812 fps_string = lives_strdup_printf("%.8f", cfile->fps);
1813 }
1814
1815 // if startframe is -ve, we will use the links created for safe_symlinks - in /tmp
1816 // for non-safe symlinks, cfile will be our new links file
1817 // for save_all, cfile will be sfile
1818
1820 com = lives_strdup_printf("%s save \"%s\" \"%s\" \"%s\" \"%s\" %d %d %d %d %d %d %.4f %.4f %s %s", prefs->backend,
1821 cfile->handle,
1822 enc_exec_name, fps_string, (tmp = lives_filename_from_utf8(full_file_name, -1, NULL, NULL, NULL)),
1823 startframe, cfile->frames, arate, cfile->achans, cfile->asampsize,
1824 asigned | aendian, aud_start, aud_end, (extra_params == NULL) ? "" : extra_params, redir);
1825 } else {
1826 com = lives_strdup_printf("%s save \"%s\" \"native:%s\" \"%s\" \"%s\" %d %d %d %d %d %d %.4f %.4f %s %s", prefs->backend,
1827 cfile->handle,
1828 enc_exec_name, fps_string, (tmp = lives_filename_from_utf8(full_file_name, -1, NULL, NULL, NULL)),
1829 startframe, cfile->frames, arate, cfile->achans, cfile->asampsize,
1830 asigned | aendian, aud_start, aud_end, (extra_params == NULL) ? "" : extra_params, redir);
1831
1832 }
1833 lives_free(tmp);
1834 lives_free(fps_string);
1835
1836 lives_freep((void **)&extra_params);
1837
1839 cfile->nokeep = TRUE;
1840
1841 lives_rm(cfile->info_file);
1842 THREADVAR(write_failed) = FALSE;
1843 save_file_comments(current_file);
1844
1845 if (debug_mode) {
1846 fprintf(stderr, "Running command: %s\n", com);
1847 }
1848
1849 lives_system(com, FALSE);
1850 lives_free(com);
1851 mainw->error = FALSE;
1852
1853 if (THREADVAR(com_failed) || THREADVAR(write_failed)) {
1854 mainw->error = TRUE;
1855 }
1856
1857 if (!mainw->error) {
1858 //char *pluginstr;
1859
1860 cfile->progress_start = 1;
1861 cfile->progress_end = cfile->frames;
1862
1863 not_cancelled = do_progress_dialog(TRUE, TRUE, _("Saving [can take a long time]"));
1864
1865 if (mainw->iochan) {
1867
1868 lives_fsync(new_stderr);
1870
1871#ifdef GUI_GTK
1872 g_io_channel_shutdown(mainw->iochan, FALSE, &gerr);
1873 g_io_channel_unref(mainw->iochan);
1874 if (gerr) lives_error_free(gerr);
1875#endif
1876#ifdef GUI_QT
1877 delete mainw->iochan;
1878#endif
1879 mainw->iochan = NULL;
1880
1881 close(new_stderr);
1882 lives_rm(new_stderr_name);
1883 lives_free(new_stderr_name);
1884 lives_free(redir);
1885 }
1886
1888 cfile->nokeep = FALSE;
1889 } else {
1890 if (mainw->iochan) {
1892
1893 lives_fsync(new_stderr);
1895
1896#ifdef GUI_GTK
1897 g_io_channel_shutdown(mainw->iochan, FALSE, &gerr);
1898 g_io_channel_unref(mainw->iochan);
1899 if (gerr) lives_error_free(gerr);
1900#endif
1901#ifdef GUI_QT
1902 delete mainw->iochan;
1903#endif
1904 mainw->iochan = NULL;
1905 close(new_stderr);
1906 lives_rm(new_stderr_name);
1907 lives_free(new_stderr_name);
1908 lives_free(redir);
1909 }
1910 }
1911
1912 cwd = lives_get_current_dir();
1913
1914 clipdir = lives_build_path(prefs->workdir, cfile->handle, NULL);
1915 lives_chdir(clipdir, FALSE);
1916 lives_free(clipdir);
1917
1918 com = lives_strdup_printf("\"%s\" clear", enc_exec_name);
1919
1920 if (debug_mode) {
1921 fprintf(stderr, "Running command: %s\n", com);
1922 }
1923 lives_system(com, FALSE);
1924 lives_free(com);
1925
1926 lives_chdir(cwd, FALSE);
1927 lives_free(cwd);
1928
1929 lives_free(enc_exec_name);
1930
1931 if (not_cancelled || mainw->error) {
1932 if (mainw->error) {
1936 lives_free(full_file_name);
1937 if (!save_all && !safe_symlinks) {
1938 char *permitname = lives_build_filename(prefs->workdir, cfile->handle, TEMPFILE_MARKER "." LIVES_FILE_EXT_TMP, NULL);
1940 lives_touch(permitname);
1941 lives_free(permitname);
1942 lives_system((com = lives_strdup_printf("%s close \"%s\"", prefs->backend, cfile->handle)), TRUE);
1943 lives_free(com);
1944 lives_freep((void **)&cfile);
1947 } else if (!save_all && safe_symlinks) {
1948 com = lives_strdup_printf("%s clear_symlinks \"%s\"", prefs->backend_sync, cfile->handle);
1949 lives_system(com, TRUE);
1950 lives_free(com);
1951 }
1952
1953 switch_to_file(mainw->current_file, current_file);
1954
1955 lives_freep((void **)&mainw->subt_save_file);
1956 sensitize();
1957 return;
1958 }
1959
1960 if (lives_file_test((tmp = lives_filename_from_utf8(full_file_name, -1, NULL, NULL, NULL)), LIVES_FILE_TEST_EXISTS)) {
1961 lives_free(tmp);
1962 stat((tmp = lives_filename_from_utf8(full_file_name, -1, NULL, NULL, NULL)), &filestat);
1963 if (filestat.st_size > 0) output_exists = TRUE;
1964 }
1965 if (!output_exists) {
1966 lives_free(tmp);
1967
1971 lives_free(full_file_name);
1972 if (!save_all && !safe_symlinks) {
1973 char *permitname = lives_build_filename(prefs->workdir, cfile->handle, TEMPFILE_MARKER "." LIVES_FILE_EXT_TMP, NULL);
1975 lives_touch(permitname);
1976 lives_free(permitname);
1977 lives_system((com = lives_strdup_printf("%s close \"%s\"", prefs->backend, cfile->handle)), TRUE);
1978 lives_free(com);
1979 lives_freep((void **)&cfile);
1982 } else if (!save_all && safe_symlinks) {
1983 com = lives_strdup_printf("%s clear_symlinks \"%s\"", prefs->backend_sync, cfile->handle);
1984 lives_system(com, TRUE);
1985 lives_free(com);
1986 }
1987
1988 if (!mainw->multitrack) {
1989 switch_to_file(mainw->current_file, current_file);
1990 }
1991 retval = do_error_dialog(_("\n\nEncoder error - output file was not created !\n"));
1992
1993 if (retval == LIVES_RESPONSE_SHOW_DETAILS) {
1996 }
1997
1998 if (mainw->iochan) {
1999 save_log_file("failed_encoder_log");
2000 mainw->iochan = NULL;
2002 }
2003
2004 lives_freep((void **)&mainw->subt_save_file);
2005 sensitize();
2006 if (mainw->error) d_print_failed();
2007
2008 return;
2009 }
2010 lives_free(tmp);
2011
2012 if (save_all) {
2013 if (prefs->enc_letterbox) {
2015 int iwidth = sfile->ohsize;
2016 int iheight = sfile->ovsize;
2017 boolean bad_header = FALSE;
2018
2019 com = lives_strdup_printf("%s mv_mgk \"%s\" %d %d \"%s\" 1", prefs->backend, sfile->handle, 1, sfile->frames,
2021
2022 lives_rm(sfile->info_file);
2023 lives_system(com, FALSE);
2024
2025 do_progress_dialog(TRUE, FALSE, _("Clearing letterbox"));
2026
2027 if (mainw->error) {
2028 // cfile->may_be_damaged=TRUE;
2030 return;
2031 }
2032
2033 calc_maxspect(sfile->hsize, sfile->vsize, &iwidth, &iheight);
2034
2035 sfile->hsize = iwidth;
2036 sfile->vsize = iheight;
2037
2039 if (THREADVAR(com_failed) || THREADVAR(write_failed)) bad_header = TRUE;
2041 if (THREADVAR(com_failed) || THREADVAR(write_failed)) bad_header = TRUE;
2042 if (bad_header) do_header_write_error(mainw->current_file);
2043 }
2044
2045 lives_snprintf(sfile->save_file_name, PATH_MAX, "%s", full_file_name);
2046 sfile->changed = FALSE;
2047
2050 fsize = sget_file_size(full_file_name);
2051 if (fsize < 0) fsize = 0;
2052 cfile->f_size = (size_t)fsize;
2053
2054 if (sfile->is_untitled) {
2055 sfile->is_untitled = FALSE;
2056 }
2057 if (!sfile->was_renamed) {
2058 lives_menu_item_set_text(sfile->menuentry, full_file_name, FALSE);
2059 lives_snprintf(sfile->name, CLIP_NAME_MAXLEN, "%s", full_file_name);
2060 }
2061 set_main_title(cfile->name, 0);
2062 if (prefs->show_recent) {
2063 add_to_recent(full_file_name, 0., 0, NULL);
2064 global_recent_manager_add(full_file_name);
2065 }
2066 } else {
2067 if (!safe_symlinks) {
2068 char *permitname = lives_build_filename(prefs->workdir, nfile->handle, TEMPFILE_MARKER "." LIVES_FILE_EXT_TMP, NULL);
2069#ifdef IS_MINGW
2070 lives_kill_subprocesses(nfile->handle, TRUE);
2071#endif
2072 lives_touch(permitname);
2073 lives_free(permitname);
2074 lives_system((com = lives_strdup_printf("%s close \"%s\"", prefs->backend, nfile->handle)), TRUE);
2075 lives_free(com);
2076 lives_free(nfile);
2077 mainw->files[new_file] = NULL;
2079 mainw->first_free_file = new_file;
2080 } else {
2081 com = lives_strdup_printf("%s clear_symlinks \"%s\"", prefs->backend_sync, cfile->handle);
2082 lives_system(com, TRUE);
2083 lives_free(com);
2084 }
2085 }
2086 }
2087
2088 if (!mainw->multitrack) {
2089 switch_to_file(mainw->current_file, current_file);
2090 }
2091 if (mainw->iochan) {
2092 save_log_file("encoder_log");
2094 mainw->iochan = NULL;
2095 }
2096
2097 if (not_cancelled) {
2098 char *fsize_ds;
2100 d_print_done();
2101
2103
2104 fsize = sget_file_size(full_file_name);
2105 if (fsize >= 0) {
2107
2108 fsize_ds = lives_format_storage_space_string(fsize);
2109 d_print(_("File size was %s\n"), fsize_ds);
2110 lives_free(fsize_ds);
2111
2112 if (mainw->subt_save_file) {
2113 save_subs_to_file(sfile, mainw->subt_save_file);
2114 lives_freep((void **)&mainw->subt_save_file);
2115 }
2116 }
2118
2120 (mesg = lives_strdup_printf("encode %d \"%s\"", clip,
2121 (tmp = lives_filename_from_utf8(full_file_name, -1, NULL, NULL, NULL)))));
2122 lives_free(tmp);
2123 lives_free(mesg);
2124 } else {
2125 lives_rm((tmp = lives_filename_from_utf8(full_file_name, -1, NULL, NULL, NULL)));
2126 lives_free(tmp);
2127 }
2128
2129 lives_free(full_file_name);
2130}
2131
2132
2133char *prep_audio_player(char *com2, char *com3, frames_t audio_end, int arate, int asigned, int aendian) {
2134 char *stfile = NULL;
2135 char *stopcom = NULL, *com;
2136 short audio_player = prefs->audio_player;
2137 int loop = 0;
2138
2139 if (cfile->achans > 0) {
2140 cfile->aseek_pos = (off64_t)(cfile->real_pointer_time * (double)cfile->arate) * cfile->achans * (cfile->asampsize / 8);
2141 if (mainw->playing_sel) {
2142 off64_t apos = (off64_t)((double)(mainw->play_start - 1.) / cfile->fps * (double)cfile->arate) * cfile->achans *
2143 (cfile->asampsize / 8);
2144 if (apos > cfile->aseek_pos) cfile->aseek_pos = apos;
2145 }
2146 if (cfile->aseek_pos > cfile->afilesize) cfile->aseek_pos = 0.;
2147 if (mainw->current_file == 0 && cfile->arate < 0) cfile->aseek_pos = cfile->afilesize;
2148 }
2149 // start up our audio player (jack or pulse)
2150 if (audio_player == AUD_PLAYER_JACK) {
2151#ifdef ENABLE_JACK
2152 if (mainw->jackd) jack_aud_pb_ready(mainw->current_file);
2153 return NULL;
2154#endif
2155 } else if (audio_player == AUD_PLAYER_PULSE) {
2156#ifdef HAVE_PULSE_AUDIO
2157 if (mainw->pulsed) pulse_aud_pb_ready(mainw->current_file);
2158 return NULL;
2159#endif
2160 } else if (audio_player != AUD_PLAYER_NONE && cfile->achans > 0) {
2161 // sox or mplayer audio - run as background process
2162 if (com3) {
2163 if (mainw->loop_cont) {
2164 // tell audio to loop forever
2165 loop = -1;
2166 }
2167
2168 stfile = lives_build_filename(prefs->workdir, cfile->handle, ".stoploop", NULL);
2169 lives_rm(stfile);
2170
2171 if (cfile->achans > 0 || (!cfile->is_loaded && !mainw->is_generating)) {
2172 if (loop) {
2173 lives_free(com3);
2174 com3 = lives_strdup_printf("%s \"%s\" 2>\"%s\" 1>&2", capable->touch_cmd, stfile, prefs->cmd_log);
2175 }
2176
2177 if (com2) {
2178 if (cfile->achans > 0) {
2179 com2 = lives_strdup_printf("%s stop_audio %s", prefs->backend_sync, cfile->handle);
2180 }
2181 stopcom = lives_strconcat(com3, com2, NULL);
2182 }
2183 }
2184 }
2185
2186 lives_freep((void **)&stfile);
2187
2188 stfile = lives_build_filename(prefs->workdir, cfile->handle, LIVES_STATUS_FILE_NAME".play", NULL);
2189
2190 lives_snprintf(cfile->info_file, PATH_MAX, "%s", stfile);
2191 lives_free(stfile);
2192 if (cfile->clip_type == CLIP_TYPE_DISK) lives_rm(cfile->info_file);
2193
2194 // PLAY
2195
2196 if (cfile->clip_type == CLIP_TYPE_DISK && cfile->opening) {
2197 com = lives_strdup_printf("%s play_opening_preview \"%s\" %.3f %d %d %d %d %d %d %d %d", prefs->backend,
2198 cfile->handle, cfile->fps, mainw->audio_start, audio_end, 0,
2199 arate, cfile->achans, cfile->asampsize, asigned, aendian);
2200 } else {
2201 // this is only used now for sox or mplayer audio player
2202 com = lives_strdup_printf("%s play %s %.3f %d %d %d %d %d %d %d %d", prefs->backend, cfile->handle,
2203 cfile->fps, mainw->audio_start, audio_end, loop,
2204 arate, cfile->achans, cfile->asampsize, asigned, aendian);
2205 }
2206 if (!mainw->multitrack && com) lives_system(com, FALSE);
2207 }
2208 return stopcom;
2209}
2210
2211
2213void play_file(void) {
2214 LiVESWidgetClosure *freeze_closure, *bg_freeze_closure;
2215 LiVESList *cliplist;
2216 weed_plant_t *pb_start_event = NULL;
2217
2218#ifdef GDK_WINDOWING_X11
2219 uint64_t awinid = -1;
2220#endif
2221
2222 char *com, *com2 = lives_strdup(" "), *com3 = lives_strdup(" ");
2223 char *stopcom = NULL;
2224 char *stfile;
2225#ifdef GDK_WINDOWING_X11
2226 char *tmp;
2227#endif
2228
2229 double fps_med = 0.;
2230 double pointer_time = cfile->pointer_time;
2231 double real_pointer_time = cfile->real_pointer_time;
2232
2233 short audio_player = prefs->audio_player;
2234
2235 boolean mute;
2236 boolean needsadone = FALSE;
2237
2238#ifdef RT_AUDIO
2239 boolean exact_preview = FALSE;
2240#endif
2241 boolean has_audio_buffers = FALSE;
2242
2243 int arate;
2244
2245 int asigned = !(cfile->signed_endian & AFORM_UNSIGNED);
2246 int aendian = !(cfile->signed_endian & AFORM_BIG_ENDIAN);
2247 int current_file = mainw->current_file;
2248 int audio_end = 0;
2249
2251 mainw->noswitch = TRUE;
2253
2254 asigned = !(cfile->signed_endian & AFORM_UNSIGNED);
2255 aendian = !(cfile->signed_endian & AFORM_BIG_ENDIAN);
2256 current_file = mainw->current_file;
2257 if (mainw->pre_play_file == -1) mainw->pre_play_file = current_file;
2258
2260 else mainw->aud_file_to_kill = -1;
2261
2262#ifdef ENABLE_JACK_TRANSPORT
2263 if (!mainw->preview && !mainw->foreign) {
2264 if (!mainw->multitrack)
2265 jack_pb_start(cfile->achans > 0 ? cfile->real_pointer_time : cfile->pointer_time);
2266 else
2267 jack_pb_start(mainw->multitrack->pb_start_time);
2268 }
2269#endif
2270
2272
2273 mainw->rec_aclip = -1;
2274
2276
2279
2281 lives_accel_group_connect(LIVES_ACCEL_GROUP(mainw->accel_group), LIVES_KEY_BackSpace,
2282 (LiVESXModifierType)LIVES_CONTROL_MASK,
2283 (LiVESAccelFlags)0, (freeze_closure = lives_cclosure_new(LIVES_GUI_CALLBACK(freeze_callback),
2284 LIVES_INT_TO_POINTER(SCREEN_AREA_FOREGROUND), NULL)));
2285 lives_accel_group_connect(LIVES_ACCEL_GROUP(mainw->accel_group), LIVES_KEY_BackSpace,
2286 (LiVESXModifierType)(LIVES_CONTROL_MASK | LIVES_ALT_MASK),
2287 (LiVESAccelFlags)0, (bg_freeze_closure = lives_cclosure_new(LIVES_GUI_CALLBACK(freeze_callback),
2288 LIVES_INT_TO_POINTER(SCREEN_AREA_BACKGROUND), NULL)));
2289
2291 lives_accel_path_disconnect(mainw->accel_group, LIVES_ACCEL_PATH_QUIT);
2292
2293 if (mainw->multitrack) {
2294 mainw->event_list = mainw->multitrack->event_list;
2295 pb_start_event = mainw->multitrack->pb_start_event;
2296#ifdef RT_AUDIO
2297 exact_preview = mainw->multitrack->exact_preview;
2298#endif
2299 }
2300
2301 // reinit all active effects
2303
2304 if (mainw->record) {
2305 if (mainw->preview) {
2306 mainw->record = FALSE;
2307 d_print(_("recording aborted by preview.\n"));
2308 } else if (mainw->current_file == 0) {
2309 mainw->record = FALSE;
2310 d_print(_("recording aborted by clipboard playback.\n"));
2311 } else {
2312 d_print(_("Recording performance..."));
2313 needsadone = TRUE;
2315 // TODO
2316 if (mainw->current_file > 0 && (cfile->undo_action == UNDO_RESAMPLE || cfile->undo_action == UNDO_RENDER)) {
2319 cfile->undoable = cfile->redoable = FALSE;
2320 }
2321 }
2322 }
2324 else if (mainw->event_list) cfile->next_event = get_first_event(mainw->event_list);
2325
2329 //lives_signal_handler_block(mainw->spinbutton_start, mainw->spin_start_func);
2330 //lives_signal_handler_block(mainw->spinbutton_end, mainw->spin_end_func);
2331 }
2332
2333#ifdef ENABLE_JACK_TRANSPORT
2336 // calculate the start position from jack transport
2337 double sttime = (double)jack_transport_get_current_ticks() / TICKS_PER_SECOND_DBL;
2338 cfile->pointer_time = cfile->real_pointer_time = sttime;
2339 if (cfile->real_pointer_time > CLIP_TOTAL_TIME(mainw->current_file))
2340 cfile->real_pointer_time = CLIP_TOTAL_TIME(mainw->current_file);
2341 if (cfile->pointer_time > cfile->video_time) cfile->pointer_time = 0.;
2343 }
2344#endif
2345
2348
2349 if (cfile->achans > 0) {
2350 if (mainw->event_list &&
2351 !(mainw->preview && mainw->is_rendering) &&
2352 !(mainw->multitrack && mainw->preview && mainw->multitrack->is_rendering)) {
2354 if (event_list_get_end_secs(mainw->event_list) > cfile->frames / cfile->fps && !mainw->playing_sel) {
2355 mainw->audio_end = (event_list_get_end_secs(mainw->event_list) * cfile->fps + 1.) * cfile->arate / cfile->arps;
2356 }
2357 }
2358
2359 if (mainw->audio_end == 0) {
2361 mainw->play_start) * cfile->fps + 1. * cfile->arate / cfile->arps;
2363 + 1. * cfile->arate / cfile->arps;
2364 if (!mainw->playing_sel) {
2365 mainw->audio_end = 0;
2366 }
2367 }
2368 }
2369
2370 if (!cfile->opening_audio && !mainw->loop) {
2373 audio_end = mainw->audio_end;
2374 }
2375
2376 if (!mainw->multitrack) {
2377 if (!mainw->preview) {
2378 lives_frame_set_label(LIVES_FRAME(mainw->playframe), _("Play"));
2379 } else {
2380 lives_frame_set_label(LIVES_FRAME(mainw->playframe), _("Preview"));
2381 }
2382
2383 if (palette->style & STYLE_1) {
2385 LIVES_WIDGET_STATE_NORMAL, &palette->normal_fore);
2386 }
2387
2388 if (mainw->foreign) {
2391 }
2392
2394 if ((mainw->faded || (prefs->show_playwin && !prefs->show_gui)
2395 || (mainw->fs && (!mainw->sep_win))) && (cfile->frames > 0 ||
2396 mainw->foreign)) {
2398 }
2399
2401 && (cfile->frames > 0 ||
2402 mainw->foreign)) {
2406 }
2407
2410 }
2411
2412 arate = cfile->arate;
2413
2414 mute = mainw->mute;
2415
2416 if (!is_realtime_aplayer(audio_player)) {
2417 if (cfile->achans == 0 || mainw->is_rendering) mainw->mute = TRUE;
2418 if (mainw->mute && !cfile->opening_only_audio) arate = arate ? -arate : -1;
2419 }
2420
2421 cfile->frameno = mainw->play_start;
2422 cfile->pb_fps = cfile->fps;
2423 if (mainw->reverse_pb) {
2424 cfile->pb_fps = -cfile->pb_fps;
2425 cfile->frameno = mainw->play_end;
2426 }
2427 cfile->last_frameno = cfile->frameno;
2429
2430 mainw->swapped_clip = -1;
2431 mainw->blend_palette = WEED_PALETTE_END;
2432
2433 cfile->play_paused = FALSE;
2435
2436 if (audio_player == AUD_PLAYER_JACK
2439
2441
2444
2445 if (!mainw->preview || !cfile->opening) {
2446 enable_record();
2447 desensitize();
2449 }
2450
2451 if (mainw->record) {
2454 }
2455
2458 }
2459
2461
2463 else if (!cfile->opening) {
2465 else {
2468 }
2469 }
2470
2472
2476
2478 mainw->loop_cont || is_realtime_aplayer(audio_player))
2479 && mainw->current_file > 0);
2481 is_realtime_aplayer(audio_player))
2482 && mainw->current_file > 0);
2483
2484 if (cfile->frames == 0 && !mainw->multitrack) {
2486
2488
2489 mainw->pw_scroll_func = lives_signal_connect(LIVES_GUI_OBJECT(mainw->play_window), LIVES_WIDGET_SCROLL_EVENT,
2490 LIVES_GUI_CALLBACK(on_mouse_scroll), NULL);
2491 }
2492 } else {
2493 if (mainw->sep_win) {
2497 } else {
2498 if (!mainw->multitrack) {
2499 if (mainw->preview_controls) {
2501 /* mainw->pw_scroll_func = lives_signal_connect(LIVES_GUI_OBJECT(mainw->play_window), LIVES_WIDGET_SCROLL_EVENT, */
2502 /* LIVES_GUI_CALLBACK(on_mouse_scroll), */
2503 /* NULL); */
2504 }
2505 }
2506
2507 if (!mainw->multitrack || mainw->fs) {
2509 }
2510
2512 if (!mainw->multitrack) {
2514 } else {
2516 if (mainw->play_window) {
2517 if (prefs->show_playwin) {
2518 lives_window_present(LIVES_WINDOW(mainw->play_window));
2520 // *INDENT-OFF*
2521 }}}}}
2522 // *INDENT-ON*
2523
2524 if (mainw->play_window) {
2528 }
2529
2530 if (!mainw->foreign && !mainw->sep_win) {
2532 }
2533
2534 if (!mainw->sep_win && !mainw->foreign) {
2535 if (mainw->double_size) resize(2.);
2536 else resize(1);
2537 }
2538
2539 /* if (mainw->vpp && mainw->vpp->fheight > -1 && mainw->vpp->fwidth > -1) { */
2540 /* // fixed o/p size for stream */
2541 /* if (mainw->vpp->fwidth * mainw->vpp->fheight == 0) { */
2542 /* mainw->vpp->fwidth = DEF_VPP_HSIZE; */
2543 /* mainw->vpp->fheight = DEF_VPP_VSIZE; */
2544 /* } */
2545 /* if (!(mainw->vpp->capabilities & VPP_CAN_RESIZE)) { */
2546 /* mainw->pwidth = mainw->vpp->fwidth; */
2547 /* mainw->pheight = mainw->vpp->fheight; */
2548 /* } */
2549 /* } */
2550
2551 if (mainw->fs && !mainw->sep_win && cfile->frames > 0) {
2553 }
2554 }
2555
2556 // moved down because xdg-screensaver requires a mapped windowID
2557 if (prefs->stop_screensaver) {
2558 lives_freep((void **)&com2);
2559#ifdef GDK_WINDOWING_X11
2561 awinid = lives_widget_get_xwinid(mainw->play_window, NULL);
2562 } else if (prefs->show_gui) {
2564 }
2565
2566 com2 = lives_strdup("xset s off 2>/dev/null; xset -dpms 2>/dev/null ;");
2567
2568 if (capable->has_gconftool_2) {
2569 char *xnew = lives_strdup(" gconftool-2 --set --type bool /apps/gnome-screensaver/idle_activation_enabled "
2570 "false 2>/dev/null ;");
2571 tmp = lives_concat(com2, xnew);
2572 com2 = tmp;
2573 }
2574 if (capable->has_xdg_screensaver && awinid != -1) {
2575 char *xnew = lives_strdup_printf(" xdg-screensaver suspend %"PRIu64" 2>/dev/null ;", awinid);
2576 tmp = lives_concat(com2, xnew);
2577 com2 = tmp;
2578 }
2579#else
2580 if (capable->has_gconftool_2) {
2581 com2 = lives_strdup("gconftool-2 --set --type bool /apps/gnome-screensaver/idle_activation_enabled false 2>/dev/null ;");
2582 } else com2 = lives_strdup("");
2583#endif
2584 if (!com2) com2 = lives_strdup("");
2585 }
2586
2587 if (!mainw->foreign && prefs->midisynch && !mainw->preview) {
2588 lives_free(com3);
2589 com3 = lives_strdup(EXEC_MIDISTART);
2590 }
2591 com = lives_strconcat(com2, com3, NULL);
2592 if (*com) {
2593 // allow this to fail - not all sub-commands may be present
2594 lives_system(com, TRUE);
2595 }
2596 lives_freep((void **)&com);
2597 lives_freep((void **)&com2);
2598 lives_free(com3);
2599 com3 = lives_strdup(" ");
2600
2601 if (!mainw->multitrack) {
2602 lives_spin_button_set_value(LIVES_SPIN_BUTTON(mainw->spinbutton_pb_fps), cfile->pb_fps);
2603
2604 mainw->last_blend_file = -1;
2605
2606 // show the framebar
2607 if (!mainw->multitrack && !mainw->faded
2608 && (!prefs->hide_framebar &&
2610 && capable->nmonitors > 1 &&
2611 mainw->sep_win) ||
2613 ((!mainw->preview && (cfile->frames > 0 || mainw->foreign)) || cfile->opening))) {
2615 }
2616 }
2617
2618 cfile->play_paused = FALSE;
2619 mainw->actual_frame = 0;
2620
2621 mainw->currticks = 0;
2623
2625
2626 // reinit all active effects
2628
2629 if (!mainw->foreign && (!(prefs->audio_src == AUDIO_SRC_EXT &&
2630 (audio_player == AUD_PLAYER_JACK ||
2631 audio_player == AUD_PLAYER_PULSE || audio_player == AUD_PLAYER_NONE)))) {
2632 stopcom = prep_audio_player(com2, com3, audio_end, arate, asigned, aendian);
2633 }
2634
2635 lives_free(com3);
2636
2637 // if recording, refrain from writing audio until we are ready
2639
2640 // if recording, set up recorder (jack or pulse)
2641 if (!mainw->preview && (prefs->audio_src == AUDIO_SRC_EXT || (mainw->record && mainw->agen_key != 0))
2642 && (audio_player == AUD_PLAYER_JACK || audio_player == AUD_PLAYER_PULSE)) {
2643 mainw->rec_samples = -1; // record unlimited
2644 if (mainw->record) {
2645 // create temp clip
2647 if (mainw->ascrap_file != -1) {
2649 mainw->rec_avel = 1.;
2650 mainw->rec_aseek = 0;
2651 }
2652 }
2653 if (audio_player == AUD_PLAYER_JACK) {
2654#ifdef ENABLE_JACK
2656 if (mainw->agen_key != 0 || mainw->agen_needs_reinit) {
2657 mainw->jackd->playing_file = mainw->current_file;
2658 if (mainw->ascrap_file != -1 || !prefs->perm_audio_reader)
2659 jack_rec_audio_to_clip(mainw->ascrap_file, -1, RECA_GENERATED);
2660 } else {
2661 if (mainw->ascrap_file != -1 || !prefs->perm_audio_reader)
2662 jack_rec_audio_to_clip(mainw->ascrap_file, -1, RECA_EXTERNAL);
2663 }
2664 //mainw->jackd->in_use = TRUE;
2665 }
2667 mainw->jackd_read->num_input_channels = mainw->jackd_read->num_output_channels = 2;
2668 mainw->jackd_read->sample_in_rate = mainw->jackd_read->sample_out_rate;
2669 mainw->jackd_read->is_paused = TRUE;
2670 mainw->jackd_read->in_use = TRUE;
2671 }
2672#endif
2673 }
2674 if (audio_player == AUD_PLAYER_PULSE) {
2675#ifdef HAVE_PULSE_AUDIO
2677 if (mainw->agen_key != 0 || mainw->agen_needs_reinit) {
2678 mainw->pulsed->playing_file = mainw->current_file;
2679 if (mainw->ascrap_file != -1 || !prefs->perm_audio_reader)
2680 pulse_rec_audio_to_clip(mainw->ascrap_file, -1, RECA_GENERATED);
2681 } else {
2682 if (mainw->ascrap_file != -1 || !prefs->perm_audio_reader)
2683 pulse_rec_audio_to_clip(mainw->ascrap_file, -1, RECA_EXTERNAL);
2684 }
2685 //mainw->pulsed->in_use = TRUE;
2686 }
2688 mainw->pulsed_read->in_achans = mainw->pulsed_read->out_achans = PA_ACHANS;
2689 mainw->pulsed_read->in_asamps = mainw->pulsed_read->out_asamps = PA_SAMPSIZE;
2690 mainw->pulsed_read->in_arate = mainw->pulsed_read->out_arate;
2691 mainw->pulsed_read->is_paused = TRUE;
2692 mainw->pulsed_read->in_use = TRUE;
2693 }
2694#endif
2695 }
2696 }
2697
2698 // set in case audio lock gets actioned
2700
2702 if (mainw->osc_auto)
2705
2706#ifdef ENABLE_JACK
2707 if (mainw->event_list && !mainw->record && audio_player == AUD_PLAYER_JACK && mainw->jackd &&
2709 !(mainw->multitrack && mainw->preview && mainw->multitrack->is_rendering))) {
2710 // if playing an event list, we switch to audio memory buffer mode
2711 if (mainw->multitrack) init_jack_audio_buffers(cfile->achans, cfile->arate, exact_preview);
2713 has_audio_buffers = TRUE;
2714 }
2715#endif
2716#ifdef HAVE_PULSE_AUDIO
2717 if (mainw->event_list && !mainw->record && audio_player == AUD_PLAYER_PULSE && mainw->pulsed &&
2719 !(mainw->multitrack && mainw->preview && mainw->multitrack->is_rendering))) {
2720 // if playing an event list, we switch to audio memory buffer mode
2721 if (mainw->multitrack) init_pulse_audio_buffers(cfile->achans, cfile->arate, exact_preview);
2723 has_audio_buffers = TRUE;
2724 }
2725#endif
2726
2727 mainw->abufs_to_fill = 0;
2728 //lives_widget_context_update();
2729 //play until stopped or a stream finishes
2730 do {
2733 mainw->fps_measure = 0;
2734
2735 if (mainw->event_list && !mainw->record) {
2736 if (!pb_start_event) pb_start_event = get_first_event(mainw->event_list);
2737
2738 if (!(mainw->preview && mainw->multitrack && mainw->multitrack->is_rendering))
2740
2741 if (has_audio_buffers) {
2742#ifdef ENABLE_JACK
2743 if (audio_player == AUD_PLAYER_JACK) {
2744 int i;
2745 mainw->write_abuf = 0;
2746
2747 // fill our audio buffers now
2748 // this will also get our effects state
2749
2750 // reset because audio sync may have set it
2751 if (mainw->multitrack) mainw->jackd->abufs[0]->arate = cfile->arate;
2752 else mainw->jackd->abufs[0]->arate = mainw->jackd->sample_out_rate;
2753 fill_abuffer_from(mainw->jackd->abufs[0], mainw->event_list, pb_start_event, exact_preview);
2754 for (i = 1; i < prefs->num_rtaudiobufs; i++) {
2755 // reset because audio sync may have set it
2756 if (mainw->multitrack) mainw->jackd->abufs[i]->arate = cfile->arate;
2757 else mainw->jackd->abufs[i]->arate = mainw->jackd->sample_out_rate;
2758 fill_abuffer_from(mainw->jackd->abufs[i], mainw->event_list, NULL, FALSE);
2759 }
2760
2761 pthread_mutex_lock(&mainw->abuf_mutex);
2762 mainw->jackd->read_abuf = 0;
2763 mainw->abufs_to_fill = 0;
2764 pthread_mutex_unlock(&mainw->abuf_mutex);
2765 if (mainw->event_list)
2766 mainw->jackd->in_use = TRUE;
2767 }
2768#endif
2769#ifdef HAVE_PULSE_AUDIO
2770 if (audio_player == AUD_PLAYER_PULSE) {
2771 int i;
2772 mainw->write_abuf = 0;
2773
2776
2778 if (mainw->multitrack) mainw->pulsed->abufs[0]->arate = cfile->arate;
2779 else mainw->pulsed->abufs[0]->arate = mainw->pulsed->out_arate;
2780
2782 mainw->pulsed->abufs[0]->out_asamps = mainw->pulsed->out_asamps;
2783
2784 fill_abuffer_from(mainw->pulsed->abufs[0], mainw->event_list, pb_start_event, exact_preview);
2785 for (i = 1; i < prefs->num_rtaudiobufs; i++) {
2786 if (mainw->multitrack) mainw->pulsed->abufs[i]->arate = cfile->arate;
2787 else mainw->pulsed->abufs[i]->arate = mainw->pulsed->out_arate;
2788 mainw->pulsed->abufs[i]->out_asamps = mainw->pulsed->out_asamps;
2789 fill_abuffer_from(mainw->pulsed->abufs[i], mainw->event_list, NULL, FALSE);
2790 }
2791
2792 pthread_mutex_lock(&mainw->abuf_mutex);
2793 mainw->pulsed->read_abuf = 0;
2794 mainw->abufs_to_fill = 0;
2795 pthread_mutex_unlock(&mainw->abuf_mutex);
2796 if (mainw->event_list) {
2797 mainw->pulsed->in_use = TRUE;
2798 }
2799 }
2800#endif
2801 }
2802 }
2803
2804 if (!mainw->foreign && !mainw->multitrack)
2806 else
2808
2809 if (!mainw->multitrack || !mainw->multitrack->pb_start_event) {
2811
2812 // reset audio buffers
2813#ifdef ENABLE_JACK
2814 if (audio_player == AUD_PLAYER_JACK && mainw->jackd) {
2815 // must do this before deinit fx
2816 pthread_mutex_lock(&mainw->abuf_mutex);
2817 mainw->jackd->read_abuf = -1;
2818 mainw->jackd->in_use = FALSE;
2819 pthread_mutex_unlock(&mainw->abuf_mutex);
2820 }
2821#endif
2822#ifdef HAVE_PULSE_AUDIO
2823 if (audio_player == AUD_PLAYER_PULSE && mainw->pulsed) {
2824 // must do this before deinit fx
2825 pthread_mutex_lock(&mainw->abuf_mutex);
2826 mainw->pulsed->read_abuf = -1;
2827 mainw->pulsed->in_use = FALSE;
2828 pthread_mutex_unlock(&mainw->abuf_mutex);
2829 }
2830#endif
2831 } else {
2832 // play from middle of mt timeline
2833 cfile->next_event = mainw->multitrack->pb_start_event;
2834
2835 if (!has_audio_buffers) {
2836 // no audio buffering
2837 // get just effects state
2838 get_audio_and_effects_state_at(mainw->multitrack->event_list, mainw->multitrack->pb_start_event, 0,
2840 }
2841
2843
2844 // reset audio read buffers
2845#ifdef ENABLE_JACK
2846 if (audio_player == AUD_PLAYER_JACK && mainw->jackd) {
2847 // must do this before deinit fx
2848 pthread_mutex_lock(&mainw->abuf_mutex);
2849 mainw->jackd->read_abuf = -1;
2850 mainw->jackd->in_use = FALSE;
2851 pthread_mutex_unlock(&mainw->abuf_mutex);
2852 }
2853#endif
2854#ifdef HAVE_PULSE_AUDIO
2855 if (audio_player == AUD_PLAYER_PULSE && mainw->pulsed) {
2856 // must do this before deinit fx
2857 pthread_mutex_lock(&mainw->abuf_mutex);
2858 mainw->pulsed->read_abuf = -1;
2859 mainw->pulsed->in_use = FALSE;
2860 pthread_mutex_unlock(&mainw->abuf_mutex);
2861 }
2862#endif
2863 // realtime effects off (for multitrack and event_list preview)
2865
2866 cfile->next_event = NULL;
2867
2868 if (!(mainw->preview && mainw->multitrack && mainw->multitrack->is_rendering))
2870
2871 // multitrack loop - go back to loop start position unless external transport moved us
2872 if (mainw->scratch == SCRATCH_NONE) {
2873 mainw->multitrack->pb_start_event = mainw->multitrack->pb_loop_event;
2874 }
2875 }
2876 mainw->effort = 0;
2877 if (mainw->multitrack) pb_start_event = mainw->multitrack->pb_start_event;
2878 } while (mainw->multitrack && (mainw->loop_cont || mainw->scratch != SCRATCH_NONE) &&
2880 }
2881
2882 mainw->osc_block = TRUE;
2883 mainw->rte_textparm = NULL;
2884 mainw->playing_file = -1;
2885 mainw->abufs_to_fill = 0;
2886
2887 if (!mainw->foreign) {
2889 if (prefs->allow_easing && !mainw->multitrack) {
2890 // any effects which were "easing out" should be deinited now
2892 }
2893 }
2894
2895 if (mainw->ext_playback) {
2896#ifndef IS_MINGW
2899#else
2902#endif
2903 }
2904
2905 // play completed
2906 if (prefs->show_player_stats) {
2907 if (mainw->fps_measure > 0) {
2908 fps_med = (double)mainw->fps_measure / ((double)lives_get_relative_ticks(mainw->origsecs, mainw->orignsecs)
2910 }
2911 }
2913 mainw->osc_auto = 0;
2914
2916 if (prefs->show_msg_area) {
2918 }
2919
2921 if ((mainw->current_file == current_file) && CURRENT_CLIP_IS_VALID) {
2922 cfile->pointer_time = pointer_time;
2923 cfile->real_pointer_time = real_pointer_time;
2924 }
2925
2926#ifdef ENABLE_JACK
2927 if (audio_player == AUD_PLAYER_JACK && (mainw->jackd || mainw->jackd_read)) {
2928 if (mainw->jackd_read || mainw->aud_rec_fd != -1)
2929 jack_rec_audio_end(!prefs->perm_audio_reader, TRUE);
2930
2931 if (mainw->jackd_read) {
2932 mainw->jackd_read->in_use = FALSE;
2933 }
2934
2935 // send jack transport stop
2936 if (!mainw->preview && !mainw->foreign) jack_pb_stop();
2937
2938 // tell jack client to close audio file
2939 if (mainw->jackd && mainw->jackd->playing_file > 0) {
2940 ticks_t timeout = 0;
2943 while ((timeout = lives_alarm_check(alarm_handle)) > 0 && jack_get_msgq(mainw->jackd)) {
2944 sched_yield(); // wait for seek
2945 lives_usleep(prefs->sleep_time);
2946 }
2947 lives_alarm_clear(alarm_handle);
2948 }
2950 jack_message.command = ASERVER_CMD_FILE_CLOSE;
2951 jack_message.data = NULL;
2952 jack_message.next = NULL;
2953 mainw->jackd->msgq = &jack_message;
2954 if (timeout == 0) handle_audio_timeout();
2955 else {
2956 while (mainw->jackd->playing_file > -1) {
2957 sched_yield();
2958 lives_usleep(prefs->sleep_time);
2959 }
2960 }
2961 }
2962 } else {
2963#endif
2964#ifdef HAVE_PULSE_AUDIO
2965 if (audio_player == AUD_PLAYER_PULSE && (mainw->pulsed || mainw->pulsed_read)) {
2966 if (mainw->pulsed_read || mainw->aud_rec_fd != -1)
2967 pulse_rec_audio_end(!prefs->perm_audio_reader, TRUE);
2968
2969 if (mainw->pulsed_read) {
2970 mainw->pulsed_read->in_use = FALSE;
2971 pulse_driver_cork(mainw->pulsed_read);
2972 }
2973
2974 // tell pulse client to close audio file
2975 if (mainw->pulsed) {
2976 if (mainw->pulsed->playing_file > 0 || mainw->pulsed->fd > 0) {
2977 ticks_t timeout = 0;
2980 while ((timeout = lives_alarm_check(alarm_handle)) > 0 && pulse_get_msgq(mainw->pulsed)) {
2981 sched_yield(); // wait for seek
2982 lives_usleep(prefs->sleep_time);
2983 }
2984 lives_alarm_clear(alarm_handle);
2985 }
2987 pulse_message.command = ASERVER_CMD_FILE_CLOSE;
2988 pulse_message.data = NULL;
2989 pulse_message.next = NULL;
2990 mainw->pulsed->msgq = &pulse_message;
2991 if (timeout == 0) {
2993 mainw->pulsed->playing_file = -1;
2994 mainw->pulsed->fd = -1;
2995 } else {
2996 while (mainw->pulsed->playing_file > -1 || mainw->pulsed->fd > 0) {
2997 sched_yield();
2998 lives_usleep(prefs->sleep_time);
2999 }
3000 pulse_driver_cork(mainw->pulsed);
3001 }
3002 } else {
3003 pulse_driver_cork(mainw->pulsed);
3004 }
3005 }
3006 } else {
3007#endif
3008 if (!is_realtime_aplayer(audio_player) && stopcom) {
3009 // kill sound (if still playing)
3010 lives_system(stopcom, TRUE);
3011 mainw->aud_file_to_kill = -1;
3012 lives_free(stopcom);
3013 }
3014#ifdef ENABLE_JACK
3015 }
3016#endif
3017#ifdef HAVE_PULSE_AUDIO
3018 }
3019#endif
3020
3021 lives_freep((void **)&com);
3022 lives_freep((void **)&mainw->urgency_msg);
3023 mainw->actual_frame = 0;
3024
3026
3027 if (mainw->new_clip != -1) {
3029 mainw->new_clip = -1;
3030 }
3031
3032 // stop the audio players
3033#ifdef ENABLE_JACK
3034 if (audio_player == AUD_PLAYER_JACK && mainw->jackd) {
3035 mainw->jackd->in_use = FALSE;
3036 }
3037#endif
3038#ifdef HAVE_PULSE_AUDIO
3039 if (audio_player == AUD_PLAYER_PULSE && mainw->pulsed) {
3040 mainw->pulsed->in_use = FALSE;
3041 }
3042#endif
3043
3045 if (audio_player == AUD_PLAYER_JACK
3049
3050 // terminate autolives if running
3051 lives_check_menu_item_set_active(LIVES_CHECK_MENU_ITEM(mainw->autolives), FALSE);
3052
3053 // PLAY FINISHED...
3054
3055 // allow this to fail - not all sub-commands may be present
3056 if (prefs->stop_screensaver) {
3057#ifdef GDK_WINDOWING_X11
3058 com = lives_strdup("xset s on 2>/dev/null; xset +dpms 2>/dev/null ;");
3059
3060 if (capable->has_gconftool_2) {
3061 char *xnew = lives_strdup(" gconftool-2 --set --type bool /apps/gnome-screensaver/idle_activation_enabled "
3062 "true 2>/dev/null ;");
3063 tmp = lives_strconcat(com, xnew, NULL);
3064 lives_free(com);
3065 lives_free(xnew);
3066 com = tmp;
3067 }
3068 if (capable->has_xdg_screensaver && awinid != -1) {
3069 char *xnew = lives_strdup_printf(" xdg-screensaver resume %"PRIu64" 2>/dev/null ;", awinid);
3070 tmp = lives_strconcat(com, xnew, NULL);
3071 lives_free(com);
3072 lives_free(xnew);
3073 com = tmp;
3074 }
3075#else
3076 if (capable->has_gconftool_2) {
3077 com = lives_strdup("gconftool-2 --set --type bool /apps/gnome-screensaver/idle_activation_enabled true 2>/dev/null ;");
3078 } else com = lives_strdup("");
3079#endif
3080
3081 if (com) {
3082 lives_system(com, TRUE);
3083 lives_free(com);
3084 }
3085 }
3086
3088 lives_toggle_tool_button_set_active(LIVES_TOGGLE_TOOL_BUTTON(mainw->ext_audio_mon), FALSE);
3089
3090 // reset in case audio lock was actioned
3092
3093 // TODO ***: use MIDI output port for this
3095
3096 // we could have started by playing a generator, which could've been closed
3097 if (!mainw->files[current_file]) current_file = mainw->current_file;
3098
3099 if (!is_realtime_aplayer(audio_player)) {
3100 // wait for audio_ended...
3101 if (cfile->achans > 0 && com2) {
3102 wait_for_stop(com2);
3103 mainw->aud_file_to_kill = -1;
3104 }
3105 lives_freep((void **)&com2);
3106 }
3107
3109 cfile->last_play_sequence = mainw->play_sequence;
3110 stfile = lives_build_filename(prefs->workdir, cfile->handle, LIVES_STATUS_FILE_NAME, NULL);
3111 lives_snprintf(cfile->info_file, PATH_MAX, "%s", stfile);
3112 lives_free(stfile);
3113 }
3114
3116 lives_close_buffered(LIVES_POINTER_TO_INT(mainw->files[mainw->scrap_file]->ext_src));
3117 mainw->files[mainw->scrap_file]->ext_src = NULL;
3119 }
3120
3121 if (mainw->foreign) {
3122 // recording from external window capture
3125
3126 cfile->hsize = mainw->pwidth;
3127 cfile->vsize = mainw->pheight;
3128
3130
3132
3133 return;
3134 }
3135
3139 mainw->blend_palette = WEED_PALETTE_END;
3140 mainw->audio_stretch = 1.;
3141
3142 if (!mainw->multitrack) {
3143 if (mainw->faded || mainw->fs) {
3145 }
3146
3148
3150 resize(1.);
3152 lives_frame_set_label(LIVES_FRAME(mainw->playframe), NULL);
3153 }
3154
3155 if (palette->style & STYLE_1) {
3157 }
3158
3159 if (prefs->show_msg_area && !mainw->multitrack) {
3162 }
3163
3169
3170 if (!prefs->hide_framebar && !prefs->hfbwnp) {
3172 }
3173 }
3174
3175 if (!is_realtime_aplayer(audio_player)) mainw->mute = mute;
3176
3178 if (mainw->play_window) {
3179 if (mainw->fs) {
3185 }
3187 }
3190 } else {
3192 if (CURRENT_CLIP_IS_VALID && cfile->is_loaded && cfile->frames > 0 && !mainw->is_rendering &&
3193 (cfile->clip_type != CLIP_TYPE_GENERATOR)) {
3194 if (mainw->preview_controls) {
3196 if (prefs->show_gui) {
3201 //lives_widget_grab_focus(mainw->preview_spinbutton);
3202 }
3203 }
3204 if (mainw->current_file != current_file) {
3205 // now we have to guess how to center the play window
3206 mainw->opwx = mainw->opwy = -1;
3207 mainw->preview_frame = 0;
3208 }
3209 }
3210
3211 if (!mainw->multitrack) {
3212 mainw->playing_file = -2;
3215 mainw->playing_file = -1;
3217
3218 if (!mainw->preview_box) {
3219 // create the preview box that shows frames
3221 }
3222 // and add it to the play window
3227 }
3228
3229 if (mainw->play_window) {
3230 if (prefs->show_playwin) {
3231 lives_window_present(LIVES_WINDOW(mainw->play_window));
3240 lives_window_center(LIVES_WINDOW(mainw->play_window));
3243 // *INDENT-OFF*
3244 }}}}}
3245 // *INDENT-ON*
3246
3248 if (mainw->frame_layer) {
3250 mainw->frame_layer = NULL;
3251 }
3252
3253 if (mainw->lazy) mainw->lazy = lives_idle_add_simple(lazy_startup_checks, NULL);
3254
3255 cliplist = mainw->cliplist;
3256 while (cliplist) {
3257 int i = LIVES_POINTER_TO_INT(cliplist->data);
3261 cliplist = cliplist->next;
3262 }
3263
3264 if (!mainw->foreign) {
3266 }
3267
3268 if (CURRENT_CLIP_IS_VALID) cfile->play_paused = FALSE;
3269
3272 int xcurrent_file = mainw->current_file;
3274 mainw->current_file = xcurrent_file;
3275 }
3276
3278
3280 lives_accel_group_disconnect(LIVES_ACCEL_GROUP(mainw->accel_group), freeze_closure);
3281 lives_accel_group_disconnect(LIVES_ACCEL_GROUP(mainw->accel_group), bg_freeze_closure);
3282
3283 if (needsadone) d_print_done();
3284
3286 if (mainw->frame_layer_preload && mainw->pred_clip != -1) {
3289 }
3290 mainw->frame_layer_preload = NULL;
3291
3292 if (!prefs->vj_mode) {
3294 if (mainw->size_warn) {
3295 if (mainw->size_warn > 0 && mainw->files[mainw->size_warn]) {
3296 char *smsg = lives_strdup_printf(
3297 _("\n\nSome frames in the clip\n%s\nare wrongly sized.\nYou should "
3298 "click on Tools--->Resize All\n"
3299 "and resize all frames to the current size.\n"),
3302 do_error_dialog(smsg);
3304 lives_free(smsg);
3305 }
3306 }
3307 }
3308 mainw->size_warn = 0;
3309
3310 // set processing state again if a previewe finished
3311 // CAUTION !!
3314
3316
3317 // TODO - ????
3318 if (CURRENT_CLIP_IS_VALID && cfile->clip_type == CLIP_TYPE_DISK && cfile->frames == 0 && mainw->record_perf) {
3320 lives_check_menu_item_set_active(LIVES_CHECK_MENU_ITEM(mainw->record_perf), FALSE);
3322 }
3323
3324 // TODO - can this be done earlier ?
3325 if (mainw->cancelled == CANCEL_APP_QUIT) on_quit_activate(NULL, NULL);
3326
3328
3329#ifdef ENABLE_JACK
3330 if (audio_player == AUD_PLAYER_JACK && mainw->jackd) {
3331 ticks_t timeout;
3333 while ((timeout = lives_alarm_check(alarm_handle)) > 0 && jack_get_msgq(mainw->jackd)) {
3334 sched_yield();
3335 lives_usleep(prefs->sleep_time);
3336 }
3337 lives_alarm_clear(alarm_handle);
3338 if (timeout == 0) {
3340 }
3341 if (has_audio_buffers) {
3344 }
3345 }
3346#endif
3347#ifdef HAVE_PULSE_AUDIO
3348 if (audio_player == AUD_PLAYER_PULSE && mainw->pulsed) {
3349 ticks_t timeout;
3351 while ((timeout = lives_alarm_check(alarm_handle)) > 0 && pulse_get_msgq(mainw->pulsed)) {
3352 sched_yield();
3353 lives_usleep(prefs->sleep_time);
3354 }
3355 lives_alarm_clear(alarm_handle);
3356 if (timeout == 0) {
3358 }
3359
3360 if (has_audio_buffers) {
3363 }
3364 }
3365#endif
3366
3367 if (prefs->show_player_stats) {
3368 if (mainw->fps_measure > 0) {
3369 d_print(_("Average FPS was %.4f (%d frames in clock time of %f)\n"), fps_med, mainw->fps_measure,
3371 }
3372 }
3373
3374 if (THREADVAR(bad_aud_file)) {
3376 do_write_failed_error_s(THREADVAR(bad_aud_file), NULL);
3377 lives_freep((void **)&THREADVAR(bad_aud_file));
3378 }
3379
3380 if (mainw->new_vpp) {
3381 mainw->noswitch = FALSE;
3383 mainw->new_vpp = NULL;
3384 mainw->noswitch = TRUE;
3385 }
3386
3390 }
3391
3392 if (!mainw->preview && CURRENT_CLIP_IS_VALID && cfile->clip_type == CLIP_TYPE_GENERATOR) {
3393 mainw->osc_block = TRUE;
3394 weed_generator_end((weed_plant_t *)cfile->ext_src);
3396 } else {
3397 if (mainw->current_file > -1) {
3398 if (mainw->toy_type == LIVES_TOY_MAD_FRAMES && !cfile->opening) {
3399 showclipimgs();
3400 if (!mainw->multitrack)
3402 }
3403 }
3404 }
3405
3407 if (!mainw->multitrack) {
3408 lives_ce_update_timeline(0, cfile->real_pointer_time);
3409 mainw->ptrtime = cfile->real_pointer_time;
3412 }
3413 }
3414
3415 if (!mainw->multitrack) {
3416 //lives_table_set_column_homogeneous(LIVES_TABLE(mainw->pf_grid), FALSE);
3417 }
3418
3419 if (prefs->show_gui && ((mainw->multitrack && mainw->double_size) ||
3422 //if (prefs->gui_monitor == 0) lives_window_move(LIVES_WINDOW(LIVES_MAIN_WINDOW_WIDGET), 0, 0);
3423 if (prefs->open_maximised)
3426 }
3427
3428 if (!mainw->preview && (mainw->current_file == -1 || (CURRENT_CLIP_IS_VALID && !cfile->opening))) {
3429 sensitize();
3430 }
3431
3432 if (CURRENT_CLIP_IS_VALID && cfile->opening) {
3435 lives_widget_set_sensitive(mainw->loop_video, cfile->achans > 0 && cfile->frames > 0);
3436 }
3437
3441 }
3442
3444
3445 if (!mainw->multitrack) {
3447 if (prefs->hfbwnp) {
3449 }
3452 }
3453
3455
3457
3458 lives_menu_item_set_accel_path(LIVES_MENU_ITEM(mainw->quit), LIVES_ACCEL_PATH_QUIT);
3459
3461 set_main_title(cfile->name, 0);
3462
3463 if (!mainw->multitrack && !mainw->foreign && CURRENT_CLIP_IS_VALID && (!cfile->opening ||
3464 cfile->clip_type == CLIP_TYPE_FILE)) {
3465 showclipimgs();
3467 }
3468
3469 if (prefs->show_msg_area) {
3470 if (mainw->idlemax == 0) {
3471 lives_idle_add_simple(resize_message_area, NULL);
3472 }
3474 }
3475
3477
3479 if (mainw->record) {
3480 lives_idle_add_simple(render_choice_idle, LIVES_INT_TO_POINTER(FALSE));
3481 }
3482
3484
3486
3488 mainw->noswitch = FALSE;
3489}
3490
3491
3498int close_temp_handle(int new_clip) {
3499 char *com, *permitname;
3500 int clipno = mainw->current_file;
3501
3502 if (!IS_VALID_CLIP(new_clip)) new_clip = -1;
3503 if (!IS_VALID_CLIP(clipno)) {
3504 mainw->current_file = new_clip;
3505 return new_clip;
3506 }
3507 if (cfile->clip_type != CLIP_TYPE_TEMP
3509 close_current_file(new_clip);
3510 }
3511
3512 // as a safety feature we create a special file which allows the back end to delete the directory
3513 permitname = lives_build_filename(prefs->workdir, cfile->handle, TEMPFILE_MARKER "." LIVES_FILE_EXT_TMP, NULL);
3514 lives_touch(permitname);
3515 lives_free(permitname);
3516
3517 com = lives_strdup_printf("%s close \"%s\"", prefs->backend, cfile->handle);
3518 lives_system(com, TRUE);
3519 lives_free(com);
3520 lives_freep((void **)&mainw->files[clipno]);
3521
3522 mainw->current_file = new_clip;
3523
3524 if (mainw->first_free_file == ALL_USED || mainw->first_free_file > clipno)
3525 mainw->first_free_file = clipno;
3526 return new_clip;
3527}
3528
3529
3534static int get_next_free_file(void) {
3535 int idx = mainw->first_free_file++;
3539 }
3540 return idx;
3541}
3542
3543
3571boolean get_temp_handle(int index) {
3572 boolean is_unique, create = FALSE;
3573
3575 break_me("temp clip in temp clip !!");
3576 return TRUE;
3577 }
3578
3579 if (index < -1 || index > MAX_FILES) {
3580 char *msg = lives_strdup_printf("Attempt to create invalid new temp clip %d\n", index);
3581 LIVES_WARN(msg);
3582 lives_free(msg);
3583 return FALSE;
3584 }
3585
3586 if (index == -1) {
3587 if (mainw->first_free_file == ALL_USED) {
3589 return FALSE;
3590 }
3591 create = TRUE;
3592 index = mainw->first_free_file;
3593 get_next_free_file();
3594 }
3595
3596 do {
3597 is_unique = TRUE;
3598
3599 // get handle from info file, the first time we will also malloc a
3600 // new "file" struct here and create a directory in prefs->workdir
3601 if (!get_handle_from_info_file(index)) {
3602 lives_freep((void **)&mainw->files[index]);
3603 if (mainw->first_free_file == ALL_USED || index < mainw->first_free_file)
3604 mainw->first_free_file = index;
3605 return FALSE;
3606 }
3607
3608 if (*mainw->set_name) {
3609 char *setclipdir = CLIPDIR(cfile->handle);
3610 if (lives_file_test(setclipdir, LIVES_FILE_TEST_IS_DIR)) is_unique = FALSE;
3611 lives_free(setclipdir);
3612 }
3613 } while (!is_unique);
3614
3615 mainw->current_file = index;
3616
3617 if (create) {
3618 // create a marker file in directory, else we will be barred from
3619 // removing it
3620 char *canremove = lives_build_filename(prefs->workdir, cfile->handle,
3622 lives_touch(canremove);
3623 lives_free(canremove);
3624 // fill with default values
3625 create_cfile(index, cfile->handle, FALSE);
3626 cfile->clip_type = CLIP_TYPE_TEMP;
3627 }
3628 return TRUE;
3629}
3630
3631
3656lives_clip_t *create_cfile(int new_file, const char *handle, boolean is_loaded) {
3657 lives_clip_t *sfile;
3658 char *stfile;
3659
3660 if (new_file == -1) {
3661 // if new_file == -1, we are going to create a new clip
3662 new_file = mainw->first_free_file;
3663 if (new_file == -1) {
3665 return NULL;
3666 }
3667
3668 mainw->current_file = new_file;
3669 get_next_free_file();
3670
3671 if (new_file < 0 || new_file > MAX_FILES || IS_VALID_CLIP(new_file)) {
3672 char *msg = lives_strdup_printf("Attempt to create invalid new clip %d\n", new_file);
3673 LIVES_WARN(msg);
3674 lives_free(msg);
3675 return NULL;
3676 }
3677
3678 if (!handle) {
3679 // if handle is NULL, we create a new clip on disk, switch to it
3680 // (unused)
3681 if (!get_handle_from_info_file(new_file)) return NULL;
3682 sfile = mainw->files[new_file];
3683 } else {
3684 // else just create the in-memory part and set the handle
3685 sfile = mainw->files[new_file] = (lives_clip_t *)(lives_calloc(1, sizeof(lives_clip_t)));
3686 if (!sfile) return NULL;
3687 lives_snprintf(sfile->handle, 256, "%s", handle);
3688 }
3689 }
3690
3691 mainw->current_file = new_file;
3692
3693 cfile->is_loaded = is_loaded;
3694
3695 // any cfile (clip) initialisation goes in here
3696 lives_memcpy((void *)&cfile->binfmt_check.chars, "LiVESXXX", 8);
3697 cfile->binfmt_version.num = make_version_hash(LiVES_VERSION);
3698 cfile->binfmt_bytes.size = (size_t)((void *)&cfile->binfmt_end - (void *)cfile);
3699 cfile->menuentry = NULL;
3700 cfile->start = cfile->end = 0;
3701 cfile->old_frames = cfile->opening_frames = cfile->frames = 0;
3702 lives_snprintf(cfile->type, 40, "%s", _("Unknown"));
3703 cfile->f_size = 0l;
3704 cfile->achans = 0;
3705 cfile->arate = 0;
3706 cfile->arps = 0;
3707 cfile->afilesize = 0l;
3708 cfile->asampsize = 0;
3709 cfile->adirection = LIVES_DIRECTION_FORWARD;
3710 cfile->undoable = FALSE;
3711 cfile->redoable = FALSE;
3712 cfile->changed = FALSE;
3713 cfile->was_in_set = FALSE;
3714 cfile->hsize = cfile->vsize = cfile->ohsize = cfile->ovsize = 0;
3715 cfile->fps = cfile->pb_fps = prefs->default_fps;
3716 cfile->resample_events = NULL;
3717 cfile->insert_start = cfile->insert_end = 0;
3718 cfile->is_untitled = TRUE;
3719 cfile->was_renamed = FALSE;
3720 cfile->undo_action = UNDO_NONE;
3721 cfile->opening_audio = cfile->opening = cfile->opening_only_audio = FALSE;
3722 cfile->pointer_time = 0.;
3723 cfile->real_pointer_time = 0.;
3724 cfile->restoring = cfile->opening_loc = cfile->nopreview = FALSE;
3725 cfile->video_time = cfile->laudio_time = cfile->raudio_time = 0.;
3726 cfile->freeze_fps = 0.;
3727 cfile->last_vframe_played = 0;
3728 cfile->frameno = cfile->last_frameno = cfile->saved_frameno = 1;
3729 cfile->progress_start = cfile->progress_end = 0;
3730 cfile->play_paused = cfile->nokeep = FALSE;
3731 cfile->undo_start = cfile->undo_end = 0;
3732 cfile->ext_src = NULL;
3733 cfile->ext_src_type = LIVES_EXT_SRC_NONE;
3734 cfile->clip_type = CLIP_TYPE_DISK;
3735 cfile->ratio_fps = FALSE;
3736 cfile->aseek_pos = 0;
3737 cfile->unique_id = gen_unique_id();
3738 cfile->layout_map = NULL;
3739 cfile->frame_index = cfile->frame_index_back = NULL;
3740 cfile->fx_frame_pump = 0;
3741 cfile->pumper = NULL;
3742 cfile->stored_layout_frame = 0;
3743 cfile->stored_layout_audio = 0.;
3744 cfile->stored_layout_fps = 0.;
3745 cfile->stored_layout_idx = -1;
3746 cfile->interlace = LIVES_INTERLACE_NONE;
3747 cfile->subt = NULL;
3748 cfile->no_proc_sys_errors = cfile->no_proc_read_errors = cfile->no_proc_write_errors = FALSE;
3749 cfile->keep_without_preview = FALSE;
3750 cfile->cb_src = -1;
3751 cfile->needs_update = cfile->needs_silent_update = FALSE;
3752 cfile->audio_waveform = NULL;
3753 cfile->md5sum[0] = 0;
3754 cfile->gamma_type = WEED_GAMMA_SRGB;
3755 cfile->last_play_sequence = 0;
3756 cfile->tcache_dubious_from = 0;
3757 cfile->tcache_height = 0;
3758 cfile->tcache = NULL;
3759 cfile->checked = FALSE;
3760 cfile->has_binfmt = TRUE;
3761
3762 if (!strcmp(prefs->image_ext, LIVES_FILE_EXT_JPG)) cfile->img_type = IMG_TYPE_JPEG;
3763 else cfile->img_type = IMG_TYPE_PNG;
3764
3765 cfile->bpp = (cfile->img_type == IMG_TYPE_JPEG) ? 24 : 32;
3766 cfile->deinterlace = FALSE;
3767
3768 cfile->play_paused = FALSE;
3769 cfile->header_version = LIVES_CLIP_HEADER_VERSION;
3770
3771 cfile->event_list = cfile->event_list_back = NULL;
3772 cfile->next_event = NULL;
3773 cfile->vol = 1.;
3774
3775 lives_memset(cfile->name, 0, 1);
3776 lives_memset(cfile->mime_type, 0, 1);
3777 lives_memset(cfile->file_name, 0, 1);
3778 lives_memset(cfile->save_file_name, 0, 1);
3779
3780 lives_memset(cfile->comment, 0, 1);
3781 lives_memset(cfile->author, 0, 1);
3782 lives_memset(cfile->title, 0, 1);
3783 lives_memset(cfile->keywords, 0, 1);
3784
3785 cfile->signed_endian = AFORM_UNKNOWN;
3786 lives_snprintf(cfile->undo_text, 32, "%s", _("_Undo"));
3787 lives_snprintf(cfile->redo_text, 32, "%s", _("_Redo"));
3788
3789 stfile = lives_build_filename(prefs->workdir, cfile->handle, LIVES_STATUS_FILE_NAME, NULL);
3790
3791 lives_snprintf(cfile->info_file, PATH_MAX, "%s", stfile);
3792 lives_free(stfile);
3793
3794 // backwards compat.
3795 cfile->checked_for_old_header = FALSE;
3796 cfile->has_old_header = FALSE;
3797
3798 return cfile;
3799}
3800
3801
3803 // utility function to get clip name
3804 return lives_strdup_printf(_("Untitled%d"), number);
3805}
3806
3807
3808int create_nullvideo_clip(const char *handle) {
3809 // create a file with no video, just produces blank frames
3810 // may be used to playback with audio, for testign etc.
3811 int new_file;
3812 int current_file = mainw->current_file;
3813 create_cfile(-1, handle, TRUE);
3814 new_file = mainw->current_file;
3815 mainw->current_file = current_file;
3817 return new_file;
3818}
3819
3820
3821boolean get_new_handle(int index, const char *name) {
3822 // here is where we first initialize for the clipboard
3823 // and for paste_as_new, and restore, etc.
3824 // pass in name as NULL or "" and it will be set with an untitled number
3825
3826 // this function *does not* change mainw->current_file (except briefly), or add to the menu
3827 // or update mainw->clips_available
3828
3829 // differences from get_temp_handle:
3830 // - here we dont't switch clips;
3831 // - index is normally passed in rather than generated (pulled from next_free_file) - this allows
3832 // the caller to know the index number and do preconfig before calling
3833 // - we set name and file_name from the name parameter, or if name is NULL, we set an untitled name
3834 // and increment mainw->untitled_number
3835 // - the clip should be closed using close_current_file() instead of close_temp_handle()
3836
3837 char *xname;
3838
3839 int current_file = mainw->current_file;
3840
3841 // if TRUE, changes mainw->current_file (and hence cfile)
3842 if (!get_temp_handle(index)) return FALSE;
3843
3844 // setup would have been done already in get_temp_handle()
3845 if (index == -1) index = mainw->current_file;
3846
3847 else create_cfile(index, cfile->handle, FALSE);
3848
3849 // note : don't need to update first_free_file for the clipboard
3850 // because we used index 0 instead of a free index number
3851 if (index != 0) {
3852 get_next_free_file();
3853 }
3854
3855 if (!name || !*name) {
3856 cfile->is_untitled = TRUE;
3858 } else xname = lives_strdup(name);
3859
3860 lives_snprintf(cfile->file_name, PATH_MAX, "%s", xname);
3861 lives_snprintf(cfile->name, CLIP_NAME_MAXLEN, "%s", xname);
3862
3863 mainw->current_file = current_file;
3864
3865 lives_free(xname);
3866 return TRUE;
3867}
3868
3869
3870boolean add_file_info(const char *check_handle, boolean aud_only) {
3871 // file information has been retrieved, set struct cfile with details
3872 // contained in mainw->msg. We do this twice, once before opening the file, once again after.
3873 // The first time, frames and afilesize may not be correct.
3874 char *mesg, *mesg1;
3875 char **array;
3876 char *test_fps_string1;
3877 char *test_fps_string2;
3878
3879 if (aud_only && !mainw->save_with_sound) {
3880 cfile->arps = cfile->arate = cfile->achans = cfile->asampsize = 0;
3881 cfile->afilesize = 0l;
3882 return TRUE;
3883 }
3884
3885 if (!strcmp(mainw->msg, "killed")) {
3886 char *com;
3887 // user pressed "enough"
3888 // just in case last frame is damaged, we delete it (physically, otherwise it will get dragged in when the file is opened)
3889 if (!cfile->ext_src) {
3890 cfile->frames = get_frame_count(mainw->current_file, cfile->opening_frames);
3891 if (cfile->frames > 1) {
3892 com = lives_strdup_printf("%s cut \"%s\" %d %d %d %d \"%s\" %.3f %d %d %d",
3893 prefs->backend, cfile->handle, cfile->frames, cfile->frames,
3894 FALSE, cfile->frames, get_image_ext_for_type(cfile->img_type),
3895 0., 0, 0, 0);
3896 lives_system(com, FALSE);
3897 lives_free(com);
3898 cfile->frames--;
3899 }
3900 }
3901
3902 // commit audio
3904 lives_rm(cfile->info_file);
3905
3906 com = lives_strdup_printf("%s commit_audio \"%s\" 1", prefs->backend, cfile->handle);
3907 lives_system(com, TRUE);
3908 lives_free(com);
3909
3911
3913 d_print_enough(cfile->frames);
3914
3915 if (prefs->auto_trim_audio) {
3916 if (cfile->laudio_time > cfile->video_time) {
3917 d_print(_("Auto trimming %.2f seconds of audio at end..."), cfile->laudio_time - cfile->video_time);
3918 if (on_trim_audio_activate(NULL, LIVES_INT_TO_POINTER(0))) d_print_done();
3919 else d_print("\n");
3920 cfile->changed = FALSE;
3921 }
3922 }
3923 } else {
3924 if (check_handle) {
3925 int npieces = get_token_count(mainw->msg, '|');
3926 if (npieces < 2) return FALSE;
3927
3928 array = lives_strsplit(mainw->msg, "|", npieces);
3929
3930 if (!strcmp(array[0], "error")) {
3931 if (npieces >= 3) {
3932 mesg = lives_strdup_printf(_("\nAn error occurred doing\n%s\n"), array[2]);
3933 LIVES_ERROR(array[2]);
3934 } else mesg = (_("\nAn error occurred opening the file\n"));
3936 do_error_dialog(mesg);
3938 lives_free(mesg);
3939 lives_strfreev(array);
3940 return FALSE;
3941 }
3942
3943 // sanity check handle against status file
3944 // (this should never happen...)
3945 if (strcmp(check_handle, array[1])) {
3946 LIVES_ERROR("Handle!=statusfile !");
3947 mesg = lives_strdup_printf(_("\nError getting file info for clip %s.\nBad things may happen with this clip.\n"),
3948 check_handle);
3950 do_error_dialog(mesg);
3952 lives_free(mesg);
3953 lives_strfreev(array);
3954 return FALSE;
3955 }
3956
3957 cfile->arps = cfile->arate = atoi(array[9]);
3958 cfile->achans = atoi(array[10]);
3959 cfile->asampsize = atoi(array[11]);
3960 cfile->signed_endian = get_signed_endian(atoi(array[12]), atoi(array[13]));
3961 cfile->afilesize = strtol(array[14], NULL, 10);
3962 if (aud_only) {
3963 lives_strfreev(array);
3964 return TRUE;
3965 }
3966
3967 cfile->frames = atoi(array[2]);
3968 if (aud_only) {
3969 lives_strfreev(array);
3970 return TRUE;
3971 }
3972 lives_snprintf(cfile->type, 40, "%s", array[3]);
3973 cfile->hsize = atoi(array[4]);
3974 cfile->vsize = atoi(array[5]);
3975 cfile->bpp = atoi(array[6]);
3976 cfile->pb_fps = cfile->fps = lives_strtod(array[7], NULL);
3977 cfile->f_size = strtol(array[8], NULL, 10);
3978
3979 if (npieces > 15 && array[15]) {
3980 if (prefs->btgamma) {
3981 if (!strcmp(array[15], "bt709")) cfile->gamma_type = WEED_GAMMA_BT709;
3982 }
3983 }
3984
3985 if (!*cfile->title && npieces > 16 && array[16]) {
3986 lives_snprintf(cfile->title, 1024, "%s", lives_strstrip(array[16]));
3987 }
3988 if (!*cfile->author && npieces > 17 && array[17]) {
3989 lives_snprintf(cfile->author, 1024, "%s", lives_strstrip(array[17]));
3990 }
3991 if (!*cfile->comment && npieces > 18 && array[18]) {
3992 lives_snprintf(cfile->comment, 1024, "%s", lives_strstrip(array[18]));
3993 }
3994
3995 lives_strfreev(array);
3996 }
3997 }
3998
3999 cfile->video_time = 0;
4000
4001 test_fps_string1 = lives_strdup_printf("%.3f00000", cfile->fps);
4002 test_fps_string2 = lives_strdup_printf("%.8f", cfile->fps);
4003
4004 if (strcmp(test_fps_string1, test_fps_string2)) {
4005 cfile->ratio_fps = TRUE;
4006 } else {
4007 cfile->ratio_fps = FALSE;
4008 }
4009 lives_free(test_fps_string1);
4010 lives_free(test_fps_string2);
4011
4012 if (!mainw->save_with_sound) {
4013 cfile->arps = cfile->arate = cfile->achans = cfile->asampsize = 0;
4014 cfile->afilesize = 0l;
4015 }
4016
4017 if (cfile->frames <= 0) {
4018 if (cfile->afilesize == 0l && cfile->is_loaded) {
4019 // we got no video or audio...
4020 return FALSE;
4021 }
4022 cfile->start = cfile->end = cfile->undo_start = cfile->undo_end = 0;
4023 } else {
4024 // start with all selected
4025 cfile->start = 1;
4026 cfile->end = cfile->frames;
4027 cfile->undo_start = cfile->start;
4028 cfile->undo_end = cfile->end;
4029 }
4030
4031 cfile->orig_file_name = TRUE;
4032 cfile->is_untitled = FALSE;
4033
4034 // some files give us silly frame rates, even single frames...
4035 // fps of 1000. is used for some streams (i.e. play each frame as it is received)
4036 if (cfile->fps == 0. || cfile->fps == 1000. || (cfile->frames < 2 && cfile->is_loaded)) {
4037
4038 if ((cfile->afilesize * cfile->asampsize * cfile->arate * cfile->achans == 0) || cfile->frames < 2) {
4039 if (cfile->frames != 1) {
4040 d_print(_("\nPlayback speed not found or invalid ! Using default fps of %.3f fps. \n"
4041 "Default can be set in Tools | Preferences | Misc.\n"),
4043 }
4044 cfile->pb_fps = cfile->fps = prefs->default_fps;
4045 } else {
4046 cfile->laudio_time = cfile->raudio_time = cfile->afilesize / cfile->asampsize * 8. / cfile->arate / cfile->achans;
4047 cfile->pb_fps = cfile->fps = 1.*(int)(cfile->frames / cfile->laudio_time);
4048 if (cfile->fps > FPS_MAX || cfile->fps < 1.) {
4049 cfile->pb_fps = cfile->fps = prefs->default_fps;
4050 }
4051 d_print(_("Playback speed was adjusted to %.3f frames per second to fit audio.\n"), cfile->fps);
4052 }
4053 }
4054
4055 cfile->video_time = (double)cfile->frames / cfile->fps;
4056
4057 if (cfile->opening) return TRUE;
4058
4059 if ((!strcmp(cfile->type, LIVES_IMAGE_TYPE_JPEG) || !strcmp(cfile->type, LIVES_IMAGE_TYPE_PNG))) {
4060 mesg = (_("Image format detected"));
4061 d_print(mesg);
4062 lives_free(mesg);
4063 return TRUE;
4064 }
4065
4066 if (cfile->bpp == 256) {
4067 mesg1 = lives_strdup_printf(_("Frames=%d type=%s size=%dx%d *bpp=Greyscale* fps=%.3f\nAudio:"), cfile->frames,
4068 cfile->type, cfile->hsize, cfile->vsize, cfile->fps);
4069 } else {
4070 if (cfile->bpp != 32) cfile->bpp = 24; // assume RGB24 *** TODO - check
4071 mesg1 = lives_strdup_printf(_("Frames=%d type=%s size=%dx%d bpp=%d fps=%.3f\nAudio:"), cfile->frames,
4072 cfile->type, cfile->hsize, cfile->vsize, cfile->bpp, cfile->fps);
4073 }
4074
4075 if (cfile->achans == 0) {
4076 mesg = lives_strdup_printf(_("%s none\n"), mesg1);
4077 } else {
4078 mesg = lives_strdup_printf(P_("%s %d Hz %d channel %d bps\n", "%s %d Hz %d channels %d bps\n", cfile->achans),
4079 mesg1, cfile->arate, cfile->achans, cfile->asampsize);
4080 }
4081 d_print(mesg);
4082 lives_free(mesg1);
4083 lives_free(mesg);
4084
4085 // get the author,title,comments
4086 if (*cfile->author) {
4087 d_print(_(" - Author: %s\n"), cfile->author);
4088 }
4089 if (*cfile->title) {
4090 d_print(_(" - Title: %s\n"), cfile->title);
4091 }
4092 if (*cfile->comment) {
4093 d_print(_(" - Comment: %s\n"), cfile->comment);
4094 }
4095
4096 return TRUE;
4097}
4098
4099
4100boolean save_file_comments(int fileno) {
4101 // save the comments etc for smogrify
4102 int retval;
4103 int comment_fd;
4104 char *comment_file = lives_strdup_printf("%s/%s/.comment", prefs->workdir, cfile->handle);
4105 lives_clip_t *sfile = mainw->files[fileno];
4106
4107 lives_rm(comment_file);
4108
4109 do {
4110 retval = 0;
4111 comment_fd = creat(comment_file, S_IRUSR | S_IWUSR);
4112 if (comment_fd < 0) {
4113 THREADVAR(write_failed) = TRUE;
4114 retval = do_write_failed_error_s_with_retry(comment_file, lives_strerror(errno));
4115 } else {
4116 THREADVAR(write_failed) = FALSE;
4117 lives_write(comment_fd, sfile->title, strlen(sfile->title), TRUE);
4118 lives_write(comment_fd, "||%", 3, TRUE);
4119 lives_write(comment_fd, sfile->author, strlen(sfile->author), TRUE);
4120 lives_write(comment_fd, "||%", 3, TRUE);
4121 lives_write(comment_fd, sfile->comment, strlen(sfile->comment), TRUE);
4122
4123 close(comment_fd);
4124
4125 if (THREADVAR(write_failed)) {
4126 retval = do_write_failed_error_s_with_retry(comment_file, NULL);
4127 }
4128 }
4129 } while (retval == LIVES_RESPONSE_RETRY);
4130
4131 lives_free(comment_file);
4132
4133 if (THREADVAR(write_failed)) return FALSE;
4134
4135 return TRUE;
4136}
4137
4138
4139void wait_for_stop(const char *stop_command) {
4140 FILE *infofile;
4141
4142 // only used for audio player mplayer or audio player sox
4143
4144# define SECOND_STOP_TIME 0.1
4145# define STOP_GIVE_UP_TIME 1.0
4146
4147 double time_waited = 0.;
4148 boolean sent_second_stop = FALSE;
4149
4150 // send another stop if necessary
4151 while (!(infofile = fopen(cfile->info_file, "r"))) {
4153 lives_usleep(prefs->sleep_time);
4154 time_waited += 1000000. / prefs->sleep_time;
4155 if (time_waited > SECOND_STOP_TIME && !sent_second_stop) {
4156 lives_system(stop_command, TRUE);
4157 sent_second_stop = TRUE;
4158 }
4159
4160 if (time_waited > STOP_GIVE_UP_TIME) {
4161 // give up waiting, but send a last try...
4162 lives_system(stop_command, TRUE);
4163 break;
4164 }
4165 }
4166 if (infofile) fclose(infofile);
4167}
4168
4169
4170boolean save_frame_inner(int clip, int frame, const char *file_name, int width, int height, boolean from_osc) {
4171 // save 1 frame as an image
4172 // width==-1, height==-1 to use "natural" values
4173 LiVESResponseType resp;
4174 lives_clip_t *sfile = mainw->files[clip];
4175 char full_file_name[PATH_MAX];
4176 char *com, *tmp;
4177
4178 boolean allow_over = FALSE;
4179
4180 if (!from_osc && strrchr(file_name, '.') == NULL) {
4181 lives_snprintf(full_file_name, PATH_MAX, "%s.%s", file_name,
4183 } else {
4184 lives_snprintf(full_file_name, PATH_MAX, "%s", file_name);
4185 if (!allow_over) allow_over = TRUE;
4186 }
4187
4188 // TODO - allow overwriting in sandbox
4189 if (from_osc && lives_file_test(full_file_name, LIVES_FILE_TEST_EXISTS)) return FALSE;
4190
4191 tmp = lives_filename_from_utf8(full_file_name, -1, NULL, NULL, NULL);
4192
4193 if (!mainw->multitrack) {
4194 d_print(_("Saving frame %d as %s..."), frame, full_file_name);
4195
4196 if (sfile->clip_type == CLIP_TYPE_FILE) {
4197 frames_t res = virtual_to_images(clip, frame, frame, FALSE, NULL);
4198 if (res <= 0) {
4200 return FALSE;
4201 }
4202 }
4203
4204 do {
4205 resp = LIVES_RESPONSE_NONE;
4206
4207 com = lives_strdup_printf("%s save_frame %s %d \"%s\" %d %d", prefs->backend_sync, sfile->handle,
4208 frame, tmp, width, height);
4209 lives_system(com, FALSE);
4210 lives_free(com);
4211
4212 if (THREADVAR(write_failed)) {
4213 THREADVAR(write_failed) = 0;
4215 resp = do_file_perm_error(tmp, TRUE);
4216 if (resp == LIVES_RESPONSE_CANCEL) {
4217 lives_free(tmp);
4218 return FALSE;
4219 }
4220 }
4221 if (!THREADVAR(com_failed)) {
4222 lives_free(tmp);
4223 d_print_done();
4224 return TRUE;
4225 }
4226 } while (resp == LIVES_RESPONSE_RETRY);
4227 } else {
4228 // multitrack mode
4229 LiVESError *gerr = NULL;
4230 LiVESPixbuf *pixbuf;
4231 int retval;
4232
4234 resize_layer(mainw->frame_layer, sfile->hsize, sfile->vsize, LIVES_INTERP_BEST, WEED_PALETTE_RGB24, 0);
4235 convert_layer_palette(mainw->frame_layer, WEED_PALETTE_RGB24, 0);
4236 weed_set_int_value(mainw->frame_layer, WEED_LEAF_GAMMA_TYPE, WEED_GAMMA_SRGB);
4238 weed_plant_free(mainw->frame_layer);
4239 mainw->frame_layer = NULL;
4240
4241 do {
4242 retval = 0;
4243 if (sfile->img_type == IMG_TYPE_JPEG) lives_pixbuf_save(pixbuf, tmp, IMG_TYPE_JPEG, 100,
4244 sfile->hsize, sfile->vsize, &gerr);
4245 else if (sfile->img_type == IMG_TYPE_PNG) lives_pixbuf_save(pixbuf, tmp, IMG_TYPE_PNG, 100,
4246 sfile->hsize, sfile->vsize, &gerr);
4247
4248 if (gerr) {
4249 retval = do_write_failed_error_s_with_retry(full_file_name, gerr->message);
4250 lives_error_free(gerr);
4251 gerr = NULL;
4252 }
4253 } while (retval == LIVES_RESPONSE_RETRY);
4254
4255 free(tmp);
4257 }
4258
4259 // some other error condition
4260 return FALSE;
4261}
4262
4263
4264void backup_file(int clip, int start, int end, const char *file_name) {
4265 lives_clip_t *sfile = mainw->files[clip];
4266 char **array;
4267
4268 char *title;
4269 char full_file_name[PATH_MAX];
4270
4271 char *com, *tmp;
4272
4273 boolean with_perf = FALSE;
4274 boolean retval, allow_over;
4275
4276 int withsound = 1;
4277 int current_file = mainw->current_file;
4278
4279 if (strrchr(file_name, '.') == NULL) {
4280 lives_snprintf(full_file_name, PATH_MAX, "%s.%s", file_name, LIVES_FILE_EXT_BACKUP);
4281 allow_over = FALSE;
4282 } else {
4283 lives_snprintf(full_file_name, PATH_MAX, "%s", file_name);
4284 allow_over = TRUE;
4285 }
4286
4287 // check if file exists
4288 if (!check_file(full_file_name, allow_over)) return;
4289
4290 // create header files
4291 retval = write_headers(sfile); // for pre LiVES 0.9.6
4292 retval = save_clip_values(clip); // new style (0.9.6+)
4293
4294 if (!retval) return;
4295
4296 //...and backup
4297 title = get_menu_name(sfile, FALSE);
4298 d_print(_("Backing up %s to %s"), title, full_file_name);
4299 lives_free(title);
4300
4301 if (!mainw->save_with_sound) {
4302 d_print(_(" without sound"));
4303 withsound = 0;
4304 }
4305
4306 d_print("...");
4307 cfile->progress_start = 1;
4308 cfile->progress_end = sfile->frames;
4309
4310 if (sfile->clip_type == CLIP_TYPE_FILE) {
4311 frames_t ret;
4312 char *msg = (_("Pulling frames from clip..."));
4313 if ((ret = realize_all_frames(clip, msg, FALSE)) < cfile->frames) {
4314 lives_free(msg);
4315 cfile->nopreview = FALSE;
4316 if (ret > 0) d_print_cancelled();
4317 return;
4318 }
4319 lives_free(msg);
4320 }
4321
4322 com = lives_strdup_printf("%s backup %s %d %d %d %s", prefs->backend, sfile->handle, withsound,
4323 start, end, (tmp = lives_filename_from_utf8(full_file_name, -1, NULL, NULL, NULL)));
4324 lives_free(tmp);
4325
4326 // TODO
4327 mainw->current_file = clip;
4328
4329 lives_rm(cfile->info_file);
4330 cfile->nopreview = TRUE;
4331 lives_system(com, FALSE);
4332 lives_free(com);
4333
4334 if (THREADVAR(com_failed)) {
4335 THREADVAR(com_failed) = FALSE;
4336 mainw->current_file = current_file;
4337 return;
4338 }
4339
4340 if (!(do_progress_dialog(TRUE, TRUE, _("Backing up"))) || mainw->error) {
4341 if (mainw->error) {
4343 }
4344
4345 // cancelled - clear up files
4346 cfile->nopreview = FALSE;
4347
4348 // using restore details in the 'wrong' way here...it will also clear files
4349 com = lives_strdup_printf("%s restore_details %s", prefs->backend, cfile->handle);
4351 lives_free(com);
4352
4353 //save_clip_values(mainw->current_file);
4354 mainw->current_file = current_file;
4355 return;
4356 }
4357
4358 cfile->nopreview = FALSE;
4359
4360 mainw->current_file = current_file;
4361
4362 if (mainw->error) {
4367 return;
4368 }
4369
4370 if (with_perf) {
4371 d_print(_("performance data was backed up..."));
4372 }
4373
4374 array = lives_strsplit(mainw->msg, "|", 3);
4375 sfile->f_size = strtol(array[1], NULL, 10);
4376 lives_strfreev(array);
4377
4378 lives_snprintf(sfile->file_name, PATH_MAX, "%s", full_file_name);
4379 if (!sfile->was_renamed) {
4380 lives_snprintf(sfile->name, CLIP_NAME_MAXLEN, "%s", full_file_name);
4381 set_main_title(cfile->name, 0);
4382 lives_menu_item_set_text(sfile->menuentry, full_file_name, FALSE);
4383 }
4384 if (prefs->show_recent)
4385 add_to_recent(full_file_name, 0., 0, NULL);
4386
4387 sfile->changed = FALSE;
4388 // set is_untitled to stop users from saving with a .lv1 extension
4389 sfile->is_untitled = TRUE;
4390 d_print_done();
4391}
4392
4393
4395 // this function is included only for backwards compatibility with ancient builds of LiVES
4396 //
4397
4398 int retval;
4399 int header_fd;
4400 char *hdrfile;
4401
4402 // save the file details
4403 hdrfile = lives_build_filename(prefs->workdir, file->handle, LIVES_CLIP_HEADER_OLD, NULL);
4404
4405 do {
4406 retval = 0;
4407 header_fd = creat(hdrfile, S_IRUSR | S_IWUSR);
4408 if (header_fd < 0) {
4409 retval = do_write_failed_error_s_with_retry(hdrfile, lives_strerror(errno));
4410 } else {
4411 THREADVAR(write_failed) = FALSE;
4412
4413 lives_write_le(header_fd, &cfile->bpp, 4, TRUE);
4414 lives_write_le(header_fd, &cfile->fps, 8, TRUE);
4415 lives_write_le(header_fd, &cfile->hsize, 4, TRUE);
4416 lives_write_le(header_fd, &cfile->vsize, 4, TRUE);
4417 lives_write_le(header_fd, &cfile->arps, 4, TRUE);
4418 lives_write_le(header_fd, &cfile->signed_endian, 4, TRUE);
4419 lives_write_le(header_fd, &cfile->arate, 4, TRUE);
4420 lives_write_le(header_fd, &cfile->unique_id, 8, TRUE);
4421 lives_write_le(header_fd, &cfile->achans, 4, TRUE);
4422 lives_write_le(header_fd, &cfile->asampsize, 4, TRUE);
4423
4424 lives_write(header_fd, LiVES_VERSION, strlen(LiVES_VERSION), TRUE);
4425 close(header_fd);
4426
4427 if (THREADVAR(write_failed)) retval = do_write_failed_error_s_with_retry(hdrfile, NULL);
4428 }
4429 } while (retval == LIVES_RESPONSE_RETRY);
4430
4431 lives_free(hdrfile);
4432
4433 if (retval != LIVES_RESPONSE_CANCEL) {
4434 // more file details (since version 0.7.5)
4435 hdrfile = lives_build_filename(prefs->workdir, file->handle, LIVES_CLIP_HEADER_OLD2, NULL);
4436
4437 do {
4438 retval = 0;
4439 header_fd = creat(hdrfile, S_IRUSR | S_IWUSR);
4440
4441 if (header_fd < 0) {
4442 retval = do_write_failed_error_s_with_retry(hdrfile, lives_strerror(errno));
4443 } else {
4444 THREADVAR(write_failed) = FALSE;
4445 lives_write_le(header_fd, &file->frames, 4, TRUE);
4446 lives_write(header_fd, &file->title, 1024, TRUE);
4447 lives_write(header_fd, &file->author, 1024, TRUE);
4448 lives_write(header_fd, &file->comment, 1024, TRUE);
4449 close(header_fd);
4450 }
4451 if (THREADVAR(write_failed)) retval = do_write_failed_error_s_with_retry(hdrfile, NULL);
4452 } while (retval == LIVES_RESPONSE_RETRY);
4453
4454 lives_free(hdrfile);
4455 }
4456
4457 if (retval == LIVES_RESPONSE_CANCEL) {
4458 THREADVAR(write_failed) = FALSE;
4459 return FALSE;
4460 }
4461 return TRUE;
4462}
4463
4464
4465boolean read_headers(int fileno, const char *dir, const char *file_name) {
4466 // file_name is only used to get the file size on the disk
4467 lives_clip_t *sfile;
4468 char **array;
4469 char buff[1024];
4470 char version[32];
4471 char *com, *tmp;
4472 char *old_hdrfile, *lives_header = NULL;
4473
4474 off_t header_size;
4475 int version_hash;
4476 int pieces;
4477 int header_fd;
4478 int retval2;
4479 int asigned = 0, aendian = LIVES_LITTLE_ENDIAN;
4480
4481 lives_clip_details_t detail;
4482
4483 boolean retval, retvala;
4484 boolean is_ascrap = FALSE;
4485
4486 off_t sizhead = 28; //8 * 4 + 8 + 8;
4487
4488 time_t old_time = 0, new_time = 1;
4489 struct stat mystat;
4490
4491 if (!IS_VALID_CLIP(fileno)) return FALSE;
4492
4494
4495 sfile = mainw->files[fileno];
4496
4497 old_hdrfile = lives_build_filename(dir, LIVES_CLIP_HEADER_OLD, NULL);
4498
4499 if (fileno == mainw->ascrap_file) {
4500 is_ascrap = TRUE;
4503 lives_header = lives_build_filename(dir, LIVES_ACLIP_HEADER, NULL);
4504 if (!lives_file_test(lives_header, LIVES_FILE_TEST_EXISTS)) {
4505 lives_free(lives_header);
4506 lives_header = NULL;
4507 }
4508 }
4509 if (!lives_header) lives_header = lives_build_filename(dir, LIVES_CLIP_HEADER, NULL);
4510
4512 sfile->img_type = IMG_TYPE_UNKNOWN;
4513
4514 if (lives_file_test(lives_header, LIVES_FILE_TEST_EXISTS)) {
4515 do {
4516 retval2 = LIVES_RESPONSE_OK;
4517 if (!(mainw->hdrs_cache = cache_file_contents(lives_header))) {
4518 if (fileno != mainw->current_file) goto rhd_failed;
4519 retval2 = do_read_failed_error_s_with_retry(lives_header, NULL);
4520 }
4521 } while (retval2 == LIVES_RESPONSE_RETRY);
4522
4523 if (retval2 == LIVES_RESPONSE_CANCEL) {
4524 goto rhd_failed;
4525 }
4526
4527 if (fileno == mainw->current_file) {
4529 }
4530
4531 if (!is_ascrap) restore_clip_binfmt(fileno);
4532
4533 do {
4534 do {
4536 retval = get_clip_value(fileno, detail, &sfile->header_version, 16);
4537 if (retval) {
4538 if (sfile->header_version < 100) goto old_check;
4539 } else {
4540 if (lives_file_test(old_hdrfile, LIVES_FILE_TEST_EXISTS)) {
4541 goto old_check;
4542 }
4543 if (fileno != mainw->current_file) {
4544 goto rhd_failed;
4545 }
4546 if (mainw->hdrs_cache) {
4548 } else {
4549 retval2 = do_header_read_error_with_retry(fileno);
4550 }
4551 }
4552 } while (retval2 == LIVES_RESPONSE_RETRY);
4553
4554 if (retval2 == LIVES_RESPONSE_CANCEL) goto rhd_failed;
4555
4556 if (is_ascrap) goto get_avals;
4557
4558 detail = CLIP_DETAILS_FRAMES;
4559 retval = get_clip_value(fileno, detail, &sfile->frames, 0);
4560
4561 if (retval) {
4562 detail = CLIP_DETAILS_BPP;
4563 retval = get_clip_value(fileno, detail, &sfile->bpp, 0);
4564 }
4565 if (retval) {
4566 detail = CLIP_DETAILS_FPS;
4567 retval = get_clip_value(fileno, detail, &sfile->fps, 0);
4568 }
4569 if (retval) {
4570 detail = CLIP_DETAILS_PB_FPS;
4571 retval = get_clip_value(fileno, detail, &sfile->pb_fps, 0);
4572 if (!retval) {
4573 retval = TRUE;
4574 sfile->pb_fps = sfile->fps;
4575 }
4576 }
4577 if (retval) {
4578 retval = get_clip_value(fileno, CLIP_DETAILS_PB_FRAMENO, &sfile->frameno, 0);
4579 if (!retval) {
4580 retval = TRUE;
4581 sfile->frameno = 1;
4582 }
4583 if (sfile->frameno <= 0) sfile->frameno = 1;
4584 }
4585 if (retval) {
4586 detail = CLIP_DETAILS_WIDTH;
4587 retval = get_clip_value(fileno, detail, &sfile->hsize, 0);
4588 }
4589 if (retval) {
4590 detail = CLIP_DETAILS_HEIGHT;
4591 retval = get_clip_value(fileno, detail, &sfile->vsize, 0);
4592 }
4593 if (retval) {
4594 if (sfile->header_version > 100) {
4595 detail = CLIP_DETAILS_GAMMA_TYPE;
4596 get_clip_value(fileno, detail, &sfile->gamma_type, 0);
4597 if (sfile->gamma_type == 0) sfile->gamma_type = WEED_GAMMA_SRGB;
4598 if (sfile->gamma_type != WEED_GAMMA_SRGB) {
4599 if (!do_gamma_import_warn(sfile->has_binfmt ?
4600 sfile->binfmt_version.num : 0, sfile->gamma_type)) goto rhd_failed;
4601 }
4602 }
4603 }
4604 if (retval) {
4605 detail = CLIP_DETAILS_CLIPNAME;
4606 get_clip_value(fileno, detail, sfile->name, CLIP_NAME_MAXLEN);
4607 }
4608 if (retval) {
4609 detail = CLIP_DETAILS_FILENAME;
4610 get_clip_value(fileno, detail, sfile->file_name, PATH_MAX);
4611 }
4612
4613get_avals:
4614 if (retval) {
4615 detail = CLIP_DETAILS_ACHANS;
4616 retvala = get_clip_value(fileno, detail, &sfile->achans, 0);
4617 if (!retvala) sfile->achans = 0;
4618 }
4619
4620 if (sfile->achans == 0) retvala = FALSE;
4621 else retvala = TRUE;
4622
4623 if (retval && retvala) {
4624 detail = CLIP_DETAILS_ARATE;
4625 retvala = get_clip_value(fileno, detail, &sfile->arps, 0);
4626 }
4627
4628 if (!retvala) sfile->arps = sfile->achans = sfile->arate = sfile->asampsize = 0;
4629 if (sfile->arps == 0) retvala = FALSE;
4630
4631 if (retvala && retval) {
4632 detail = CLIP_DETAILS_PB_ARATE;
4633 retvala = get_clip_value(fileno, detail, &sfile->arate, 0);
4634 if (!retvala) {
4635 retvala = TRUE;
4636 sfile->arate = sfile->arps;
4637 }
4638 }
4639 if (retvala && retval) {
4640 detail = CLIP_DETAILS_ASIGNED;
4641 retval = get_clip_value(fileno, detail, &asigned, 0);
4642 }
4643 if (retvala && retval) {
4644 detail = CLIP_DETAILS_AENDIAN;
4645 retval = get_clip_value(fileno, detail, &aendian, 0);
4646 }
4647
4648 sfile->signed_endian = asigned + aendian;
4649
4650 if (retvala && retval) {
4651 detail = CLIP_DETAILS_ASAMPS;
4652 retval = get_clip_value(fileno, detail, &sfile->asampsize, 0);
4653 }
4654 if (!retval) {
4655 if (fileno != mainw->current_file) goto rhd_failed;
4656 if (mainw->hdrs_cache) {
4657 retval2 = do_header_missing_detail_error(fileno, detail);
4658 } else {
4659 retval2 = do_header_read_error_with_retry(fileno);
4660 }
4661 } else {
4662 if (!is_ascrap) {
4663 get_clip_value(fileno, CLIP_DETAILS_TITLE, sfile->title, 1024);
4664 get_clip_value(fileno, CLIP_DETAILS_AUTHOR, sfile->author, 1024);
4665 get_clip_value(fileno, CLIP_DETAILS_COMMENT, sfile->comment, 1024);
4666 get_clip_value(fileno, CLIP_DETAILS_KEYWORDS, sfile->keywords, 1024);
4667 get_clip_value(fileno, CLIP_DETAILS_INTERLACE, &sfile->interlace, 0);
4668 // user must have selected this:
4669 if (sfile->interlace != LIVES_INTERLACE_NONE) sfile->deinterlace = TRUE;
4670 }
4671 lives_free(old_hdrfile);
4672 lives_free(lives_header);
4673 if (!prefs->vj_mode) {
4674 sfile->afilesize = reget_afilesize_inner(fileno);
4675 }
4677 // passed to further functions, but it needs to be freed and set to NULL
4678 // at some point
4679 return TRUE;
4680 }
4681 } while (retval2 == LIVES_RESPONSE_RETRY);
4682 goto rhd_failed;
4683 }
4684
4685old_check:
4686
4687 if (lives_file_test(old_hdrfile, LIVES_FILE_TEST_EXISTS)) {
4688 sfile->has_old_header = TRUE;
4689 if (!stat(old_hdrfile, &mystat)) old_time = mystat.st_mtime;
4690 if (!stat(lives_header, &mystat)) new_time = mystat.st_mtime;
4691 }
4692
4693 lives_free(lives_header);
4694 lives_header = NULL;
4696
4697 if (sfile->has_old_header && old_time <= new_time) {
4698 retval2 = LIVES_RESPONSE_OK;
4699 detail = CLIP_DETAILS_FRAMES;
4700
4701 if (get_clip_value(fileno, detail, &sfile->frames, 0)) {
4702 char *tmp;
4703
4704 // use new style header (LiVES 0.9.6+)
4705 // clean up and get file sizes
4706 if (file_name) {
4707 com = lives_strdup_printf("%s restore_details \"%s\" \"%s\" 0",
4708 prefs->backend_sync, sfile->handle,
4709 (tmp = lives_filename_from_utf8(file_name, -1, NULL, NULL, NULL)));
4710 lives_free(tmp);
4711 } else
4712 com = lives_strdup_printf("%s restore_details \"%s\" . 1", prefs->backend_sync, sfile->handle);
4713
4714 lives_popen(com, fileno != mainw->current_file, buff, 1024);
4715 lives_free(com);
4716
4717 if (THREADVAR(com_failed)) {
4718 THREADVAR(com_failed) = FALSE;
4719 goto rhd_failed;
4720 }
4721
4722 pieces = get_token_count(buff, '|');
4723
4724 if (pieces > 3) {
4725 array = lives_strsplit(buff, "|", pieces);
4726 sfile->f_size = strtol(array[1], NULL, 10);
4727 sfile->afilesize = strtol(array[2], NULL, 10);
4728 if (sfile->clip_type == CLIP_TYPE_DISK) {
4729 if (!strcmp(array[3], LIVES_FILE_EXT_JPG)) sfile->img_type = IMG_TYPE_JPEG;
4730 else sfile->img_type = IMG_TYPE_PNG;
4731 }
4732 lives_strfreev(array);
4733 }
4734 if (fileno == mainw->current_file) threaded_dialog_spin(0.);
4735 } else goto rhd_failed;
4736 lives_free(old_hdrfile);
4738 return TRUE;
4739 }
4740
4741 do {
4742 // old style headers (pre 0.9.6)
4743 retval = LIVES_RESPONSE_OK;
4744 THREADVAR(read_failed) = FALSE;
4745 lives_memset(version, 0, 32);
4746 lives_memset(buff, 0, 1024);
4747
4748 header_fd = lives_open2(old_hdrfile, O_RDONLY);
4749
4750 if (header_fd < 0) {
4751 if (fileno != mainw->current_file) {
4752 goto rhd_failed;
4753 }
4754 retval = do_read_failed_error_s_with_retry(old_hdrfile, lives_strerror(errno));
4755 } else {
4756 THREADVAR(read_failed) = FALSE;
4757 header_size = get_file_size(header_fd);
4758
4759 if (header_size < sizhead) {
4760 close(header_fd);
4761 goto rhd_failed;
4762 } else {
4763 THREADVAR(read_failed) = FALSE;
4764 lives_read_le(header_fd, &sfile->fps, 4, FALSE);
4765 if (!THREADVAR(read_failed))
4766 lives_read_le(header_fd, &sfile->bpp, 8, FALSE);
4767 if (!THREADVAR(read_failed))
4768 lives_read_le(header_fd, &sfile->hsize, 4, FALSE);
4769 if (!THREADVAR(read_failed))
4770 lives_read_le(header_fd, &sfile->vsize, 4, FALSE);
4771 if (!THREADVAR(read_failed))
4772 lives_read_le(header_fd, &sfile->arps, 4, FALSE);
4773 if (!THREADVAR(read_failed))
4774 lives_read_le(header_fd, &sfile->signed_endian, 4, FALSE);
4775 if (!THREADVAR(read_failed))
4776 lives_read_le(header_fd, &sfile->arate, 4, FALSE);
4777 if (!THREADVAR(read_failed))
4778 lives_read_le(header_fd, &sfile->unique_id, 8, FALSE);
4779 if (!THREADVAR(read_failed))
4780 lives_read_le(header_fd, &sfile->achans, 4, FALSE);
4781 if (!THREADVAR(read_failed))
4782 lives_read_le(header_fd, &sfile->asampsize, 4, FALSE);
4783
4784 if (header_size > sizhead) {
4785 if (header_size - sizhead > 31) {
4786 if (!THREADVAR(read_failed))
4787 lives_read(header_fd, &version, 31, FALSE);
4788 version[31] = '\0';
4789 } else {
4790 if (!THREADVAR(read_failed))
4791 lives_read(header_fd, &version, header_size - sizhead, FALSE);
4792 version[header_size - sizhead] = '\0';
4793 }
4794 }
4795 }
4796 close(header_fd);
4797 }
4798
4799 if (THREADVAR(read_failed)) {
4800 if (fileno != mainw->current_file) goto rhd_failed;
4801 retval = do_read_failed_error_s_with_retry(old_hdrfile, NULL);
4802 if (retval == LIVES_RESPONSE_CANCEL) goto rhd_failed;
4803 }
4804 } while (retval == LIVES_RESPONSE_RETRY);
4805
4806 lives_freep((void **)&old_hdrfile);
4807
4808 if (retval == LIVES_RESPONSE_CANCEL) goto rhd_failed;
4809
4810 // handle version changes
4811 version_hash = verhash(version);
4812 if (version_hash < 7001) {
4813 sfile->arps = sfile->arate;
4814 sfile->signed_endian = mainw->endian;
4815 }
4816
4817 com = lives_strdup_printf("%s restore_details %s %s %d", prefs->backend_sync, sfile->handle,
4818 (tmp = lives_filename_from_utf8(file_name, -1, NULL, NULL, NULL)),
4819 !strcmp(file_name, "."));
4820
4821 lives_popen(com, FALSE, buff, 1024);
4822 lives_free(com);
4823 lives_free(tmp);
4824
4825 if (THREADVAR(com_failed)) {
4826 THREADVAR(com_failed) = FALSE;
4827 goto rhd_failed;
4828 }
4829
4830 pieces = get_token_count(buff, '|');
4831 array = lives_strsplit(buff, "|", pieces);
4832 sfile->f_size = strtol(array[1], NULL, 10);
4833 sfile->afilesize = strtol(array[2], NULL, 10);
4834
4835 if (sfile->clip_type == CLIP_TYPE_DISK) {
4836 if (!strcmp(array[3], LIVES_FILE_EXT_JPG)) sfile->img_type = IMG_TYPE_JPEG;
4837 else sfile->img_type = IMG_TYPE_PNG;
4838 }
4839
4840 sfile->frames = atoi(array[4]);
4841
4842 sfile->bpp = (sfile->img_type == IMG_TYPE_JPEG) ? 24 : 32;
4843
4844 if (pieces > 4 && array[5]) {
4845 lives_snprintf(sfile->title, 1024, "%s", lives_strstrip(array[4]));
4846 }
4847 if (pieces > 5 && array[6]) {
4848 lives_snprintf(sfile->author, 1024, "%s", lives_strstrip(array[5]));
4849 }
4850 if (pieces > 6 && array[7]) {
4851 lives_snprintf(sfile->comment, 1024, "%s", lives_strstrip(array[6]));
4852 }
4853
4854 lives_strfreev(array);
4855 return TRUE;
4856
4857rhd_failed:
4858 lives_freep((void **)&lives_header);
4859 lives_freep((void **)&old_hdrfile);
4860 return FALSE;
4861}
4862
4863
4864void open_set_file(int clipnum) {
4865 char name[CLIP_NAME_MAXLEN];
4866
4867 if (mainw->current_file < 1) return;
4868
4870
4871 if (mainw->hdrs_cache) {
4872 boolean retval;
4873 // LiVES 0.9.6+
4874
4876 if (!retval) {
4877 cfile->pb_fps = cfile->fps;
4878 }
4880 if (!retval) {
4881 cfile->frameno = 1;
4882 }
4883
4885 if (!retval) {
4886 char *tmp;
4887 lives_snprintf(name, CLIP_NAME_MAXLEN, "%s", (tmp = get_untitled_name(mainw->untitled_number++)));
4888 lives_free(tmp);
4889 cfile->needs_update = TRUE;
4890 }
4891 retval = get_clip_value(mainw->current_file, CLIP_DETAILS_UNIQUE_ID, &cfile->unique_id, 0);
4892 if (!retval) {
4893 cfile->unique_id = gen_unique_id();
4894 cfile->needs_silent_update = TRUE;
4895 }
4896 retval = get_clip_value(mainw->current_file, CLIP_DETAILS_INTERLACE, &cfile->interlace, 0);
4897 if (!retval) {
4898 cfile->interlace = LIVES_INTERLACE_NONE;
4899 cfile->needs_silent_update = TRUE;
4900 }
4901 if (cfile->interlace != LIVES_INTERLACE_NONE) cfile->deinterlace = TRUE;
4902 } else {
4903 // pre 0.9.6 <- ancient code
4904 ssize_t nlen;
4905 int set_fd;
4906 int pb_fps;
4907 int retval;
4908 char *setfile = lives_strdup_printf("%s/%s/set.%s", prefs->workdir, cfile->handle, mainw->set_name);
4909
4910 do {
4911 retval = 0;
4912 if ((set_fd = lives_open2(setfile, O_RDONLY)) > -1) {
4913 // get perf_start
4914 if ((nlen = lives_read_le(set_fd, &pb_fps, 4, TRUE)) > 0) {
4915 cfile->pb_fps = pb_fps / 1000.;
4916 lives_read_le(set_fd, &cfile->frameno, 4, TRUE);
4917 lives_read(set_fd, name, CLIP_NAME_MAXLEN, TRUE);
4918 }
4919 close(set_fd);
4920 } else retval = do_read_failed_error_s_with_retry(setfile, lives_strerror(errno));
4921 } while (retval == LIVES_RESPONSE_RETRY);
4922
4923 lives_free(setfile);
4924 cfile->needs_silent_update = TRUE;
4925 }
4926
4927 if (!*name) {
4928 lives_snprintf(name, CLIP_NAME_MAXLEN, "set_clip %.3d", clipnum);
4929 } else {
4930 // pre 3.x, files erroneously had the set name appended permanently, so here we undo that
4931 if (lives_string_ends_with(name, " (%s)", mainw->set_name)) {
4932 char *remove = lives_strdup_printf(" (%s)", mainw->set_name);
4933 if (strlen(name) > strlen(remove)) name[strlen(name) - strlen(remove)] = 0;
4934 lives_free(remove);
4935 cfile->needs_silent_update = TRUE;
4936 }
4937 lives_snprintf(cfile->name, CLIP_NAME_MAXLEN, "%s", name);
4938 }
4939}
4940
4941
4942void reload_subs(int fileno) {
4943 lives_clip_t *sfile;
4944 char *subfname;
4945 if (!IS_VALID_CLIP(fileno)) return;
4946
4947 sfile = mainw->files[fileno];
4948 subfname = lives_build_filename(prefs->workdir, sfile->handle, SUBS_FILENAME "."
4949 LIVES_FILE_EXT_SRT, NULL);
4950 if (lives_file_test(subfname, LIVES_FILE_TEST_EXISTS)) {
4951 subtitles_init(sfile, subfname, SUBTITLE_TYPE_SRT);
4952 } else {
4953 lives_free(subfname);
4954 subfname = lives_build_filename(prefs->workdir, sfile->handle, SUBS_FILENAME "."
4955 LIVES_FILE_EXT_SUB, NULL);
4956 if (lives_file_test(subfname, LIVES_FILE_TEST_EXISTS)) {
4957 subtitles_init(sfile, subfname, SUBTITLE_TYPE_SUB);
4958 }
4959 }
4960 lives_free(subfname);
4961}
4962
4963
4964ulong restore_file(const char *file_name) {
4965 char *com = lives_strdup("dummy");
4966 char *mesg, *mesg1, *tmp;
4967 boolean is_OK = TRUE;
4968 char *fname = lives_strdup(file_name);
4969 char *clipdir;
4970
4971 int old_file = mainw->current_file, current_file;
4972 int new_file = mainw->first_free_file;
4973 boolean not_cancelled;
4974
4975 // create a new file
4976 if (!get_new_handle(new_file, fname)) {
4977 return 0;
4978 }
4979
4980 d_print(_("Restoring %s..."), file_name);
4981
4982 mainw->current_file = new_file;
4983
4984 cfile->hsize = mainw->def_width;
4985 cfile->vsize = mainw->def_height;
4986
4987 if (!mainw->multitrack) {
4988 switch_to_file((mainw->current_file = old_file), new_file);
4989 set_main_title(cfile->file_name, 0);
4990 }
4991
4992 com = lives_strdup_printf("%s restore %s %s", prefs->backend, cfile->handle,
4993 (tmp = lives_filename_from_utf8(file_name, -1, NULL, NULL, NULL)));
4994
4995 lives_rm(cfile->info_file);
4996 lives_system(com, FALSE);
4997 lives_free(tmp);
4998 lives_free(com);
4999
5000 if (THREADVAR(com_failed)) {
5001 THREADVAR(com_failed) = FALSE;
5002 close_current_file(old_file);
5003 return 0;
5004 }
5005
5006 cfile->restoring = TRUE;
5007 not_cancelled = do_progress_dialog(TRUE, TRUE, _("Restoring"));
5008 cfile->restoring = FALSE;
5009
5010 if (mainw->error || !not_cancelled) {
5011 if (mainw->error && mainw->cancelled != CANCEL_ERROR) {
5013 }
5014 close_current_file(old_file);
5015 return 0;
5016 }
5017
5018 // call function to return rest of file details
5019 // fsize, afilesize and frames
5020 clipdir = lives_build_path(prefs->workdir, cfile->handle, NULL);
5021 is_OK = read_headers(mainw->current_file, clipdir, file_name);
5022 lives_free(clipdir);
5024
5025 if (!is_OK) {
5026 mesg = lives_strdup_printf(_("\n\nThe file %s is corrupt.\nLiVES was unable to restore it.\n"),
5027 file_name);
5028 do_error_dialog(mesg);
5029 lives_free(mesg);
5030
5032 close_current_file(old_file);
5033 return 0;
5034 }
5035
5036 // get img_type, check frame count and size
5037 if (!cfile->checked && !check_clip_integrity(mainw->current_file, NULL, cfile->frames)) {
5038 if (cfile->afilesize == 0) {
5040 }
5042 cfile->frames = get_frame_count(mainw->current_file, 1);
5043 }
5044 }
5045 cfile->checked = TRUE;
5046
5047 // add entry to window menu
5048 // TODO - do this earlier and allow switching during restore
5050
5051 if (prefs->show_recent) {
5052 add_to_recent(file_name, 0., 0, NULL);
5053 }
5054
5055 if (cfile->frames > 0) {
5056 cfile->start = 1;
5057 } else {
5058 cfile->start = 0;
5059 }
5060 cfile->end = cfile->frames;
5061 cfile->arps = cfile->arate;
5062 cfile->pb_fps = cfile->fps;
5063 cfile->opening = FALSE;
5064 cfile->changed = FALSE;
5065
5066 if (prefs->autoload_subs) {
5068 }
5069
5070 lives_snprintf(cfile->type, 40, "Frames");
5071 mesg1 = lives_strdup_printf(_("Frames=%d type=%s size=%dx%d bpp=%d fps=%.3f\nAudio:"), cfile->frames, cfile->type,
5072 cfile->hsize, cfile->vsize, cfile->bpp, cfile->fps);
5073
5074 if (cfile->afilesize == 0l) {
5075 cfile->achans = 0;
5076 mesg = lives_strdup_printf(_("%s none\n"), mesg1);
5077 } else {
5078 mesg = lives_strdup_printf(P_("%s %d Hz %d channel %d bps\n", "%s %d Hz %d channels %d bps\n", cfile->achans),
5079 mesg1, cfile->arate, cfile->achans, cfile->asampsize);
5080 }
5081 d_print(mesg);
5082 lives_free(mesg);
5083 lives_free(mesg1);
5084
5085 cfile->is_loaded = TRUE;
5086 current_file = mainw->current_file;
5087
5088 // set new bpp
5089 cfile->bpp = (cfile->img_type == IMG_TYPE_JPEG) ? 24 : 32;
5090
5091 cfile->saved_frameno = cfile->frameno;
5092 if (cfile->frameno > cfile->frames && cfile->frameno > 1) cfile->frameno = cfile->frames;
5093 cfile->last_frameno = cfile->frameno;
5094 cfile->pointer_time = cfile->real_pointer_time = calc_time_from_frame(mainw->current_file, cfile->frameno);
5095 if (cfile->real_pointer_time > CLIP_TOTAL_TIME(mainw->current_file))
5096 cfile->real_pointer_time = CLIP_TOTAL_TIME(mainw->current_file);
5097 if (cfile->pointer_time > cfile->video_time) cfile->pointer_time = 0.;
5098
5099 if (cfile->achans) {
5100 cfile->aseek_pos = (off64_t)((double)(cfile->real_pointer_time * cfile->arate) * cfile->achans *
5101 (cfile->asampsize / 8));
5102 if (cfile->aseek_pos > cfile->afilesize) cfile->aseek_pos = 0.;
5103 }
5104
5105 if (!save_clip_values(current_file)) {
5106 close_current_file(old_file);
5107 return 0;
5108 }
5109
5111
5112 if (!mainw->multitrack) {
5113 switch_to_file((mainw->current_file = old_file), current_file);
5114 }
5116
5117 return cfile->unique_id;
5118}
5119
5120
5122 // when doing a resample, we save a list of frames for the back end to do
5123 // a reorder
5124
5125 // here we also update the frame_index for clips of type CLIP_TYPE_FILE
5126
5127 char *hdrfile = lives_strdup_printf("%s/%s/event.frames", prefs->workdir, cfile->handle);
5128
5129 int header_fd, i = 0;
5130 int retval;
5131 int perf_start, perf_end;
5132 int nevents;
5133
5134 if (!cfile->event_list) {
5135 lives_rm(hdrfile);
5136 return -1;
5137 }
5138
5139 perf_start = (int)(cfile->fps * event_list_get_start_secs(cfile->event_list)) + 1;
5140 perf_end = perf_start + (nevents = count_events(cfile->event_list, FALSE, 0, 0)) - 1;
5141
5142 if (!event_list_to_block(cfile->event_list, nevents)) return -1;
5143
5144 if (cfile->frame_index) {
5145 LiVESResponseType response;
5146 int xframes = cfile->frames;
5147 char *what = (_("creating the frame index for resampling "));
5148
5149 if (cfile->frame_index_back) lives_free(cfile->frame_index_back);
5150 cfile->frame_index_back = cfile->frame_index;
5151 cfile->frame_index = NULL;
5152
5153 do {
5154 response = LIVES_RESPONSE_OK;
5156 if (!cfile->frame_index) {
5157 response = do_memory_error_dialog(what, nevents * 4);
5158 }
5159 } while (response == LIVES_RESPONSE_RETRY);
5160 lives_free(what);
5161 if (response == LIVES_RESPONSE_CANCEL) {
5162 cfile->frame_index = cfile->frame_index_back;
5163 cfile->frame_index_back = NULL;
5164 return -1;
5165 }
5166
5167 for (i = 0; i < nevents; i++) {
5168 cfile->frame_index[i] = cfile->frame_index_back[(cfile->resample_events + i)->value - 1];
5169 }
5170
5171 cfile->frames = nevents;
5173 cfile->frames = xframes;
5174 }
5175
5176 do {
5177 retval = 0;
5178 header_fd = creat(hdrfile, S_IRUSR | S_IWUSR);
5179 if (header_fd < 0) {
5180 retval = do_write_failed_error_s_with_retry(hdrfile, lives_strerror(errno));
5181 } else {
5182 // use machine endian.
5183 // When we call "smogrify reorder", we will pass the endianness as 3rd parameter
5184
5185 THREADVAR(write_failed) = FALSE;
5186 lives_write(header_fd, &perf_start, 4, FALSE);
5187
5188 if (cfile->resample_events) {
5189 for (i = 0; i <= perf_end - perf_start; i++) {
5190 if (THREADVAR(write_failed)) break;
5191 lives_write(header_fd, &((cfile->resample_events + i)->value), 4, TRUE);
5192 }
5193 lives_freep((void **)&cfile->resample_events);
5194 }
5195
5196 if (THREADVAR(write_failed)) {
5197 retval = do_write_failed_error_s_with_retry(hdrfile, NULL);
5198 }
5199
5200 close(header_fd);
5201 }
5202 } while (retval == LIVES_RESPONSE_RETRY);
5203
5204 if (retval == LIVES_RESPONSE_CANCEL) {
5205 i = -1;
5206 }
5207
5208 lives_free(hdrfile);
5209 return i;
5210}
5211
5212
5217
5221
5222static double ascrap_mb; // MB written to audio file
5223static uint64_t free_mb; // MB free to write
5224
5225void add_to_ascrap_mb(uint64_t bytes) {
5226 ascrap_mb += bytes / 1000000.;
5227}
5228
5229
5230boolean open_scrap_file(void) {
5231 // create a scrap file for recording generated video frames
5232 int current_file = mainw->current_file;
5233 char *dir;
5234 char *handle, *scrap_handle;
5235
5238 return FALSE;
5239 }
5240
5241 handle = get_worktmp("_scrap");
5242 if (!handle) {
5244 return FALSE;
5245 }
5246 if (!create_cfile(-1, handle, FALSE)) {
5247 dir = lives_build_path(prefs->workdir, cfile->handle, NULL);
5248 lives_rmdir(dir, FALSE);
5249 lives_free(dir); lives_free(handle);
5250 return FALSE;
5251 }
5252 lives_free(handle);
5253
5255
5256 lives_snprintf(cfile->type, 40, "scrap");
5257
5258 scrap_handle = lives_strdup_printf("scrap|%s", cfile->handle);
5259 if (prefs->crash_recovery) add_to_recovery_file(scrap_handle);
5260 lives_free(scrap_handle);
5261
5262 pthread_mutex_lock(&mainw->clip_list_mutex);
5263 mainw->cliplist = lives_list_append(mainw->cliplist, LIVES_INT_TO_POINTER(mainw->current_file));
5264 pthread_mutex_unlock(&mainw->clip_list_mutex);
5265
5266 dir = lives_build_path(prefs->workdir, cfile->handle, NULL);
5267 free_mb = (double)get_ds_free(dir) / (double)ONE_MILLION;
5268 lives_free(dir);
5269
5270 mainw->current_file = current_file;
5271
5272 if (mainw->ascrap_file == -1) ascrap_mb = 0.;
5273
5274 return TRUE;
5275}
5276
5277
5278boolean open_ascrap_file(void) {
5279 // create a scrap file for recording audio
5280 int current_file = mainw->current_file;
5281 char *dir;
5282 char *handle, *ascrap_handle;
5283
5286 return FALSE;
5287 }
5288
5289 handle = get_worktmp("_ascrap");
5290 if (!handle) {
5292 return FALSE;
5293 }
5294 if (!create_cfile(-1, handle, FALSE)) {
5295 dir = lives_build_path(prefs->workdir, cfile->handle, NULL);
5296 lives_rmdir(dir, FALSE);
5297 lives_free(dir); lives_free(handle);
5298 return FALSE;
5299 }
5300 lives_free(handle);
5301
5303 lives_snprintf(cfile->type, 40, "ascrap");
5304
5305 cfile->opening = FALSE;
5306
5307 cfile->achans = 2;
5308 cfile->arate = cfile->arps = DEFAULT_AUDIO_RATE;
5309 cfile->asampsize = 16;
5310 cfile->signed_endian = 0; // ???
5311
5312#ifdef HAVE_PULSE_AUDIO
5314 if (prefs->audio_src == AUDIO_SRC_EXT) {
5315 if (mainw->pulsed_read) {
5316 cfile->arate = cfile->arps = mainw->pulsed_read->in_arate;
5317 }
5318 } else {
5319 if (mainw->pulsed) {
5320 cfile->arate = cfile->arps = mainw->pulsed->out_arate;
5321 }
5322 }
5323 }
5324#endif
5325
5326#ifdef ENABLE_JACK
5328 if (prefs->audio_src == AUDIO_SRC_EXT) {
5329 if (mainw->jackd_read) {
5330 cfile->arate = cfile->arps = mainw->jackd_read->sample_in_rate;
5331 }
5332 } else {
5333 if (mainw->jackd) {
5334 cfile->arate = cfile->arps = mainw->jackd->sample_out_rate;
5335 }
5336 }
5337 }
5338#endif
5339
5340 ascrap_handle = lives_strdup_printf("ascrap|%s", cfile->handle);
5341 if (prefs->crash_recovery) add_to_recovery_file(ascrap_handle);
5342 lives_free(ascrap_handle);
5343
5344 pthread_mutex_lock(&mainw->clip_list_mutex);
5345 mainw->cliplist = lives_list_append(mainw->cliplist, LIVES_INT_TO_POINTER(mainw->current_file));
5346 pthread_mutex_unlock(&mainw->clip_list_mutex);
5347
5348 dir = lives_build_path(prefs->workdir, cfile->handle, NULL);
5349 free_mb = (double)get_ds_free(dir) / (double)ONE_MILLION;
5350 lives_free(dir);
5351
5352 mainw->current_file = current_file;
5353
5354 ascrap_mb = 0.;
5355
5356 return TRUE;
5357}
5358
5359
5360boolean load_from_scrap_file(weed_layer_t *layer, int frame) {
5361 // load raw frame data from scrap file
5362
5363 // this will also set cfile width and height - for letterboxing etc.
5364
5365 // return FALSE if the frame does not exist/we are unable to read it
5366
5367 char *oname;
5368
5369 lives_clip_t *scrapfile = mainw->files[mainw->scrap_file];
5370
5371 int fd;
5372 if (!IS_VALID_CLIP(mainw->scrap_file)) return FALSE;
5373
5374 if (!scrapfile->ext_src) {
5375 oname = make_image_file_name(scrapfile, 1, LIVES_FILE_EXT_SCRAP);
5376 fd = lives_open_buffered_rdonly(oname);
5377 lives_free(oname);
5378 if (fd < 0) return FALSE;
5379#ifdef HAVE_POSIX_FADVISE
5380 posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
5381#endif
5382 scrapfile->ext_src = LIVES_INT_TO_POINTER(fd);
5384 } else fd = LIVES_POINTER_TO_INT(scrapfile->ext_src);
5385
5386 if (frame < 0 || !layer) return TRUE;
5387
5388 if (!weed_plant_deserialise(fd, NULL, layer)) {
5389 //g_print("bad scrapfile frame\n");
5390 return FALSE;
5391 }
5392 return TRUE;
5393}
5394
5395
5396static void ds_warn(boolean freelow, uint64_t bytes) {
5397 char *reason, *aorb;
5398 char *amount = lives_format_storage_space_string(bytes);
5399 if (freelow) {
5400 reason = (_("FREE DISK SPACE"));
5401 aorb = (_("BELOW"));
5402 } else {
5403 reason = (_("DISK SPACE USED"));
5404 aorb = (_("ABOVE"));
5405 }
5406 d_print(_("\nRECORDING was PAUSED because %s in %s IS %s %s !\n"
5407 "Diskspace limits can be set in Preferences / Misc.\n"),
5408 reason, prefs->workdir, aorb, amount);
5409 on_record_perf_activate(NULL, NULL);
5410 d_print_urgency(URGENCY_MSG_TIMEOUT, _("RECORDING WAS PAUSED DUE TO DISKSPACE LIMITS\n"));
5411 lives_free(reason);
5412 lives_free(aorb);
5413}
5414
5415
5416boolean check_for_disk_space(boolean fullcheck) {
5419 static int64_t free_ds = -1;
5420 static double xscrap_mb = -1., xascrap_mb = -1.;
5421 static double xxscrap_mb = -1., xxascrap_mb = -1.;
5422 static int64_t ds_used = -1;
5423 static boolean wrtable = FALSE;
5424
5425 double scrap_mb = 0.;
5426
5427 if (prefs->disk_quota == 0 && prefs->rec_stop_gb < 0.) return TRUE;
5428
5429 if (fullcheck) ds_used = -1;
5430
5432 scrap_mb = (double)mainw->files[mainw->scrap_file]->f_size / (double)ONE_MILLION;
5433 }
5434
5435 if (prefs->disk_quota > 0) {
5436 int64_t xds_used = -1;
5437
5438 if ((ds_used = disk_monitor_check_result(prefs->workdir)) > -1) {
5439 xds_used = ds_used;
5440 xxscrap_mb = scrap_mb;
5441 xxascrap_mb = ascrap_mb;
5442 } else {
5443 if (xxscrap_mb == -1. || xxscrap_mb > scrap_mb) xxscrap_mb = scrap_mb;
5444 if (xxascrap_mb == -1. || xxascrap_mb > ascrap_mb) xxascrap_mb = ascrap_mb;
5445 if (ds_used > -1) xds_used = ds_used
5446 + (int64_t)(scrap_mb + ascrap_mb - xxscrap_mb - xxascrap_mb)
5447 * ONE_MILLION;
5448 }
5449 if (xds_used > -1) {
5451 if ((uint64_t)xds_used >= prefs->disk_quota * ONE_BILLION) {
5452 if (mainw->record && !mainw->record_paused) {
5453 ds_warn(FALSE, (uint64_t)ds_used);
5454 }
5455 return FALSE;
5456 }
5457 }
5458 }
5459
5460 // check if we have enough free space left on the volume (return FALSE if not)
5461 if (prefs->rec_stop_gb > -1.) {
5462 // check free space again
5463 if (fullcheck || free_ds == -1 || xscrap_mb == -1 || xascrap_mb == -1
5464 || scrap_mb < xscrap_mb || ascrap_mb < xascrap_mb) {
5465 free_ds = (int64_t)get_ds_free(prefs->workdir);
5466 xscrap_mb = scrap_mb;
5467 xascrap_mb = ascrap_mb;
5468 if (free_ds == 0) wrtable = is_writeable_dir(prefs->workdir);
5469 else wrtable = TRUE;
5470 }
5471 if (wrtable) {
5472 double free_mb = (double)free_ds / (double)ONE_MILLION;
5473 double freesp = free_mb - (scrap_mb + ascrap_mb - xscrap_mb - xascrap_mb);
5474 if ((double)freesp / 1000. < prefs->rec_stop_gb) {
5475 if (mainw->record && !mainw->record_paused) {
5476 ds_warn(TRUE, freesp * ONE_MILLION);
5477 }
5478 return FALSE;
5479 }
5480 }
5481 }
5482 return TRUE;
5483}
5484
5485
5486static void _save_to_scrap_file(weed_layer_t *layer) {
5487 // returns frame number
5488 // dump the raw layer (frame) data to disk
5489
5490 // TODO: run as bg thread
5491
5492 size_t pdata_size;
5493
5494 lives_clip_t *scrapfile = mainw->files[mainw->scrap_file];
5495
5496 boolean writeable = TRUE;
5497
5498 char *framecount;
5499
5500 //int flags = O_WRONLY | O_CREAT | O_TRUNC;
5501 int fd;
5502
5503 if (!scrapfile->ext_src) {
5504 char *oname = make_image_file_name(scrapfile, 1, LIVES_FILE_EXT_SCRAP), *dirname;
5505
5506#ifdef O_NOATIME
5507 //flags |= O_NOATIME;
5508#endif
5509
5510 dirname = lives_build_filename(prefs->workdir, scrapfile->handle, NULL);
5511 lives_mkdir_with_parents(dirname, capable->umask);
5512 lives_free(dirname);
5513
5515 lives_free(oname);
5516
5517 if (fd < 0) {
5518 weed_layer_free(layer);
5519 return;
5520 }
5521 scrapfile->ext_src = LIVES_INT_TO_POINTER(fd);
5523
5524#ifdef HAVE_POSIX_FADVISE
5525 posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
5526#endif
5527 } else fd = LIVES_POINTER_TO_INT(scrapfile->ext_src);
5528
5529
5530 // serialise entire frame to scrap file
5531 pdata_size = weed_plant_serialise(fd, layer, NULL);
5532 weed_layer_free(layer);
5533
5534 scrapfile->f_size += pdata_size;
5535
5536 // check free space every 256 frames or every 10 MB of audio (TODO ****)
5537 if ((scrapfile->frames & 0xFF) == 0) {
5538 char *dir = lives_build_filename(prefs->workdir, scrapfile->handle, NULL);
5539 free_mb = (double)get_ds_free(dir) / 1000000.;
5540 if (free_mb == 0) writeable = is_writeable_dir(dir);
5541 lives_free(dir);
5542 }
5543
5544 if ((!mainw->fs || (prefs->play_monitor != widget_opts.monitor + 1 && capable->nmonitors > 1)) && !prefs->hide_framebar &&
5545 !mainw->faded) {
5546 double scrap_mb = (double)scrapfile->f_size / 1000000.;
5547 if ((scrap_mb + ascrap_mb) < (double)free_mb * .75) {
5548 // TRANSLATORS: rec(ord) %.2f M(ega)B(ytes)
5549 framecount = lives_strdup_printf(_("rec %.2f MB"), scrap_mb + ascrap_mb);
5550 } else {
5551 // warn if scrap_file > 3/4 of free space
5552 // TRANSLATORS: !rec(ord) %.2f M(ega)B(ytes)
5553 if (writeable)
5554 framecount = lives_strdup_printf(_("!rec %.2f MB"), scrap_mb + ascrap_mb);
5555 else
5556 // TRANSLATORS: rec(ord) ?? M(ega)B(ytes)
5557 framecount = (_("rec ?? MB"));
5558 }
5559 lives_entry_set_text(LIVES_ENTRY(mainw->framecounter), framecount);
5560 lives_free(framecount);
5561 }
5562
5564 check_for_disk_space((scrapfile->frames & 0x3F) ? TRUE : FALSE);
5565}
5566
5567static lives_proc_thread_t scrap_file_procthrd = NULL;
5568
5570 weed_layer_t *orig_layer;
5571 lives_clip_t *scrapfile = mainw->files[mainw->scrap_file];
5572 if (!IS_VALID_CLIP(mainw->scrap_file)) return -1;
5573 if (!layer) return scrapfile->frames;
5574 orig_layer = weed_layer_copy(NULL, layer);
5575 if (scrap_file_procthrd) {
5576 lives_proc_thread_join(scrap_file_procthrd);
5577 }
5578 scrap_file_procthrd = lives_proc_thread_create(LIVES_THRDATTR_NONE,
5579 (lives_funcptr_t)_save_to_scrap_file, -1, "V", orig_layer);
5580 return scrapfile->frames;
5581}
5582
5583void close_scrap_file(boolean remove) {
5584 int current_file = mainw->current_file;
5585
5586 if (!IS_VALID_CLIP(mainw->scrap_file)) return;
5587
5588 if (scrap_file_procthrd) {
5589 lives_proc_thread_join(scrap_file_procthrd);
5590 scrap_file_procthrd = NULL;
5591 }
5592
5594 if (cfile->ext_src && cfile->ext_src_type == LIVES_EXT_SRC_FILE_BUFF)
5595 lives_close_buffered(LIVES_POINTER_TO_INT(cfile->ext_src));
5596 cfile->ext_src = NULL;
5597 cfile->ext_src_type = LIVES_EXT_SRC_NONE;
5598
5599 if (remove) close_temp_handle(current_file);
5600 else mainw->current_file = current_file;
5601
5602 pthread_mutex_lock(&mainw->clip_list_mutex);
5603 mainw->cliplist = lives_list_remove(mainw->cliplist, LIVES_INT_TO_POINTER(mainw->scrap_file));
5604 pthread_mutex_unlock(&mainw->clip_list_mutex);
5605
5607
5608 mainw->scrap_file = -1;
5609}
5610
5611
5612void close_ascrap_file(boolean remove) {
5613 int current_file = mainw->current_file;
5614
5615 if (mainw->ascrap_file == -1) return;
5616
5617 if (remove) {
5619 close_temp_handle(current_file);
5620 }
5621
5622 pthread_mutex_lock(&mainw->clip_list_mutex);
5623 mainw->cliplist = lives_list_remove(mainw->cliplist, LIVES_INT_TO_POINTER(mainw->ascrap_file));
5624 pthread_mutex_unlock(&mainw->clip_list_mutex);
5625
5627
5628 mainw->ascrap_file = -1;
5629}
5630
5631
5632void recover_layout_map(int numclips) {
5633 // load global layout map for a set and assign entries to clips [mainw->files[i]->layout_map]
5634 LiVESList *omlist, *mlist, *lmap_node, *lmap_node_next, *lmap_entry_list, *lmap_entry_list_next;
5635
5636 layout_map *lmap_entry;
5637 uint32_t mask;
5638
5639 char **array;
5640 char *check_handle;
5641
5642 if (numclips > MAX_FILES) numclips = MAX_FILES;
5643
5644 if ((omlist = load_layout_map())) {
5645 int i;
5646
5647 mlist = omlist;
5648
5649 // assign layout map to clips
5650 for (i = 1; i <= numclips; i++) {
5651 lives_clip_t *sfile = mainw->files[i];
5652 if (!sfile) continue;
5653 lmap_node = mlist;
5654 while (lmap_node) {
5655 lmap_node_next = lmap_node->next;
5656 lmap_entry = (layout_map *)lmap_node->data;
5657 check_handle = lives_strdup(sfile->handle);
5658
5659 if (strstr(lmap_entry->handle, "/") == NULL) {
5660 lives_free(check_handle);
5661 check_handle = lives_path_get_basename(sfile->handle);
5662 }
5663
5664 if ((!strcmp(check_handle, lmap_entry->handle) && (sfile->unique_id == lmap_entry->unique_id)) ||
5665 (prefs->mt_load_fuzzy && (!strcmp(check_handle, lmap_entry->handle) || (sfile->unique_id == lmap_entry->unique_id)))
5666 ) {
5667 // check handle and unique id match
5668 // got a match, assign list to layout_map and delete this node
5669 lmap_entry_list = lmap_entry->list;
5670 while (lmap_entry_list) {
5671 lmap_entry_list_next = lmap_entry_list->next;
5672 array = lives_strsplit((char *)lmap_entry_list->data, "|", -1);
5673 if (!lives_file_test(array[0], LIVES_FILE_TEST_EXISTS)) {
5674 //g_print("removing layout because no file %s\n", array[0]);
5675 // layout file has been deleted, remove this entry
5676 if (lmap_entry_list->prev) lmap_entry_list->prev->next = lmap_entry_list_next;
5677 else lmap_entry->list = lmap_entry_list_next;
5678 if (lmap_entry_list_next) lmap_entry_list_next->prev = lmap_entry_list->prev;
5679 lives_free((livespointer)lmap_entry_list->data);
5680 lives_list_free(lmap_entry_list);
5681 }
5682 lives_strfreev(array);
5683 lmap_entry_list = lmap_entry_list_next;
5684 }
5685 sfile->layout_map = lmap_entry->list;
5686 lives_free(lmap_entry->handle);
5687 lives_free(lmap_entry->name);
5688 lives_free(lmap_entry);
5689 if (lmap_node->prev) lmap_node->prev->next = lmap_node_next;
5690 else omlist = mlist = lmap_node_next;
5691 if (lmap_node_next) lmap_node_next->prev = lmap_node->prev;
5692 lmap_node->prev = lmap_node->next = NULL;
5693 lives_list_free(lmap_node);
5695 // TODO: -- needs checking ----
5696 mask = 0;
5697 mainw->xlays = layout_frame_is_affected(i, sfile->frames + 1, 0, mainw->xlays);
5698 if (mainw->xlays) {
5699 add_lmap_error(LMAP_ERROR_DELETE_FRAMES, sfile->name, (livespointer)sfile->layout_map, i,
5700 sfile->frames, 0., FALSE);
5703 //g_print("FRMS %d\n", cfile->frames);
5704 }
5705
5707 if (mainw->xlays) {
5708 add_lmap_error(LMAP_ERROR_DELETE_AUDIO, sfile->name, (livespointer)sfile->layout_map, i,
5709 sfile->frames, sfile->laudio_time, FALSE);
5712 //g_print("AUD %f\n", cfile->laudio_time);
5713 }
5714 if (mask != 0) popup_lmap_errors(NULL, LIVES_INT_TO_POINTER(mask));
5715 }
5716
5717 lives_free(check_handle);
5718 lmap_node = lmap_node_next;
5719 }
5720 }
5721
5722 lmap_node = mlist;
5723 while (lmap_node) {
5724 lmap_entry = (layout_map *)lmap_node->data;
5725 if (lmap_entry->name) lives_free(lmap_entry->name);
5726 if (lmap_entry->handle) lives_free(lmap_entry->handle);
5727 lives_list_free_all(&lmap_entry->list);
5728 lmap_node = lmap_node->next;
5729 }
5730 if (omlist) lives_list_free(omlist);
5731 }
5732}
5733
5734
5735boolean reload_clip(int fileno, int maxframe) {
5736 // reload clip -- for CLIP_TYPE_FILE
5737 // cd to clip directory - so decoder plugins can write temp files
5738 LiVESList *odeclist;
5739 lives_clip_t *sfile = mainw->files[fileno];
5740
5741 const lives_clip_data_t *cdata = NULL;
5743
5744 double orig_fps = sfile->fps;
5745
5746 char decoder_name[PATH_MAX];
5747 char *orig_filename = lives_strdup(sfile->file_name);
5748 char *cwd = lives_get_current_dir();
5749 char *ppath = lives_build_filename(prefs->workdir, sfile->handle, NULL);
5750
5751 LiVESResponseType response;
5752 boolean was_renamed = FALSE, retb = FALSE;
5753 int current_file;
5754
5756
5757 if (!mainw->decoders_loaded) {
5760 }
5761
5762 odeclist = lives_list_copy(mainw->decoder_list);
5763 retb = get_clip_value(fileno, CLIP_DETAILS_DECODER_NAME, decoder_name, PATH_MAX);
5764 if (retb && *decoder_name) {
5765 decoder_plugin_move_to_first(decoder_name);
5766 }
5767 retb = FALSE;
5768 lives_chdir(ppath, FALSE);
5769 lives_free(ppath);
5770
5771 while (1) {
5773
5774 fake_cdata->URI = lives_strdup(sfile->file_name);
5775 fake_cdata->fps = sfile->fps;
5776 fake_cdata->nframes = maxframe;
5777
5778 response = LIVES_RESPONSE_NONE;
5779
5780 if ((cdata = get_decoder_cdata(fileno, prefs->disabled_decoders, fake_cdata->fps != 0. ? fake_cdata : NULL)) == NULL) {
5781 if (mainw->error) {
5782manual_locate:
5783 response = do_file_notfound_dialog(_("The original file"), orig_filename);
5784 if (response == LIVES_RESPONSE_RETRY) {
5785 lives_freep((void **)&fake_cdata->URI);
5786 continue;
5787 }
5788 if (response == LIVES_RESPONSE_BROWSE) {
5789 int resp;
5790 char fname[PATH_MAX], dirname[PATH_MAX], *newname;
5791 LiVESWidget *chooser;
5792
5793 lives_snprintf(dirname, PATH_MAX, "%s", orig_filename);
5794 lives_snprintf(fname, PATH_MAX, "%s", orig_filename);
5795
5796 get_dirname(dirname);
5797 get_basename(fname);
5798
5799 chooser = choose_file_with_preview(dirname, fname, NULL, LIVES_FILE_SELECTION_VIDEO_AUDIO);
5800
5801 resp = lives_dialog_run(LIVES_DIALOG(chooser));
5802
5804
5805 if (resp == LIVES_RESPONSE_ACCEPT) {
5806 newname = lives_file_chooser_get_filename(LIVES_FILE_CHOOSER(chooser));
5807 lives_widget_destroy(LIVES_WIDGET(chooser));
5808
5809 if (newname && *newname) {
5810 char *tmp;
5811 lives_snprintf(sfile->file_name, PATH_MAX, "%s", (tmp = lives_filename_to_utf8(newname, -1, NULL, NULL, NULL)));
5812 lives_free(tmp);
5813 lives_free(newname);
5814 }
5815
5816 lives_freep((void **)&fake_cdata->URI);
5817
5818 //re-scan for these
5819 sfile->fps = 0.;
5820 maxframe = 0;
5821
5822 was_renamed = TRUE;
5823 // try again with the new file
5824 continue;
5825 }
5826 // cancelled from filechooser
5827 lives_widget_destroy(LIVES_WIDGET(chooser));
5828 goto manual_locate;
5829 }
5830 // cancelled
5831 } else {
5832 // unopenable
5833 if (was_renamed) goto manual_locate;
5835 }
5836
5837 lives_chdir(cwd, FALSE);
5838 lives_free(cwd);
5839
5840 // NOT openable, or not found and user cancelled, switch back to original clip
5841 if (!sfile->checked && cdata) {
5842 check_clip_integrity(fileno, cdata, maxframe);
5843 if (sfile->frames > 0 || sfile->afilesize > 0) {
5844 // recover whatever we can
5845 sfile->clip_type = CLIP_TYPE_FILE;
5846 retb = check_if_non_virtual(fileno, 1, sfile->frames);
5847 }
5848 sfile->checked = TRUE;
5849 }
5850 if (!retb) {
5851 current_file = mainw->current_file;
5852 mainw->current_file = fileno;
5853 close_current_file(current_file);
5854 }
5855 unref_struct(&fake_cdata->lsd);
5856
5857 lives_free(orig_filename);
5858 lives_list_free(mainw->decoder_list);
5859 mainw->decoder_list = odeclist;
5860 return retb;
5861 }
5862
5863 // got cdata
5864 if (was_renamed) {
5865 // manual relocation
5866 sfile->fps = orig_fps;
5867 if (!sfile->checked && !check_clip_integrity(fileno, cdata, maxframe)) {
5868 // get correct img_type, fps, etc.
5869 if (THREADVAR(com_failed) || THREADVAR(write_failed)) do_header_write_error(fileno);
5870 goto manual_locate;
5871 }
5872 sfile->checked = TRUE;
5873 sfile->needs_silent_update = TRUE; // force filename update in header
5874 if (prefs->show_recent) {
5875 // replace in recent menu
5876 char file[PATH_MAX];
5877 int i;
5878 for (i = 0; i < 4; i++) {
5879 char *tmp;
5880 char *pref = lives_strdup_printf("%s%d", PREF_RECENT, i + 1);
5881 get_utf8_pref(pref, file, PATH_MAX);
5882 tmp = subst(file, orig_filename, sfile->file_name);
5883 if (lives_utf8_strcmp(tmp, file)) {
5884 lives_snprintf(file, PATH_MAX, "%s", tmp);
5885 set_utf8_pref(pref, file);
5888 }
5889 lives_free(tmp);
5890 lives_free(pref);
5891 }
5892 if (mainw->prefs_cache) {
5893 // update recent files -> force reload of prefs
5896 }
5897 }
5898 }
5899
5901 unref_struct(&fake_cdata->lsd);
5902 break;
5903 }
5904
5905 lives_free(orig_filename);
5906 lives_chdir(cwd, FALSE);
5907 lives_free(cwd);
5908
5909 sfile->clip_type = CLIP_TYPE_FILE;
5910 get_mime_type(sfile->type, 40, cdata);
5911 sfile->img_type = IMG_TYPE_BEST; // read_headers() will have set this to "jpeg" (default)
5912 // we will set correct value in check_clip_integrity() if there are any real images
5913
5914 if (sfile->ext_src) {
5915 boolean bad_header = FALSE;
5916 boolean correct = TRUE;
5917 if (!was_renamed) {
5918 if (!sfile->checked)
5919 correct = check_clip_integrity(fileno, cdata, maxframe); // get correct img_type, fps, etc.
5920 sfile->checked = TRUE;
5921 }
5922 if (!correct) {
5923 if (THREADVAR(com_failed) || THREADVAR(write_failed)) bad_header = TRUE;
5924 } else {
5925 lives_decoder_t *dplug = (lives_decoder_t *)sfile->ext_src;
5926 if (dplug) {
5928 if (dpsys && *dpsys->name && strcmp(dpsys->name, decoder_name)) {
5929 save_clip_value(fileno, CLIP_DETAILS_DECODER_NAME, (void *)dpsys->name);
5930 if (THREADVAR(com_failed) || THREADVAR(write_failed)) bad_header = TRUE;
5931 }
5932 }
5933 }
5934
5935 if (bad_header) do_header_write_error(fileno);
5936 }
5937 lives_list_free(mainw->decoder_list);
5938 mainw->decoder_list = odeclist;
5939 if (prefs->autoload_subs) {
5940 reload_subs(fileno);
5941 }
5942 return TRUE;
5943}
5944
5945#define _RELOAD(field) sfile->field = loaded->field
5946#define _RELOAD_STRING(field, len) lives_snprintf(sfile->field, len, "%s", loaded->field)
5947
5948#define DSIZE_MAX 100000
5949
5950static lives_clip_t *_restore_binfmt(int clipno, boolean forensic) {
5951 if (IS_NORMAL_CLIP(clipno)) {
5952 lives_clip_t *sfile = mainw->files[clipno];
5953 char *fname = lives_build_filename(prefs->workdir, sfile->handle, TOTALSAVE_NAME, NULL);
5954 if (lives_file_test(fname, LIVES_FILE_TEST_EXISTS)) {
5955 ssize_t bytes;
5956 size_t cursize = (size_t)((char *)&sfile->binfmt_end - (char *)sfile), dsize;
5957 char *xloaded = (char *)lives_calloc(1, cursize);
5958 boolean badsize = FALSE;
5959 int fd = lives_open_buffered_rdonly(fname);
5960 size_t fsize = lives_buffered_orig_size(fd);
5961 lives_clip_t *loaded = (lives_clip_t *)xloaded;
5962 if (fsize < cursize) badsize = TRUE;
5963 else {
5964 bytes = lives_read_buffered(fd, xloaded, 8, TRUE);
5965 if (bytes < 8 || lives_memcmp(loaded->binfmt_check.chars, CLIP_BINFMT_CHECK, 8)) badsize = TRUE;
5966 else {
5967 bytes += lives_read_buffered(fd, xloaded + 8, 16, TRUE);
5968 if (bytes < 16) badsize = TRUE;
5969 else {
5970 dsize = loaded->binfmt_bytes.num;
5971 if (dsize < cursize) badsize = TRUE;
5972 else {
5973 if (dsize > cursize && dsize < DSIZE_MAX) {
5974 xloaded = lives_realloc(xloaded, dsize);
5975 loaded = (lives_clip_t *)xloaded;
5976 } else dsize = cursize;
5977 bytes += lives_read_buffered(fd, xloaded + 24, dsize - 24, TRUE);
5978 if (bytes < dsize) badsize = TRUE;
5979 }
5980 }
5981 }
5982 }
5984 //if (!forensic) lives_rm(fname);
5985 lives_free(fname);
5986
5987 if (badsize) {
5988 lives_free(xloaded);
5989 return FALSE;
5990 }
5991
5992 THREADVAR(com_failed) = FALSE;
5993 if (THREADVAR(read_failed) == fd + 1) {
5994 THREADVAR(read_failed) = 0;
5995 lives_free(xloaded);
5996 return NULL;
5997 }
5998
5999 sfile->has_binfmt = TRUE;
6000
6001 if (forensic) return loaded;
6002
6003 _RELOAD_STRING(save_file_name, PATH_MAX); _RELOAD(start); _RELOAD(end); _RELOAD(is_untitled); _RELOAD(was_in_set);
6004 _RELOAD(ratio_fps); _RELOAD_STRING(mime_type, 256);
6005 _RELOAD(changed); _RELOAD(deinterlace); _RELOAD(vol);
6006 if (sfile->start < 1) sfile->start = 1;
6007 if (sfile->end > sfile->frames) sfile->end = sfile->frames;
6008 if (sfile->start > sfile->end) sfile->start = sfile->end;
6010 if (sfile->pointer_time > sfile->video_time) sfile->pointer_time = 0.;
6011 if (sfile->real_pointer_time > CLIP_TOTAL_TIME(clipno)) sfile->real_pointer_time = sfile->pointer_time;
6012 return loaded;
6013 }
6014 lives_free(fname);
6015 }
6016 return NULL;
6017}
6018
6019#undef _RELOAD
6020#undef _RELOAD_STRING
6021
6022boolean restore_clip_binfmt(int clipno) {
6023 lives_clip_t *recov = _restore_binfmt(clipno, FALSE);
6024 if (!recov) return FALSE;
6025 lives_free(recov);
6026 return TRUE;
6027}
6028
6030 return _restore_binfmt(clipno, TRUE);
6031}
6032
6033boolean recover_files(char *recovery_file, boolean auto_recover) {
6034 FILE *rfile = NULL;
6035
6036 char buff[256], *buffptr;
6037 char *clipdir;
6038
6039 LiVESResponseType resp;
6040
6041 int clipnum = 0;
6042 int maxframe;
6043 int last_good_file = -1, ngoodclips;
6044
6045 boolean is_scrap, is_ascrap;
6046 boolean did_set_check = FALSE;
6047 boolean is_ready = mainw->is_ready, mt_is_ready = FALSE;
6048 boolean mt_needs_idlefunc = FALSE;
6049 boolean retb = TRUE, retval;
6050 boolean load_from_set = TRUE;
6051 boolean rec_cleanup = FALSE;
6052
6053 // setting is_ready allows us to get the correct transient window for dialogs
6054 // otherwise the dialogs will appear behind the main interface
6055 // we do this for mainwindow and multitrack
6056
6057 // we will reset these before returning
6058 mainw->is_ready = TRUE;
6059
6060 if (mainw->multitrack) {
6061 if (mainw->multitrack->idlefunc > 0) {
6063 mainw->multitrack->idlefunc = 0;
6064 mt_needs_idlefunc = TRUE;
6065 }
6067 mt_is_ready = mainw->multitrack->is_ready;
6068 mainw->multitrack->is_ready = TRUE;
6069 }
6070
6071 if (!auto_recover) {
6072 if (1 || mainw->multitrack) {
6075 }
6076 if (!do_yesno_dialog
6077 (_("\nFiles from a previous run of LiVES were found.\nDo you want to attempt to recover them ?\n"))) {
6078 retb = FALSE;
6079 goto recovery_done;
6080 }
6081 }
6082
6083 if (recovery_file) {
6084 do {
6085 resp = LIVES_RESPONSE_NONE;
6086 rfile = fopen(recovery_file, "r");
6087 if (!rfile) {
6088 resp = do_read_failed_error_s_with_retry(recovery_file, lives_strerror(errno));
6089 if (resp == LIVES_RESPONSE_CANCEL) {
6090 retb = FALSE;
6091 goto recovery_done;
6092 }
6093 }
6094 } while (resp == LIVES_RESPONSE_RETRY);
6095 }
6096
6097 do_threaded_dialog(_("Recovering files"), FALSE);
6098 d_print(_("\nRecovering files..."));
6099
6101
6104
6105 while (1) {
6107
6109 is_scrap = FALSE;
6110 is_ascrap = FALSE;
6111
6112 THREADVAR(read_failed) = FALSE;
6113
6114 if (recovery_file) {
6115 if (!lives_fgets(buff, 256, rfile)) {
6119 if (THREADVAR(read_failed)) {
6121 do_read_failed_error_s(recovery_file, NULL);
6122 } else d_print_done();
6123 break;
6124 }
6125 } else {
6126 if (!mainw->recovery_list) {
6129 d_print_done();
6130 break;
6131 }
6132 lives_snprintf(buff, 256, "%s", (char *)mainw->recovery_list->data);
6134 }
6135
6136 lives_chomp(buff);
6137
6138 if (buff[strlen(buff) - 1] == '*') {
6139 boolean crash_recovery = prefs->crash_recovery;
6140 LiVESResponseType resp;
6141 // set to be opened
6142 buff[strlen(buff) - 1 - strlen(LIVES_DIR_SEP)] = 0;
6143 do {
6144 resp = LIVES_RESPONSE_OK;
6145 if (!is_legal_set_name(buff, TRUE, TRUE)) {
6146 resp = do_abort_cancel_retry_dialog(_("Click Abort to exit LiVES immediately, Retry to try again,"
6147 " or Cancel to continue without reloading the set.\n"));
6148 }
6149 } while (resp == LIVES_RESPONSE_RETRY);
6150 if (resp == LIVES_RESPONSE_CANCEL) continue;
6151
6156
6157 if (!reload_set(buff)) {
6158 prefs->crash_recovery = crash_recovery;
6162 continue;
6163 }
6164 mainw->was_set = TRUE;
6165 prefs->crash_recovery = crash_recovery;
6166 } else {
6168 if (!strncmp(buff, "scrap|", 6)) {
6169 is_scrap = TRUE;
6170 buffptr = buff + 6;
6171 } else if (!strncmp(buff, "ascrap|", 7)) {
6172 is_ascrap = TRUE;
6173 buffptr = buff + 7;
6174 } else {
6175 if (!strncmp(buff, "ascrap", 6) || !strncmp(buff, "scrap", 5)) {
6176 rec_cleanup = TRUE;
6177 continue;
6178 }
6179 buffptr = buff;
6180 }
6181
6182 clipdir = lives_build_filename(prefs->workdir, buffptr, NULL);
6183
6184 if (!lives_file_test(clipdir, LIVES_FILE_TEST_IS_DIR)) {
6185 lives_free(clipdir);
6186 continue;
6187 }
6188 lives_free(clipdir);
6189
6190 if (strstr(buffptr, "/" CLIPS_DIRNAME "/")) {
6191 char **array;
6193 if (!load_from_set) continue;
6194 array = lives_strsplit(buffptr, "/" CLIPS_DIRNAME "/", -1);
6195 mainw->was_set = TRUE;
6196 lives_snprintf(mainw->set_name, 128, "%s", array[0]);
6197 lives_strfreev(array);
6198
6199 if (!did_set_check && !check_for_lock_file(mainw->set_name, 0)) {
6201 load_from_set = FALSE;
6202 mainw->was_set = FALSE;
6203 mainw->set_name[0] = 0;
6204 }
6205 did_set_check = TRUE;
6206 }
6207 }
6208
6210 if (!create_cfile(-1, buffptr, FALSE)) {
6215 break;
6216 }
6217
6218 if (is_scrap || is_ascrap) {
6219 pthread_mutex_lock(&mainw->clip_list_mutex);
6220 mainw->cliplist = lives_list_append(mainw->cliplist, LIVES_INT_TO_POINTER(mainw->current_file));
6221 pthread_mutex_unlock(&mainw->clip_list_mutex);
6222 }
6223
6224 if (is_scrap) {
6226 cfile->opening = FALSE;
6227 lives_snprintf(cfile->type, 40, "scrap");
6228 cfile->frames = 1;
6229 cfile->hsize = 640;
6230 cfile->vsize = 480;
6231 continue;
6232 }
6233
6234 if (is_ascrap) {
6236 cfile->opening = FALSE;
6237 lives_snprintf(cfile->type, 40, "ascrap");
6238 }
6239
6241 // we need to keep this around for open_set_file(), below.
6242 clipdir = lives_build_path(prefs->workdir, cfile->handle, NULL);
6243 retval = read_headers(mainw->current_file, clipdir, NULL);
6244 lives_free(clipdir);
6245
6246 if (is_ascrap) {
6247 if (!retval) {
6249 mainw->ascrap_file = -1;
6250 }
6251 continue;
6252 }
6253
6254 if (mainw->current_file < 1) continue;
6255
6257 if ((maxframe = load_frame_index(mainw->current_file)) > 0) {
6259 if (!*cfile->file_name) continue;
6260 if (!reload_clip(mainw->current_file, maxframe)) continue;
6261 if (cfile->img_type == IMG_TYPE_UNKNOWN) {
6262 lives_clip_data_t *cdata = ((lives_decoder_t *)cfile->ext_src)->cdata;
6263 int fvirt = count_virtual_frames(cfile->frame_index, 1, cfile->frames);
6264 if (fvirt < cfile->frames) {
6265 if (!cfile->checked && !check_clip_integrity(mainw->current_file, cdata, cfile->frames)) {
6266 cfile->needs_update = TRUE;
6267 }
6268 cfile->checked = TRUE;
6269 }
6270 if (cfile->header_version >= 102) cfile->fps = cfile->pb_fps;
6271 }
6272 } else {
6274 boolean is_ok = TRUE;
6275 if (!cfile->checked) {
6276 if (!(is_ok = check_clip_integrity(mainw->current_file, NULL, cfile->frames))) {
6277 cfile->needs_update = TRUE;
6278 }
6279 cfile->checked = TRUE;
6280 }
6281 if (!prefs->vj_mode && !is_ok) {
6282 if (cfile->afilesize == 0) {
6284 }
6285 if (!check_frame_count(mainw->current_file, is_ok)) {
6286 cfile->frames = get_frame_count(mainw->current_file, 1);
6287 cfile->needs_update = TRUE;
6288 }
6289 }
6290 }
6291 if (!recovery_file && !cfile->checked) {
6292 lives_clip_data_t *cdata = ((lives_decoder_t *)cfile->ext_src)->cdata;
6293 if (!check_clip_integrity(mainw->current_file, cdata, cfile->frames)) {
6294 cfile->needs_update = TRUE;
6295 if (cfile->header_version >= 102) cfile->fps = cfile->pb_fps;
6296 }
6297 }
6298
6300
6306 open_set_file(++clipnum);
6307
6309
6311
6312 if (mainw->current_file < 1) continue;
6313
6314 if (cfile->clip_type == CLIP_TYPE_FILE && cfile->header_version >= 102) cfile->fps = cfile->pb_fps;
6316
6317 if (CLIP_TOTAL_TIME(mainw->current_file) == 0.) {
6318 close_current_file(last_good_file);
6319 continue;
6320 }
6321
6322 last_good_file = mainw->current_file;
6323
6324 if (cfile->needs_update || cfile->needs_silent_update) {
6325 if (cfile->needs_update) do_clip_divergence_error(mainw->current_file);
6327 cfile->needs_silent_update = cfile->needs_update = FALSE;
6328 }
6329
6330 // add to clip menu
6333 cfile->start = cfile->frames > 0 ? 1 : 0;
6334 cfile->end = cfile->frames;
6335 cfile->is_loaded = TRUE;
6336 cfile->changed = TRUE;
6337 lives_rm(cfile->info_file);
6338 if (!mainw->multitrack) set_main_title(cfile->name, 0);
6339
6340 if (cfile->frameno > cfile->frames) cfile->frameno = cfile->last_frameno = 1;
6341
6342 if (!mainw->multitrack) {
6344 lives_spin_button_set_value(LIVES_SPIN_BUTTON(mainw->spinbutton_start), cfile->start);
6347 lives_spin_button_set_value(LIVES_SPIN_BUTTON(mainw->spinbutton_end), cfile->end);
6349 showclipimgs();
6350 } else {
6351 int current_file = mainw->current_file;
6352 lives_mt *multi = mainw->multitrack;
6353 mainw->multitrack = NULL;
6354 mainw->current_file = -1;
6355 reget_afilesize(current_file);
6356 mainw->current_file = current_file;
6357 mainw->multitrack = multi;
6359 mainw->current_file = mainw->multitrack->render_file;
6360 mt_init_clips(mainw->multitrack, current_file, TRUE);
6365 mainw->current_file = current_file;
6366 }
6367
6369
6370 if (cfile->frameno > cfile->frames && cfile->frameno > 1) cfile->frameno = cfile->frames;
6371 cfile->last_frameno = cfile->frameno;
6372 cfile->pointer_time = cfile->real_pointer_time = calc_time_from_frame(mainw->current_file, cfile->frameno);
6373 if (cfile->real_pointer_time > CLIP_TOTAL_TIME(mainw->current_file))
6374 cfile->real_pointer_time = CLIP_TOTAL_TIME(mainw->current_file);
6375 if (cfile->pointer_time > cfile->video_time) cfile->pointer_time = 0.;
6376
6377 if (cfile->achans) {
6378 cfile->aseek_pos = (off64_t)((double)(cfile->real_pointer_time * cfile->arate) * cfile->achans *
6379 (cfile->asampsize / 8));
6380 if (cfile->aseek_pos > cfile->afilesize) cfile->aseek_pos = 0.;
6381 }
6382
6383 if (mainw->current_file != -1)
6385
6386 if (!mainw->multitrack) resize(1);
6387
6389 }
6390 }
6391
6393
6394 ngoodclips = lives_list_length(mainw->cliplist);
6395 if (!ngoodclips) {
6396 d_print(_("No clips were recovered.\n"));
6397 }
6398 d_print(P_("%d clip was recovered ", "%d clips were recovered ", ngoodclips), ngoodclips);
6399 if (recovery_file)
6400 d_print(_("from the previous session.\n"));
6401 else
6402 d_print(_("from previous sessions.\n"));
6403
6404 if (!mainw->multitrack) { // TODO check if we can do this in mt too
6405 int start_file = mainw->current_file;
6406 if (start_file > 1 && start_file == mainw->ascrap_file && mainw->files[start_file - 1]) {
6407 start_file--;
6408 }
6409 if (start_file > 1 && start_file == mainw->scrap_file && mainw->files[start_file - 1]) {
6410 start_file--;
6411 }
6412 if (start_file > 1 && start_file == mainw->ascrap_file && mainw->files[start_file - 1]) {
6413 start_file--;
6414 }
6415 if ((!IS_VALID_CLIP(start_file) || (mainw->files[start_file]->frames == 0 && mainw->files[start_file]->afilesize == 0))
6416 && mainw->files[1] && start_file != 1) {
6417 for (start_file = MAX_FILES; start_file > 0; start_file--) {
6418 if (mainw->files[start_file]
6419 && (mainw->files[start_file]->frames > 0 || mainw->files[start_file]->afilesize > 0))
6420 if (start_file != mainw->scrap_file && start_file != mainw->ascrap_file) break;
6421 }
6422 }
6423
6424 if (start_file != mainw->current_file) {
6425 rec_cleanup = TRUE;
6426 switch_to_file(mainw->current_file, start_file);
6427 showclipimgs();
6429 }
6430 } else {
6431 mt_clip_select(mainw->multitrack, TRUE); // scroll clip on screen
6432 }
6433
6434 if (recovery_file) fclose(rfile);
6435
6436recovery_done:
6437
6439
6443 mainw->is_ready = is_ready;
6444 if (mainw->multitrack) {
6445 mainw->multitrack->is_ready = mt_is_ready;
6446 mainw->current_file = mainw->multitrack->render_file;
6450 if (mt_needs_idlefunc) mainw->multitrack->idlefunc = mt_idle_add(mainw->multitrack);
6451 } else update_play_times();
6452 mainw->last_dprint_file = -1;
6454 d_print("");
6455 mainw->invalid_clips = rec_cleanup;
6456 return retb;
6457}
6458
6459
6460void add_to_recovery_file(const char *handle) {
6462
6463 if (THREADVAR(com_failed)) {
6464 THREADVAR(com_failed) = FALSE;
6465 return;
6466 }
6467
6468 if ((mainw->multitrack && mainw->multitrack->event_list) || mainw->stored_event_list)
6470}
6471
6472
6474 // part of the crash recovery system
6475 // returns TRUE if successful
6476 LiVESList *clist = mainw->cliplist;
6477 char *recovery_entry;
6478 char *temp_recovery_file;
6479
6480 boolean opened = FALSE;
6481 boolean wrote_set_entry = FALSE;
6482
6483 int recovery_fd = -1;
6484 LiVESResponseType retval;
6485
6486 if (!clist || !prefs->crash_recovery) {
6488 return FALSE;
6489 }
6490
6491 temp_recovery_file = lives_strdup_printf("%s.%s", mainw->recovery_file, LIVES_FILE_EXT_TMP);
6492
6493 do {
6494 retval = LIVES_RESPONSE_NONE;
6495 THREADVAR(write_failed) = FALSE;
6496 opened = FALSE;
6497 recovery_fd = -1;
6498
6499 for (; clist; clist = clist->next) {
6500 int i = LIVES_POINTER_TO_INT(clist->data);
6501 if (IS_NORMAL_CLIP(i)) {
6502 lives_clip_t *sfile = mainw->files[i];
6503 if (i == mainw->scrap_file) {
6504 recovery_entry = lives_strdup_printf("scrap|%s\n", sfile->handle);
6505 } else if (i == mainw->ascrap_file) {
6506 recovery_entry = lives_strdup_printf("ascrap|%s\n", sfile->handle);
6507 } else {
6508 if (sfile->was_in_set && *mainw->set_name) {
6509 if (!wrote_set_entry) {
6510 recovery_entry = lives_build_filename(mainw->set_name, "*\n", NULL);
6511 wrote_set_entry = TRUE;
6512 } else continue;
6513 } else recovery_entry = lives_strdup_printf("%s\n", sfile->handle);
6514 }
6515
6516 if (!opened) recovery_fd = creat(temp_recovery_file, S_IRUSR | S_IWUSR);
6517 if (recovery_fd < 0) retval = do_write_failed_error_s_with_retry(temp_recovery_file, lives_strerror(errno));
6518 else {
6519 opened = TRUE;
6520 lives_write(recovery_fd, recovery_entry, strlen(recovery_entry), TRUE);
6521 if (THREADVAR(write_failed)) retval = do_write_failed_error_s_with_retry(temp_recovery_file, NULL);
6522 }
6523 lives_free(recovery_entry);
6524 }
6525 if (THREADVAR(write_failed)) break;
6526 }
6527 } while (retval == LIVES_RESPONSE_RETRY);
6528
6529 if (!opened) lives_rm(mainw->recovery_file);
6530 else if (recovery_fd >= 0) {
6531 close(recovery_fd);
6532 retval = LIVES_RESPONSE_INVALID;
6533 do {
6534 lives_mv(temp_recovery_file, mainw->recovery_file);
6535 if (THREADVAR(com_failed)) {
6536 retval = do_write_failed_error_s_with_retry(temp_recovery_file, NULL);
6537 }
6538 } while (retval == LIVES_RESPONSE_RETRY);
6539 }
6540
6541 lives_free(temp_recovery_file);
6542
6543 if ((mainw->multitrack && mainw->multitrack->event_list) || mainw->stored_event_list)
6545
6546 return TRUE;
6547}
6548
6549
6550boolean check_for_recovery_files(boolean auto_recover) {
6551 uint32_t recpid = 0;
6552
6553 char *recovery_file, *recovery_numbering_file, *recording_file, *recording_numbering_file, *xfile;
6554 char *com;
6555
6556 boolean retval = FALSE;
6557 boolean found = FALSE, found_recording = FALSE;
6558
6559 int lgid = lives_getgid();
6560 int luid = lives_getuid();
6561
6563
6564 // ask backend to find the latest recovery file which is not owned by a running version of LiVES
6565 com = lives_strdup_printf("%s get_recovery_file %d %d %s recovery %d", prefs->backend_sync, luid, lgid,
6567
6569 lives_free(com);
6570
6571 if (THREADVAR(com_failed)) {
6572 THREADVAR(com_failed) = FALSE;
6573 return FALSE;
6574 }
6575
6576 recpid = atoi(mainw->msg);
6577 if (recpid == 0) return FALSE;
6578
6579 retval = recover_files((recovery_file = lives_strdup_printf("%s/recovery.%d.%d.%d", prefs->workdir, luid,
6580 lgid, recpid)), auto_recover);
6581 lives_free(recovery_file);
6582
6583 if (!retval || prefs->vj_mode) {
6584 com = lives_strdup_printf("%s clean_recovery_files %d %d \"%s\" %d %d", prefs->backend_sync, luid, lgid, capable->myname,
6586 lives_system(com, FALSE);
6587 lives_free(com);
6588 if (prefs->vj_mode) {
6590 return TRUE;
6591 }
6592 return FALSE;
6593 }
6594
6595#if !GTK_CHECK_VERSION(3, 0, 0)
6597 showclipimgs();
6601 }
6602#endif
6603
6604 THREADVAR(com_failed) = FALSE;
6605
6608
6609 // check for layout recovery file
6610 recovery_file = lives_strdup_printf("%s/%s.%d.%d.%d.%s", prefs->workdir, LAYOUT_FILENAME, luid, lgid, recpid,
6612 recovery_numbering_file = lives_strdup_printf("%s/%s.%d.%d.%d", prefs->workdir, LAYOUT_NUMBERING_FILENAME, luid, lgid, recpid);
6613
6614 recording_file = lives_strdup_printf("%s/recorded-%s.%d.%d.%d.%s", prefs->workdir, LAYOUT_FILENAME, luid, lgid, recpid,
6616
6617 recording_numbering_file = lives_strdup_printf("%s/recorded-%s.%d.%d.%d", prefs->workdir, LAYOUT_NUMBERING_FILENAME, luid, lgid,
6618 recpid);
6619
6620 if (!lives_file_test(recovery_file, LIVES_FILE_TEST_EXISTS)) {
6621 lives_free(recovery_file);
6622 recovery_file = lives_strdup_printf("%s/%s.%d.%d.%d", prefs->workdir, LAYOUT_FILENAME, luid, lgid, recpid);
6623 if (lives_file_test(recovery_file, LIVES_FILE_TEST_EXISTS)) {
6624 found = TRUE;
6625 }
6626 } else {
6627 found = TRUE;
6628 }
6629 if (found) {
6630 if (!lives_file_test(recovery_numbering_file, LIVES_FILE_TEST_EXISTS)) {
6631 found = FALSE;
6632 }
6633 }
6634
6635 if (prefs->rr_crash && lives_file_test(recording_file, LIVES_FILE_TEST_EXISTS)) {
6636 if (lives_file_test(recording_numbering_file, LIVES_FILE_TEST_EXISTS)) {
6637 found_recording = TRUE;
6638 xfile = lives_strdup_printf("%s/keep_recorded-layout.%d.%d.%d", prefs->workdir, luid, lgid, lpid);
6639 lives_mv(recording_file, xfile);
6640 lives_free(xfile);
6641 xfile = lives_strdup_printf("%s/keep_recorded-layout_numbering.%d.%d.%d", prefs->workdir, luid, lgid, lpid);
6642 lives_mv(recording_numbering_file, xfile);
6643 lives_free(xfile);
6645 }
6646 }
6647
6648 if (found) {
6649 // move files temporarily to stop them being cleansed
6650 xfile = lives_strdup_printf("%s/keep_layout.%d.%d.%d", prefs->workdir, luid, lgid, lpid);
6651 lives_mv(recovery_file, xfile);
6652 lives_free(xfile);
6653 xfile = lives_strdup_printf("%s/keep_layout_numbering.%d.%d.%d", prefs->workdir, luid, lgid, lpid);
6654 lives_mv(recovery_numbering_file, xfile);
6655 lives_free(xfile);
6657 }
6658
6659 if (!found && !found_recording) {
6662 }
6663
6664 lives_free(recovery_file);
6665 lives_free(recovery_numbering_file);
6666 lives_free(recording_file);
6667 lives_free(recording_numbering_file);
6668
6669 if (THREADVAR(com_failed) && prefs->crash_recovery) {
6671 return FALSE;
6672 }
6673
6674 com = lives_strdup_printf("%s clean_recovery_files %d %d \"%s\" %d 0", prefs->backend_sync, luid, lgid, capable->myname,
6675 capable->mainpid);
6676 lives_system(com, FALSE);
6677 lives_free(com);
6678
6679 recovery_file = lives_strdup_printf("%s/%s.%d.%d.%d.%s", prefs->workdir, LAYOUT_FILENAME, luid, lgid, lpid,
6681 recovery_numbering_file = lives_strdup_printf("%s/%s.%d.%d.%d", prefs->workdir, LAYOUT_NUMBERING_FILENAME, luid, lgid, lpid);
6682
6684 // move files back
6685 xfile = lives_strdup_printf("%s/keep_layout.%d.%d.%d", prefs->workdir, luid, lgid, lpid);
6686 lives_mv(xfile, recovery_file);
6687 lives_free(xfile);
6688 xfile = lives_strdup_printf("%s/keep_layout_numbering.%d.%d.%d", prefs->workdir, luid, lgid, lpid);
6689 lives_mv(xfile, recovery_numbering_file);
6690 lives_free(xfile);
6691 }
6692
6693 recording_file = lives_strdup_printf("%s/recorded-%s.%d.%d.%d.%s", prefs->workdir, LAYOUT_FILENAME, luid, lgid, lpid,
6695 recording_numbering_file = lives_strdup_printf("%s/recorded-%s.%d.%d.%d", prefs->workdir, LAYOUT_NUMBERING_FILENAME, luid, lgid,
6696 lpid);
6697
6699 xfile = lives_strdup_printf("%s/keep_recorded-layout.%d.%d.%d", prefs->workdir, luid, lgid, lpid);
6701 lives_mv(xfile, recording_file);
6702 lives_free(xfile);
6703 xfile = lives_strdup_printf("%s/keep_recorded-layout_numbering.%d.%d.%d", prefs->workdir, luid, lgid, lpid);
6704 lives_mv(xfile, recording_numbering_file);
6705 lives_free(xfile);
6706 }
6707
6708 lives_free(recovery_file);
6709 lives_free(recovery_numbering_file);
6710 lives_free(recording_file);
6711 lives_free(recording_numbering_file);
6712
6714 mainw->abort_hook_func = NULL;
6715
6721 }
6722 return retval;
6723}
6724
void audio_free_fnames(void)
Definition: audio.c:71
void audio_cache_end(void)
Definition: audio.c:3276
void fill_abuffer_from(lives_audio_buf_t *abuf, weed_plant_t *event_list, weed_plant_t *st_event, boolean exact)
Definition: audio.c:2567
void init_jack_audio_buffers(int achans, int arate, boolean exact)
Definition: audio.c:2708
void init_pulse_audio_buffers(int achans, int arate, boolean exact)
Definition: audio.c:2729
LIVES_GLOBAL_INLINE char * get_audio_file_name(int fnum, boolean opening)
Definition: audio.c:38
lives_audio_buf_t * audio_cache_init(void)
Definition: audio.c:3238
void free_pulse_audio_buffers(void)
Definition: audio.c:2768
void free_jack_audio_buffers(void)
Definition: audio.c:2748
LIVES_GLOBAL_INLINE lives_cancel_t handle_audio_timeout(void)
Definition: audio.c:3971
lives_audio_track_state_t * get_audio_and_effects_state_at(weed_plant_t *event_list, weed_plant_t *st_event, weed_timecode_t fill_tc, int what_to_get, boolean exact)
get audio (and optionally video) state at timecode tc OR before event st_event
Definition: audio.c:2419
#define MAX_ACHANS
max number of player channels
Definition: audio.h:30
#define ASERVER_CMD_FILE_CLOSE
Definition: audio.h:58
#define is_realtime_aplayer(ptype)
Definition: audio.h:236
#define DEFAULT_AUDIO_CHANS
Definition: audio.h:24
#define DEFAULT_AUDIO_RATE
defaults for when not specifed
Definition: audio.h:23
@ RECA_GENERATED
Definition: audio.h:201
@ RECA_EXTERNAL
Definition: audio.h:200
void unlock_loop_lock(void)
Definition: callbacks.c:4966
boolean on_trim_audio_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: callbacks.c:12053
void end_fs_preview(void)
Definition: callbacks.c:7569
boolean reload_set(const char *set_name)
Definition: callbacks.c:5661
void play_all(boolean from_menu)
Definition: callbacks.c:4482
void popup_lmap_errors(LiVESMenuItem *menuitem, livespointer user_data)
Definition: callbacks.c:9335
void play_sel(void)
Definition: callbacks.c:4536
void on_record_perf_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: callbacks.c:4605
boolean on_mouse_scroll(LiVESWidget *widget, LiVESXEventScroll *event, livespointer user_data)
Definition: callbacks.c:10602
void on_toy_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: callbacks.c:9550
void on_quit_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: callbacks.c:2133
boolean freeze_callback(LiVESAccelGroup *group, LiVESWidgetObject *obj, uint32_t keyval, LiVESXModifierType mod, livespointer user_data)
Definition: callbacks.c:11135
void lives_notify(int msgnumber, const char *msgstring)
Definition: callbacks.c:49
void on_details_button_clicked(void)
Definition: callbacks.c:7834
boolean on_ins_silence_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: callbacks.c:12694
void on_playsel_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: callbacks.c:4566
boolean on_del_audio_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: callbacks.c:12258
LIVES_GLOBAL_INLINE void init_conversions(int intent)
Definition: colourspace.c:1804
LiVESPixbuf * layer_to_pixbuf(weed_layer_t *layer, boolean realpalette, boolean fordisplay)
LIVES_GLOBAL_INLINE weed_layer_t * weed_layer_free(weed_layer_t *layer)
frees pixel_data for a layer, then the layer itself
boolean convert_layer_palette(weed_layer_t *layer, int outpl, int op_clamping)
boolean resize_layer(weed_layer_t *layer, int width, int height, LiVESInterpType interp, int opal_hint, int oclamp_hint)
resize a layer
weed_layer_t * weed_layer_copy(weed_layer_t *dlayer, weed_layer_t *slayer)
copy source layer slayer to dest layer dlayer
weed_plant_t weed_layer_t
Definition: colourspace.h:71
boolean create_frame_index(int fileno, boolean init, frames_t start_offset, frames_t nframes)
Definition: cvirtual.c:27
void insert_blank_frames(int sfileno, frames_t nframes, frames_t after, int palette)
Definition: cvirtual.c:1080
frames_t count_virtual_frames(frames_t *findex, frames_t start, frames_t end)
count virtual frames between start and end (inclusive)
Definition: cvirtual.c:20
frames_t load_frame_index(int fileno)
Definition: cvirtual.c:114
frames_t virtual_to_images(int sfileno, frames_t sframe, frames_t eframe, boolean update_progress, LiVESPixbuf **pbr)
Definition: cvirtual.c:719
boolean save_frame_index(int fileno)
Definition: cvirtual.c:56
boolean check_if_non_virtual(int fileno, frames_t start, frames_t end)
Definition: cvirtual.c:644
frames_t realize_all_frames(int clipno, const char *msg, boolean enough)
Definition: cvirtual.c:849
boolean check_clip_integrity(int fileno, const lives_clip_data_t *cdata, frames_t maxframe)
Definition: cvirtual.c:296
void pump_io_chan(LiVESIOChannel *iochan)
Definition: dialogs.c:1020
boolean do_yesno_dialog(const char *text)
Definition: dialogs.c:655
boolean do_header_write_error(int clip)
Definition: dialogs.c:4169
LIVES_GLOBAL_INLINE void do_clip_divergence_error(int fileno)
Definition: dialogs.c:888
LIVES_GLOBAL_INLINE boolean do_set_locked_warning(const char *setname)
Definition: dialogs.c:4357
LiVESResponseType do_read_failed_error_s_with_retry(const char *fname, const char *errtext)
Definition: dialogs.c:4122
void do_write_failed_error_s(const char *s, const char *addinfo)
Definition: dialogs.c:3979
LIVES_GLOBAL_INLINE void do_no_loadfile_error(const char *fname)
Definition: dialogs.c:3526
void do_threaded_dialog(const char *trans_text, boolean has_cancel)
Definition: dialogs.c:3849
LIVES_GLOBAL_INLINE void do_no_decoder_error(const char *fname)
Definition: dialogs.c:3518
LIVES_GLOBAL_INLINE LiVESResponseType do_abort_cancel_retry_dialog(const char *text)
Definition: dialogs.c:708
LiVESResponseType do_file_notfound_dialog(const char *detail, const char *filename)
Definition: dialogs.c:3513
LiVESResponseType do_memory_error_dialog(char *op, size_t bytes)
Definition: dialogs.c:904
LIVES_GLOBAL_INLINE void do_program_not_found_error(const char *progname)
Definition: dialogs.c:3640
boolean do_auto_dialog(const char *text, int type)
Definition: dialogs.c:2844
LiVESResponseType do_write_failed_error_s_with_retry(const char *fname, const char *errtext)
Definition: dialogs.c:4058
boolean do_comments_dialog(int fileno, char *filename)
Definition: dialogs.c:3288
LIVES_GLOBAL_INLINE void do_after_invalid_warning(void)
Definition: dialogs.c:3748
void end_threaded_dialog(void)
Definition: dialogs.c:3883
LIVES_GLOBAL_INLINE void too_many_files(void)
Definition: dialogs.c:2996
LIVES_GLOBAL_INLINE void do_after_crash_warning(void)
Definition: dialogs.c:3742
LIVES_GLOBAL_INLINE boolean do_gamma_import_warn(uint64_t fv, int gamma_type)
Definition: dialogs.c:3440
LiVESResponseType handle_backend_errors(boolean can_retry)
Definition: dialogs.c:922
void do_read_failed_error_s(const char *s, const char *addinfo)
Definition: dialogs.c:4034
LIVES_GLOBAL_INLINE LiVESResponseType do_error_dialog(const char *text)
Definition: dialogs.c:749
void threaded_dialog_spin(double fraction)
Definition: dialogs.c:3823
LiVESResponseType do_header_read_error_with_retry(int clip)
Definition: dialogs.c:4155
boolean check_storage_space(int clipno, boolean is_processing)
Definition: dialogs.c:1086
LiVESResponseType do_file_perm_error(const char *file_name, boolean allow_cancel)
Definition: dialogs.c:4226
void workdir_warning(void)
Definition: dialogs.c:3001
LiVESResponseType do_header_missing_detail_error(int clip, lives_clip_details_t detail)
Definition: dialogs.c:4186
boolean do_progress_dialog(boolean visible, boolean cancellable, const char *text)
Definition: dialogs.c:2274
boolean do_warning_dialog_with_check(const char *text, uint64_t warn_mask_number)
Definition: dialogs.c:569
void weed_generator_end(weed_plant_t *inst)
weed_plant_t * weed_plant_deserialise(int fd, unsigned char **mem, weed_plant_t *plant)
void deinit_render_effects(void)
switch off effects after render preview during rendering/render preview, we use the "keys" FX_KEYS_MA...
size_t weed_plant_serialise(int fd, weed_plant_t *plant, unsigned char **mem)
void weed_reinit_all(void)
void deinit_easing_effects(void)
switch off effects in easing out state after playback ends during playback, some effects don't deinit...
boolean weed_playback_gen_start(void)
void weed_bg_generator_end(weed_plant_t *inst)
double event_list_get_end_secs(weed_plant_t *event_list)
Definition: events.c:4607
render_details * create_render_details(int type)
Definition: events.c:6252
boolean event_list_to_block(weed_plant_t *event_list, int num_events)
Definition: events.c:2329
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
void event_list_free(weed_plant_t *event_list)
Definition: events.c:2313
double event_list_get_start_secs(weed_plant_t *event_list)
Definition: events.c:4618
render_details * rdet
Definition: events.h:256
void fade_background(void)
Definition: gui.c:3216
void enable_record(void)
Definition: gui.c:3706
void reset_message_area(void)
Definition: gui.c:4734
void add_to_playframe(void)
Definition: gui.c:4451
void make_preview_box(void)
Definition: gui.c:3515
void fullscreen_internal(void)
Definition: gui.c:3440
void play_window_set_title(void)
Definition: gui.c:3722
void resize_play_window(void)
Definition: gui.c:4349
void make_play_window(void)
actually in gui.c
Definition: gui.c:3932
void kill_play_window(void)
Definition: gui.c:4386
void add_to_clipmenu(void)
Definition: gui.c:4512
void disable_record(void)
Definition: gui.c:3717
void unfade_background(void)
Definition: gui.c:3324
char * get_menu_name(lives_clip_t *sfile, boolean add_setname)
Definition: gui.c:4487
char * choose_file(const char *dir, const char *fname, char **const filt, LiVESFileChooserAction act, const char *title, LiVESWidget *extra_widget)
Definition: interface.c:4080
double lives_ce_update_timeline(int frame, double x)
pointer position in timeline
Definition: interface.c:207
LiVESWidget * choose_file_with_preview(const char *dir, const char *title, char **const filt, int filesel_type)
Definition: interface.c:4228
char * choose_file_bg(const char *dir, const char *fname, char **const filt, LiVESFileChooserAction act, const char *title, LiVESWidget *extra_widget)
Definition: interface.c:4221
void add_suffix_check(LiVESBox *box, const char *ext)
Definition: interface.c:23
void redraw_timeline(int clipno)
Definition: interface.c:3412
LiVESTextView * create_output_textview(void)
Definition: interface.c:4630
#define LIVES_PREVIEW_TYPE_VIDEO_ONLY
Definition: interface.h:171
#define LIVES_FILE_SELECTION_VIDEO_AUDIO
Definition: interface.h:177
LIVES_GLOBAL_INLINE void unref_struct(lives_struct_def_t *lsd)
Definition: lsd-tab.c:89
void * struct_from_template(lives_struct_type st_type)
Definition: lsd-tab.c:76
@ LIVES_STRUCT_CLIP_DATA_T
Definition: lsd-tab.h:12
boolean show_desktop_panel(void)
LIVES_GLOBAL_INLINE int lives_getgid(void)
char * get_md5sum(const char *filename)
Definition: machinestate.c:646
weed_plantptr_t lives_proc_thread_t
lives proc_threads API
uint64_t get_ds_free(const char *dir)
Definition: machinestate.c:776
off_t get_file_size(int fd)
Definition: machinestate.c:943
LIVES_GLOBAL_INLINE size_t lives_strlen(const char *s)
off_t sget_file_size(const char *name)
Definition: machinestate.c:962
LIVES_GLOBAL_INLINE int lives_strappend(const char *string, int len, const char *xnew)
LIVES_GLOBAL_INLINE int lives_getuid(void)
int64_t disk_monitor_check_result(const char *dir)
Definition: machinestate.c:726
char * lives_format_storage_space_string(uint64_t space)
Definition: machinestate.c:664
LIVES_GLOBAL_INLINE void lives_proc_thread_join(lives_proc_thread_t tinfo)
uint64_t gen_unique_id(void)
Definition: machinestate.c:68
off_t reget_afilesize_inner(int fileno)
LIVES_GLOBAL_INLINE char * lives_chomp(char *buff)
LIVES_GLOBAL_INLINE char * lives_concat(char *st, char *x)
LIVES_GLOBAL_INLINE ticks_t lives_get_relative_ticks(ticks_t origsecs, ticks_t orignsecs)
Definition: machinestate.c:813
char * get_worktmp(const char *prefix)
lives_proc_thread_t lives_proc_thread_create(lives_thread_attr_t attr, lives_funcptr_t func, int return_type, const char *args_fmt,...)
create the specific plant which defines a background task to be run
void reget_afilesize(int fileno)
Definition: machinestate.c:972
#define lives_calloc
Definition: machinestate.h:67
#define lives_memcmp
Definition: machinestate.h:58
#define THREADVAR(var)
Definition: machinestate.h:531
#define lives_free
Definition: machinestate.h:52
#define lives_memset
Definition: machinestate.h:61
#define lives_memcpy
Definition: machinestate.h:55
#define PRIu64
Definition: machinestate.h:170
void *(* lives_funcptr_t)(void *)
Definition: machinestate.h:378
#define lives_realloc
Definition: machinestate.h:49
#define LIVES_THRDATTR_NONE
Definition: machinestate.h:437
void defer_sigint(int signum)
Definition: main.c:282
LIVES_GLOBAL_INLINE void free_track_decoders(void)
Definition: main.c:7826
void load_end_image(int frame)
Definition: main.c:5922
void set_drawing_area_from_pixbuf(LiVESWidget *widget, LiVESPixbuf *pixbuf, lives_painter_surface_t *surface)
Definition: main.c:5525
void sensitize(void)
Definition: main.c:5078
_palette * palette
interface colour settings
Definition: main.c:101
boolean resize_message_area(livespointer data)
Definition: main.c:3588
void catch_sigint(int signum)
Definition: main.c:296
void procw_desensitize(void)
Definition: main.c:5445
void set_signal_handlers(SignalHandlerPointer sigfunc)
Definition: main.c:4077
void showclipimgs(void)
Definition: main.c:5636
void resize(double scale)
Definition: main.c:10230
void load_preview_image(boolean update_always)
Definition: main.c:6205
void init_track_decoders(void)
Definition: main.c:7816
void set_main_title(const char *file, int untitled)
Definition: main.c:5005
void break_me(const char *brkstr)
Definition: main.c:159
boolean check_layer_ready(weed_layer_t *layer)
block until layer pixel_data is ready.
Definition: main.c:7528
mainwindow * mainw
Definition: main.c:103
void desensitize(void)
Definition: main.c:5302
void switch_to_file(int old_file, int new_file)
Definition: main.c:9646
boolean render_choice_idle(livespointer data)
Definition: main.c:3454
boolean lives_pixbuf_save(LiVESPixbuf *pixbuf, char *fname, lives_img_type_t imgtype, int quality, int width, int height, LiVESError **gerrorptr)
Save a pixbuf to a file using the specified imgtype and the specified quality/compression value.
Definition: main.c:9304
boolean lazy_startup_checks(void *data)
Definition: main.c:3480
void close_current_file(int file_to_switch_to)
close current file, and try to switch to file_to_switch_to
Definition: main.c:9373
ssize_t lives_read_buffered(int fd, void *buf, ssize_t count, boolean allow_less)
Definition: utils.c:924
#define LIVES_WARN(x)
Definition: main.h:1862
void clear_mainw_msg(void)
Definition: utils.c:1435
int lives_close_buffered(int fd)
Definition: utils.c:716
int frames_t
Definition: main.h:99
int get_frame_count(int idx, int xsize)
sets mainw->files[idx]->frames with current framecount
Definition: utils.c:3109
#define IMG_TYPE_BEST
Definition: main.h:781
void get_basename(char *filename)
Definition: utils.c:3194
ssize_t lives_popen(const char *com, boolean allow_error, char *buff, ssize_t buflen)
Definition: utils.c:194
boolean add_lmap_error(lives_lmap_error_t lerror, const char *name, livespointer user_data, int clipno, int frameno, double atime, boolean affects_current)
Definition: utils.c:2673
void(* SignalHandlerPointer)(int)
Definition: main.h:1464
void lives_list_free_all(LiVESList **)
Definition: utils.c:4873
boolean check_frame_count(int idx, boolean last_chkd)
check number of frames is correct for files of type CLIP_TYPE_DISK
Definition: utils.c:3074
void get_play_times(void)
recalculate video / audio lengths and draw the timer bars
Definition: utils.c:3672
boolean get_clip_value(int which, lives_clip_details_t, void *retval, size_t maxlen)
Definition: utils.c:5039
@ UNDO_RENDER
resample/reorder/resize/apply effects
Definition: main.h:680
@ UNDO_RESAMPLE
Definition: main.h:664
@ UNDO_NONE
Definition: main.h:660
void wait_for_bg_audio_sync(int fileno)
Definition: utils.c:4644
size_t get_token_count(const char *string, int delim)
Definition: utils.c:5430
ssize_t lives_write(int fd, livesconstpointer buf, ssize_t count, boolean allow_fail)
#define USE_MPV
some shared structures
Definition: main.h:1112
#define MAX_FILES
max files is actually 1 more than this, since file 0 is the clipboard
Definition: main.h:184
void d_print_cancelled(void)
Definition: utils.c:2610
void d_print_file_error_failed(void)
Definition: utils.c:2625
void get_total_time(lives_clip_t *file)
calculate laudio, raudio and video time (may be deprecated and replaced with macros)
Definition: utils.c:3690
double calc_time_from_frame(int clip, int frame)
Definition: utils.c:1756
void cached_list_free(LiVESList **list)
Definition: utils.c:4881
int lives_touch(const char *tfile)
Definition: utils.c:4455
#define CLIP_NAME_MAXLEN
Definition: main.h:804
#define LIVES_GLOBAL_INLINE
Definition: main.h:239
int lives_chdir(const char *path, boolean no_error_dlg)
Definition: utils.c:1393
char * subst(const char *string, const char *from, const char *to)
Definition: utils.c:5484
@ CANCEL_KILL
normal - kill background processes working on current clip
Definition: main.h:759
@ CANCEL_SOFT
just cancel in GUI (for keep, etc)
Definition: main.h:760
#define ANNOY_DISPLAY
Definition: main.h:441
#define ANNOY_FS
Definition: main.h:449
lives_img_type_t lives_image_ext_to_img_type(const char *img_ext)
Definition: utils.c:3034
void get_dirname(char *filename)
Definition: utils.c:3167
#define AV_TRACK_MIN_DIFF
ignore track time differences < this (seconds)
Definition: main.h:806
#define DEF_FILE_PERMS
non-executable, is modified by the umask
Definition: main.h:209
#define LIVES_IS_PLAYING
Definition: main.h:840
#define IS_NORMAL_CLIP(clip)
Definition: main.h:833
#define LIVES_EXT_SRC_FILE_BUFF
Definition: main.h:1049
#define LIVES_CLIP_HEADER_VERSION
Definition: main.h:941
#define CURRENT_CLIP_IS_TEMP
Definition: main.h:812
size_t lives_buffered_orig_size(int fd)
Definition: utils.c:1377
int lives_open3(const char *pathname, int flags, mode_t mode)
Definition: utils.c:94
boolean d_print_urgency(double timeout_seconds, const char *fmt,...)
Definition: utils.c:2497
#define AFORM_UNKNOWN
Definition: main.h:788
boolean lives_alarm_clear(lives_alarm_t alarm_handle)
Definition: utils.c:1732
#define ulong
Definition: main.h:178
void get_filename(char *filename, boolean strip_dir)
Definition: utils.c:3205
int lives_system(const char *com, boolean allow_error)
Definition: utils.c:145
void find_when_to_stop(void)
Definition: utils.c:3722
void lives_kill_subprocesses(const char *dirname, boolean kill_parent)
Definition: utils.c:4516
char * get_extension(const char *filename)
Definition: utils.c:3217
boolean is_writeable_dir(const char *dir)
Definition: utils.c:5701
#define AFORM_UNSIGNED
Definition: main.h:786
boolean check_file(const char *file_name, boolean check_exists)
check if file exists
Definition: utils.c:4312
char * lives_fgets(char *s, int size, FILE *stream)
Definition: utils.c:368
int lives_cp(const char *from, const char *to)
Definition: utils.c:4414
const char * get_image_ext_for_type(lives_img_type_t imgtype)
Definition: utils.c:3025
boolean lives_fsync(int fd)
Definition: utils.c:109
ssize_t lives_read_le(int fd, void *buf, ssize_t count, boolean allow_less)
Definition: utils.c:486
#define FPS_MAX
maximum fps we will allow (double)
Definition: main.h:218
int lives_open_buffered_rdonly(const char *pathname)
Definition: utils.c:636
void update_play_times(void)
like get_play_times, but will force redraw of audio waveforms
Definition: utils.c:3677
void add_to_recent(const char *filename, double start, int frames, const char *file_open_params)
Definition: utils.c:4701
int lives_mv(const char *from, const char *to)
Definition: utils.c:4446
lives_clip_details_t
Definition: main.h:1141
@ CLIP_DETAILS_KEYWORDS
Definition: main.h:1162
@ CLIP_DETAILS_UNIQUE_ID
Definition: main.h:1147
@ CLIP_DETAILS_TITLE
Definition: main.h:1155
@ CLIP_DETAILS_AUTHOR
Definition: main.h:1156
@ CLIP_DETAILS_DECODER_NAME
Definition: main.h:1164
@ CLIP_DETAILS_COMMENT
Definition: main.h:1157
@ CLIP_DETAILS_PB_FPS
Definition: main.h:1144
@ CLIP_DETAILS_ASAMPS
Definition: main.h:1153
@ CLIP_DETAILS_INTERLACE
Definition: main.h:1163
@ CLIP_DETAILS_HEIGHT
Definition: main.h:1146
@ CLIP_DETAILS_FPS
Definition: main.h:1143
@ CLIP_DETAILS_CLIPNAME
Definition: main.h:1160
@ CLIP_DETAILS_GAMMA_TYPE
Definition: main.h:1165
@ CLIP_DETAILS_WIDTH
Definition: main.h:1145
@ CLIP_DETAILS_PB_FRAMENO
Definition: main.h:1158
@ CLIP_DETAILS_FILENAME
Definition: main.h:1159
@ CLIP_DETAILS_ASIGNED
Definition: main.h:1151
@ CLIP_DETAILS_ACHANS
Definition: main.h:1150
@ CLIP_DETAILS_AENDIAN
Definition: main.h:1152
@ CLIP_DETAILS_PB_ARATE
Definition: main.h:1149
@ CLIP_DETAILS_BPP
Definition: main.h:1142
@ CLIP_DETAILS_ARATE
Definition: main.h:1148
@ CLIP_DETAILS_FRAMES
Definition: main.h:1154
@ CLIP_DETAILS_HEADER_VERSION
Definition: main.h:1161
#define RES_HIDE
Definition: main.h:456
lives_img_type_t lives_image_type_to_img_type(const char *lives_image_type)
Definition: utils.c:3046
uint64_t make_version_hash(const char *ver)
Definition: utils.c:3500
#define CURRENT_CLIP_HAS_VIDEO
Definition: main.h:815
lives_alarm_t lives_alarm_set(ticks_t ticks)
set alarm for now + delta ticks (10 nanosec) param ticks (10 nanoseconds) is the offset when we want ...
Definition: utils.c:1643
@ LIVES_DIRECTION_FORWARD
Definition: main.h:854
int lives_rmdir(const char *dir, boolean force)
Definition: utils.c:4366
#define IS_VALID_CLIP(clip)
Definition: main.h:808
#define LIVES_EXT_SRC_NONE
Definition: main.h:1043
int verhash(char *version)
Definition: utils.c:4755
void get_location(const char *exe, char *val, int maxlen)
Definition: utils.c:3407
void d_print_enough(int frames)
Definition: utils.c:2630
int lives_rm(const char *file)
Definition: utils.c:4395
int64_t ticks_t
Definition: main.h:97
ssize_t lives_write_le(int fd, livesconstpointer buf, ssize_t count, boolean allow_fail)
void d_print_failed(void)
Definition: utils.c:2615
ssize_t lives_read(int fd, void *buf, ssize_t count, boolean allow_less)
Definition: utils.c:460
LiVESList * cache_file_contents(const char *filename)
Definition: utils.c:4909
#define CURRENT_CLIP_IS_NORMAL
Definition: main.h:838
capability * capable
Definition: main.h:627
#define RESTYPE_ACTION
Definition: main.h:462
#define cfile
Definition: main.h:1833
boolean check_for_lock_file(const char *set_name, int type)
check for set lock file do this via the back-end (smogrify) this allows for the locking scheme to be ...
Definition: utils.c:2894
int lives_open2(const char *pathname, int flags)
Definition: utils.c:99
@ LIVES_INTERLACE_TOP_FIRST
Definition: main.h:793
@ LIVES_INTERLACE_NONE
Definition: main.h:791
void reset_clipmenu(void)
Definition: utils.c:4290
void d_print(const char *fmt,...)
Definition: utils.c:2542
#define LIVES_ERROR(x)
Definition: main.h:1870
@ IMG_TYPE_UNKNOWN
Definition: main.h:775
@ IMG_TYPE_PNG
Definition: main.h:777
@ IMG_TYPE_JPEG
Definition: main.h:776
boolean lives_string_ends_with(const char *string, const char *fmt,...)
Definition: utils.c:3143
int lives_echo(const char *text, const char *to, boolean append)
Definition: utils.c:4500
boolean check_for_executable(lives_checkstatus_t *cap, const char *exec)
Definition: utils.c:3434
int lives_utf8_strcmp(const char *s1, const char *s2)
Definition: utils.c:5469
int lives_pgid_t
Definition: main.h:118
#define AFORM_BIG_ENDIAN
Definition: main.h:787
#define CURRENT_CLIP_IS_VALID
Definition: main.h:809
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
#define PATH_MAX
Definition: main.h:255
#define LIVES_DIR_SEP
Definition: main.h:197
boolean lives_freep(void **ptr)
Definition: utils.c:1411
boolean is_legal_set_name(const char *set_name, boolean allow_dupes, boolean leeway)
Definition: utils.c:2975
@ CLIP_TYPE_FILE
unimported video, not or partially broken in frames
Definition: main.h:765
@ CLIP_TYPE_TEMP
temp type, for internal use only
Definition: main.h:768
@ CLIP_TYPE_GENERATOR
frames from generator plugin
Definition: main.h:766
@ CLIP_TYPE_DISK
imported video, broken into frames
Definition: main.h:764
@ CLIP_TYPE_NULL_VIDEO
generates blank video frames
Definition: main.h:767
int lives_create_buffered_nosync(const char *pathname, int mode)
Definition: utils.c:702
char * make_image_file_name(lives_clip_t *clip, frames_t frame, const char *img_ext)
lives_image_type can be a string, lives_img_type_t is an enumeration
Definition: utils.c:3053
boolean save_clip_value(int which, lives_clip_details_t, void *val)
Definition: utils.c:5175
#define CLIP_TOTAL_TIME(clip)
Definition: main.h:830
ticks_t lives_alarm_check(lives_alarm_t alarm_handle)
Definition: utils.c:1687
@ CANCEL_APP_QUIT
application quit
Definition: main.h:713
@ CANCEL_EVENT_LIST_END
event_list completed
Definition: main.h:722
@ CANCEL_NO_PROPOGATE
cancel but keep opening
Definition: main.h:707
@ CANCEL_KEEP_LOOPING
special cancel for TV toy
Definition: main.h:755
@ CANCEL_NONE
no cancel
Definition: main.h:701
@ CANCEL_ERROR
cancelled because of error
Definition: main.h:740
@ CANCEL_KEEP
user pressed 'Keep'
Definition: main.h:734
@ CANCEL_USER
user pressed stop
Definition: main.h:704
@ CANCEL_AUDIO_ERROR
cancelled because of soundcard error
Definition: main.h:743
@ CANCEL_USER_PAUSED
cancelled and paused
Definition: main.h:746
int calc_frame_from_time(int filenum, double time)
nearest frame [1, frames]
Definition: utils.c:1759
#define LIVES_CLIP_HEADER_OLD
Definition: mainwindow.h:559
#define MAINW_MSG_SIZE
mainw->msg bytesize
Definition: mainwindow.h:702
@ LIVES_TOY_NONE
Definition: mainwindow.h:234
@ LIVES_TOY_MAD_FRAMES
Definition: mainwindow.h:235
@ LIVES_TOY_TV
Definition: mainwindow.h:236
#define LIVES_WEBSITE
Definition: mainwindow.h:520
#define LIVES_IMAGE_TYPE_JPEG
Definition: mainwindow.h:479
#define MONITOR_QUOTA
Definition: mainwindow.h:1805
#define ALL_USED
Definition: mainwindow.h:192
#define LIVES_STATUS_FILE_NAME
Definition: mainwindow.h:532
#define MIN_MSGBAR_HEIGHT
Definition: mainwindow.h:135
#define LAYOUT_FILENAME
Definition: mainwindow.h:570
#define LIVES_FILE_EXT_SRT
Definition: mainwindow.h:507
#define LIVES_FILE_EXT_BACKUP
Definition: mainwindow.h:500
#define TOTALSAVE_NAME
Definition: mainwindow.h:535
#define PLUGIN_EXEC_DIR
Definition: mainwindow.h:599
#define SCRATCH_NONE
Definition: mainwindow.h:1027
#define LIVES_FILE_EXT_SCRAP
Definition: mainwindow.h:493
#define TEMPFILE_MARKER
Definition: mainwindow.h:574
#define LIVES_MAIN_WINDOW_WIDGET
Definition: mainwindow.h:188
#define DEF_IDLE_MAX
Definition: mainwindow.h:1740
#define TICKS_PER_SECOND_DBL
actually microseconds / 100.
Definition: mainwindow.h:37
#define ONE_MILLION
Definition: mainwindow.h:27
#define LIVES_ACLIP_HEADER
Definition: mainwindow.h:556
#define SUBS_FILENAME
Definition: mainwindow.h:562
#define LIVES_FILE_EXT_TMP
Definition: mainwindow.h:486
#define LIVES_FILE_EXT_LAYOUT
Definition: mainwindow.h:513
#define LIVES_ENC_DEBUG_FILE_NAME
Definition: mainwindow.h:533
#define EXEC_MPLAYER2
Definition: mainwindow.h:387
#define LIVES_CLIP_HEADER_OLD2
Definition: mainwindow.h:560
#define LIVES_CLIP_HEADER
Definition: mainwindow.h:555
#define EXEC_MKTEMP
Definition: mainwindow.h:430
#define GUI_SCREEN_WIDTH
Definition: mainwindow.h:99
#define CLIP_BINFMT_CHECK
Definition: mainwindow.h:536
#define CLIPS_DIRNAME
Definition: mainwindow.h:620
#define EXEC_MIDISTOP
shipped
Definition: mainwindow.h:416
#define CLIPDIR(handle)
Definition: mainwindow.h:630
#define EFFORT_RANGE_MAX
if set to TRUE during playback then a new frame (or possibly the current one) will be displayed ASAP
Definition: mainwindow.h:1770
#define STYLE_1
turn on theming if set
Definition: mainwindow.h:299
#define LIVES_IMAGE_TYPE_PNG
Definition: mainwindow.h:480
#define EXEC_MPV
Definition: mainwindow.h:388
#define LIVES_FILE_EXT_JPG
Definition: mainwindow.h:488
#define EXEC_MIDISTART
shipped
Definition: mainwindow.h:415
#define LIVES_FILE_EXT_SUB
Definition: mainwindow.h:508
#define EXEC_MPLAYER
Definition: mainwindow.h:386
#define SCREEN_AREA_BACKGROUND
Definition: mainwindow.h:1681
#define LIVES_DEFAULT_TIMEOUT
Definition: mainwindow.h:43
#define URGENCY_MSG_TIMEOUT
Definition: mainwindow.h:1637
#define LIVES_ACLIP_HEADER_NEW
Definition: mainwindow.h:558
#define LAYOUT_NUMBERING_FILENAME
Definition: mainwindow.h:572
#define H_RESIZE_ADJUST
Definition: mainwindow.h:66
#define LIVES_DEVNULL
Definition: mainwindow.h:592
#define V_RESIZE_ADJUST
Definition: mainwindow.h:67
#define ONE_BILLION
Definition: mainwindow.h:25
int lives_alarm_t
Definition: mainwindow.h:696
#define SCREEN_AREA_FOREGROUND
Definition: mainwindow.h:1680
#define GUI_SCREEN_HEIGHT
Definition: mainwindow.h:100
#define LIVES_CLIP_HEADER_NEW
Definition: mainwindow.h:557
void mt_clip_select(lives_mt *mt, boolean scroll)
Definition: multitrack.c:3024
uint32_t mt_idle_add(lives_mt *mt)
Definition: multitrack.c:901
void mt_desensitise(lives_mt *mt)
Definition: multitrack.c:16979
void polymorph(lives_mt *mt, lives_mt_poly_state_t poly)
Definition: multitrack.c:12777
void mt_sensitise(lives_mt *mt)
Definition: multitrack.c:17052
void multitrack_play_sel(LiVESMenuItem *menuitem, livespointer user_data)
Definition: multitrack.c:17449
void set_poly_tab(lives_mt *mt, uint32_t tab)
Definition: multitrack.c:3962
LiVESList * layout_audio_is_affected(int clipno, double stime, double etime, LiVESList *xlays)
Definition: multitrack.c:22281
void mt_swap_play_pause(lives_mt *mt, boolean put_pause)
Definition: multitrack.c:17206
LiVESList * load_layout_map(void)
Definition: multitrack.c:19584
LiVESList * layout_frame_is_affected(int clipno, int start, int end, LiVESList *xlays)
Definition: multitrack.c:22247
void mt_show_current_frame(lives_mt *mt, boolean return_layer)
preview the current frame
Definition: multitrack.c:3214
void mt_init_clips(lives_mt *mt, int orig_file, boolean add)
Definition: multitrack.c:10859
boolean write_backup_layout_numbering(lives_mt *mt)
Definition: multitrack.c:668
@ LMAP_ERROR_DELETE_AUDIO
Definition: multitrack.h:1020
@ LMAP_ERROR_DELETE_FRAMES
Definition: multitrack.h:1019
@ POLY_CLIPS
Definition: multitrack.h:123
@ POLY_NONE
Definition: multitrack.h:122
#define LIVES_OSC_NOTIFY_CLIP_OPENED
sent after a clip is opened
Definition: osc_notify.h:46
#define LIVES_OSC_NOTIFY_SUCCESS
for OSC only (not for C++)
Definition: osc_notify.h:52
#define LIVES_OSC_NOTIFY_PLAYBACK_STOPPED
sent when a/v playback ends
Definition: osc_notify.h:35
#define LIVES_OSC_NOTIFY_PLAYBACK_STARTED
sent when a/v playback starts or clip is switched
Definition: osc_notify.h:34
boolean subtitles_init(lives_clip_t *sfile, char *fname, lives_subtitle_type_t subtype)
Definition: pangotext.c:996
boolean save_srt_subtitles(lives_clip_t *sfile, double start_time, double end_time, double offset_time, const char *filename)
Definition: pangotext.c:1039
boolean save_sub_subtitles(lives_clip_t *sfile, double start_time, double end_time, double offset_time, const char *filename)
Definition: pangotext.c:1101
lives_subtitle_type_t
Definition: pangotext.h:15
@ SUBTITLE_TYPE_SUB
Definition: pangotext.h:18
@ SUBTITLE_TYPE_SRT
Definition: pangotext.h:17
@ SUBTITLE_TYPE_NONE
Definition: pangotext.h:16
void get_mime_type(char *text, int maxlen, const lives_clip_data_t *cdata)
Definition: plugins.c:2513
void vid_playback_plugin_exit(void)
Definition: plugins.c:1413
boolean decoder_plugin_move_to_first(const char *name)
Definition: plugins.c:2072
boolean chill_decoder_plugin(int fileno)
Definition: plugins.c:2425
_vid_playback_plugin * open_vid_playback_plugin(const char *name, boolean in_use)
Definition: plugins.c:1099
LiVESList * load_decoders(void)
Definition: plugins.c:2092
const lives_clip_data_t * get_decoder_cdata(int fileno, LiVESList *disabled, const lives_clip_data_t *fake_cdata)
Definition: plugins.c:2286
boolean check_encoder_restrictions(boolean get_extension, boolean user_audio, boolean save_all)
Definition: plugins.c:1557
char * plugin_run_param_window(const char *scrap_text, LiVESVBox *vbox, lives_rfx_t **ret_rfx)
create an interface window for a plugin; possibly run it, and return the parameters
Definition: plugins.c:3717
#define SYNC_HINT_AUDIO_TRIM_START
Definition: plugins.h:399
#define SYNC_HINT_AUDIO_TRIM_END
Definition: plugins.h:401
#define SYNC_HINT_VIDEO_PAD_END
Definition: plugins.h:405
#define PLUGIN_ENCODERS
Definition: plugins.h:98
#define SYNC_HINT_AUDIO_PAD_START
Definition: plugins.h:400
#define ENCODER_NON_NATIVE
Definition: plugins.h:260
#define SYNC_HINT_AUDIO_PAD_END
Definition: plugins.h:402
#define SYNC_HINT_VIDEO_PAD_START
Definition: plugins.h:404
#define HAS_RFX
Definition: plugins.h:257
#define VPP_LOCAL_DISPLAY
Definition: plugins.h:69
@ LIVES_INTENTION_PLAY
Definition: plugins.h:45
boolean pref_factory_float(const char *prefidx, float newval, boolean permanent)
Definition: preferences.c:1192
int set_utf8_pref(const char *key, const char *value)
Definition: preferences.c:306
LiVESResponseType get_utf8_pref(const char *key, char *val, int maxlen)
Definition: preferences.c:112
#define JACK_OPTS_TIMEBASE_START
jack sets play start position
Definition: preferences.h:238
#define WARN_MASK_LAYOUT_DELETE_FRAMES
Definition: preferences.h:96
#define PREF_RECENT
Definition: preferences.h:956
_prefs * prefs
Definition: preferences.h:847
#define PREF_IMAGE_DIR
Definition: preferences.h:948
#define PREF_MASTER_VOLUME
Definition: preferences.h:1099
#define SEPWIN_TYPE_NON_STICKY
Definition: preferences.h:187
#define WARN_MASK_LAYOUT_DELETE_AUDIO
Definition: preferences.h:110
#define WARN_MASK_CLEAN_INVALID
Definition: preferences.h:127
#define JACK_OPTS_TIMEBASE_CLIENT
full timebase client
Definition: preferences.h:239
#define SEPWIN_TYPE_STICKY
Definition: preferences.h:188
#define AUD_PLAYER_NONE
Definition: preferences.h:41
#define AUD_PLAYER_JACK
Definition: preferences.h:43
_future_prefs * future_prefs
Definition: preferences.h:848
#define AUDIO_SRC_EXT
Definition: preferences.h:206
#define WARN_MASK_FSIZE
Definition: preferences.h:88
#define WARN_MASK_CLEAN_AFTER_CRASH
Definition: preferences.h:122
#define AUD_PLAYER_PULSE
Definition: preferences.h:44
#define PREF_VID_SAVE_DIR
Definition: preferences.h:953
_resaudw * resaudw
Definition: resample.h:38
ulong restore_file(const char *file_name)
Definition: saveplay.c:4964
void wait_for_stop(const char *stop_command)
Definition: saveplay.c:4139
boolean load_from_scrap_file(weed_layer_t *layer, int frame)
Definition: saveplay.c:5360
boolean check_for_disk_space(boolean fullcheck)
Definition: saveplay.c:5416
#define STOP_GIVE_UP_TIME
boolean save_clip_values(int which)
Definition: saveplay.c:103
#define AUDIO_FRAMES_TO_READ
Definition: saveplay.c:307
boolean get_temp_handle(int index)
get a temp "handle" from disk.
Definition: saveplay.c:3571
boolean write_headers(lives_clip_t *file)
Definition: saveplay.c:4394
LIVES_GLOBAL_INLINE void start_playback_async(int type)
Definition: saveplay.c:96
void play_file(void)
play the current clip from 'mainw->play_start' to 'mainw->play_end'
Definition: saveplay.c:2213
void close_scrap_file(boolean remove)
Definition: saveplay.c:5583
void close_ascrap_file(boolean remove)
Definition: saveplay.c:5612
ulong deduce_file(const char *file_name, double start, int end)
Definition: saveplay.c:238
LIVES_GLOBAL_INLINE char * get_untitled_name(int number)
Definition: saveplay.c:3802
boolean save_file_comments(int fileno)
Definition: saveplay.c:4100
#define _RELOAD_STRING(field, len)
Definition: saveplay.c:5946
void open_set_file(int clipnum)
Definition: saveplay.c:4864
boolean open_scrap_file(void)
Definition: saveplay.c:5230
boolean restore_clip_binfmt(int clipno)
Definition: saveplay.c:6022
boolean rewrite_recovery_file(void)
Definition: saveplay.c:6473
boolean get_new_handle(int index, const char *name)
Definition: saveplay.c:3821
boolean _start_playback(livespointer data)
Definition: saveplay.c:19
void reload_subs(int fileno)
Definition: saveplay.c:4942
void add_to_ascrap_mb(uint64_t bytes)
Definition: saveplay.c:5225
ulong open_file_sel(const char *file_name, double start, int frames)
Definition: saveplay.c:309
int close_temp_handle(int new_clip)
close cfile and switch to new clip (may be -1)
Definition: saveplay.c:3498
int create_nullvideo_clip(const char *handle)
Definition: saveplay.c:3808
LIVES_GLOBAL_INLINE boolean start_playback(int type)
Definition: saveplay.c:94
boolean save_frame_inner(int clip, int frame, const char *file_name, int width, int height, boolean from_osc)
Definition: saveplay.c:4170
lives_clip_t * create_cfile(int new_file, const char *handle, boolean is_loaded)
set default values for a clip (in memory)
Definition: saveplay.c:3656
boolean open_ascrap_file(void)
Definition: saveplay.c:5278
boolean reload_clip(int fileno, int maxframe)
Definition: saveplay.c:5735
char * prep_audio_player(char *com2, char *com3, frames_t audio_end, int arate, int asigned, int aendian)
Definition: saveplay.c:2133
const char * get_deinterlace_string(void)
Definition: saveplay.c:230
LIVES_GLOBAL_INLINE void set_default_comment(lives_clip_t *sfile, const char *extrat)
Definition: saveplay.c:1251
void save_frame(LiVESMenuItem *menuitem, livespointer user_data)
Definition: saveplay.c:1186
#define SECOND_STOP_TIME
void backup_file(int clip, int start, int end, const char *file_name)
Definition: saveplay.c:4264
boolean read_headers(int fileno, const char *dir, const char *file_name)
Definition: saveplay.c:4465
int save_to_scrap_file(weed_layer_t *layer)
Definition: saveplay.c:5569
void pad_init_silence(void)
Definition: saveplay.c:293
boolean read_file_details(const char *file_name, boolean is_audio, boolean is_img)
Definition: saveplay.c:207
void add_to_recovery_file(const char *handle)
Definition: saveplay.c:6460
lives_clip_t * clip_forensic(int clipno)
Definition: saveplay.c:6029
boolean recover_files(char *recovery_file, boolean auto_recover)
Definition: saveplay.c:6033
#define _RELOAD(field)
Definition: saveplay.c:5945
int save_event_frames(void)
Definition: saveplay.c:5121
void recover_layout_map(int numclips)
Definition: saveplay.c:5632
boolean check_for_recovery_files(boolean auto_recover)
Definition: saveplay.c:6550
boolean add_file_info(const char *check_handle, boolean aud_only)
Definition: saveplay.c:3870
#define DSIZE_MAX
Definition: saveplay.c:5948
ulong open_file(const char *file_name)
Definition: saveplay.c:261
boolean get_handle_from_info_file(int index)
Definition: saveplay.c:1163
void save_file(int clip, int start, int end, const char *filename)
Definition: saveplay.c:1260
char of_desc[128]
Definition: plugins.h:264
char name[64]
Definition: plugins.h:234
uint32_t capabilities
Definition: plugins.h:255
char of_name[64]
Definition: plugins.h:263
char of_def_ext[16]
Definition: plugins.h:267
uint32_t audio_codec
Definition: plugins.h:235
int of_allowed_acodecs
Definition: plugins.h:265
volatile float volume
audio volume level (for jack and pulse)
Definition: preferences.h:837
uint32_t audio_opts
Definition: preferences.h:830
short pb_quality
Definition: preferences.h:831
LiVESWidgetColor normal_fore
Definition: mainwindow.h:325
int style
Definition: mainwindow.h:297
LiVESWidgetColor normal_back
Definition: mainwindow.h:324
char backend[PATH_MAX *4]
Definition: preferences.h:411
boolean vj_mode
Definition: preferences.h:459
boolean save_directories
Definition: preferences.h:195
boolean show_playwin
Definition: preferences.h:292
boolean instant_open
Definition: preferences.h:301
_encoder encoder
from main.h
Definition: preferences.h:38
boolean perm_audio_reader
Definition: preferences.h:426
boolean crash_recovery
TRUE==maintain mainw->recovery file.
Definition: preferences.h:259
volatile uint32_t audio_opts
Definition: preferences.h:254
boolean hfbwnp
Definition: preferences.h:436
boolean show_recent
Definition: preferences.h:179
int audio_src
Definition: preferences.h:204
uint64_t disk_quota
Definition: preferences.h:383
boolean keep_all_audio
Definition: preferences.h:371
int play_monitor
Definition: preferences.h:306
uint64_t warning_mask
Definition: preferences.h:80
boolean safe_symlinks
Definition: preferences.h:327
boolean hide_framebar
Definition: preferences.h:434
boolean auto_trim_audio
Definition: preferences.h:370
boolean show_gui
Definition: preferences.h:290
int num_rtaudiobufs
Definition: preferences.h:325
char video_open_command[PATH_MAX *2]
Definition: preferences.h:170
double default_fps
Definition: preferences.h:173
float volume
audio volume level (for jack and pulse)
Definition: preferences.h:457
char cmd_log[PATH_MAX]
Definition: preferences.h:168
char workdir[PATH_MAX]
kept in locale encoding
Definition: preferences.h:61
boolean show_msg_area
Definition: preferences.h:225
boolean show_player_stats
Definition: preferences.h:190
boolean enc_letterbox
encode with letterbox
Definition: preferences.h:364
char def_author[1024]
TODO - add to prefs windo.
Definition: preferences.h:497
LiVESList * disabled_decoders
Definition: preferences.h:408
boolean mt_load_fuzzy
Definition: preferences.h:432
char configfile[PATH_MAX]
kept in locale encoding (config settings) [default ~/.local/config/lives)
Definition: preferences.h:63
boolean show_rdet
show render details (frame size, encoder type) before saving to file
Definition: preferences.h:261
boolean midisynch
Definition: preferences.h:181
uint32_t jack_opts
Definition: preferences.h:232
short sepwin_type
Definition: preferences.h:186
char lib_dir[PATH_MAX]
Definition: preferences.h:75
boolean concat_images
Definition: preferences.h:296
int sleep_time
Definition: preferences.h:176
boolean allow_easing
Definition: preferences.h:461
int warn_file_size
Definition: preferences.h:180
boolean btgamma
allows clips to be stored with bt709 gamma - CAUTION not backwards compatible, untested
Definition: preferences.h:453
boolean show_desktop_panel
Definition: preferences.h:483
double rec_stop_gb
Definition: preferences.h:348
boolean stop_screensaver
Definition: preferences.h:27
char backend_sync[PATH_MAX *4]
Definition: preferences.h:410
short audio_player
Definition: preferences.h:40
char image_ext[16]
Definition: preferences.h:78
short pb_quality
Definition: preferences.h:31
boolean open_maximised
Definition: preferences.h:28
boolean autoload_subs
Definition: preferences.h:345
boolean rr_crash
Definition: preferences.h:488
uint64_t capabilities
Definition: plugins.h:177
char touch_cmd[PATH_MAX]
Definition: main.h:553
int nmonitors
Definition: main.h:588
pid_t mainpid
Definition: main.h:591
int byte_order
Definition: main.h:577
lives_checkstatus_t has_mpv
Definition: main.h:513
lives_checkstatus_t has_mplayer2
Definition: main.h:512
wm_caps_t wm_caps
Definition: main.h:607
lives_checkstatus_t has_mktemp
Definition: main.h:540
lives_checkstatus_t has_gconftool_2
Definition: main.h:527
char * myname
Definition: main.h:580
lives_checkstatus_t has_xdg_screensaver
Definition: main.h:528
lives_checkstatus_t has_mplayer
Definition: main.h:511
mode_t umask
Definition: main.h:597
char * name
Definition: multitrack.h:748
char * handle
Definition: multitrack.h:746
int64_t unique_id
Definition: multitrack.h:747
LiVESList * list
Definition: multitrack.h:749
boolean asigned
Definition: plugins.h:392
int frame_width
frame is the surrounding part, including any black border (>=width)
Definition: plugins.h:357
int64_t nframes
Definition: plugins.h:349
lives_struct_def_t lsd
Definition: plugins.h:321
float video_start_time
Definition: plugins.h:362
char * URI
the URI of this cdata
Definition: plugins.h:334
char author[1024]
Definition: plugins.h:340
char comment[1024]
Definition: plugins.h:341
char title[1024]
Definition: plugins.h:339
corresponds to one clip in the GUI
Definition: main.h:877
int arps
audio physical sample rate (i.e the "normal" sample rate of the clip when played at 1,...
Definition: main.h:905
frames_t frames
number of video frames
Definition: main.h:890
binval binfmt_check
Definition: main.h:878
char file_name[PATH_MAX]
input file
Definition: main.h:923
boolean orig_file_name
Definition: main.h:926
LiVESWidget * menuentry
Definition: main.h:1011
frames_t end
Definition: main.h:891
lives_direction_t adirection
audio play direction during playback, FORWARD or REVERSE.
Definition: main.h:1016
binval binfmt_version
Definition: main.h:878
void * ext_src
points to opaque source for non-disk types
Definition: main.h:1040
lives_clip_type_t clip_type
Definition: main.h:886
int asampsize
audio sample size in bits (8 or 16)
Definition: main.h:908
lives_img_type_t img_type
Definition: main.h:887
frames_t * frame_index
index of frames for CLIP_TYPE_FILE >0 means corresponding frame within original clip -1 means corresp...
Definition: main.h:1004
boolean checked_for_old_header
Definition: main.h:1091
boolean checked
thumbnail cache, list of lives_tcache_entry_t
Definition: main.h:1101
boolean is_untitled
Definition: main.h:926
boolean deinterlace
auto deinterlace
Definition: main.h:938
double pointer_time
pointer time in timeline, + the playback start posn for clipeditor (unless playing the selection)
Definition: main.h:931
int vsize
frame height (vertical) in pixels
Definition: main.h:897
int gamma_type
Definition: main.h:903
lives_interlace_t interlace
interlace type (if known - none, topfirst, bottomfirst or : see plugins.h)
Definition: main.h:899
char type[64]
Definition: main.h:884
char title[1024]
Definition: main.h:919
int header_version
Definition: main.h:940
int achans
number of audio channels (0, 1 or 2)
Definition: main.h:907
LiVESList * layout_map
Definition: main.h:1037
boolean ratio_fps
framerate of the clip
Definition: main.h:894
double laudio_time
Definition: main.h:929
uint32_t signed_endian
bitfield
Definition: main.h:909
double pb_fps
current playback rate, may vary from fps, can be 0. or negative
Definition: main.h:1007
uint64_t unique_id
this and the handle can be used to uniquely id a file
Definition: main.h:880
frames_t frameno
Definition: main.h:934
boolean has_old_header
Definition: main.h:1091
boolean changed
Definition: main.h:915
int ovsize
Definition: main.h:975
int ext_src_type
Definition: main.h:1051
boolean needs_silent_update
needs internal update, we shouldn't concern the user
Definition: main.h:1089
char save_file_name[PATH_MAX]
Definition: main.h:924
char info_file[PATH_MAX]
used for asynch communication with externals
Definition: main.h:1009
int hsize
frame width (horizontal) in pixels (NOT macropixels !)
Definition: main.h:896
char name[CLIP_NAME_MAXLEN]
the display name
Definition: main.h:922
lives_subtitles_t * subt
Definition: main.h:1076
char author[1024]
Definition: main.h:919
size_t afilesize
Definition: main.h:912
char keywords[1024]
Definition: main.h:919
int ohsize
Definition: main.h:975
double video_time
Definition: main.h:929
int bpp
bits per pixel of the image frames, 24 or 32
Definition: main.h:901
char comment[1024]
Definition: main.h:919
int arate
current audio playback rate (varies if the clip rate is changed)
Definition: main.h:906
double real_pointer_time
pointer time in timeline, can extend beyond video, for audio
Definition: main.h:932
boolean has_binfmt
DO NOT remove or alter any fields before this ^^^^^.
Definition: main.h:998
double fps
Definition: main.h:893
binval binfmt_bytes
Definition: main.h:878
char handle[256]
Definition: main.h:881
size_t f_size
Definition: main.h:913
boolean was_in_set
Definition: main.h:916
frames_t start
Definition: main.h:891
uint64_t binfmt_end
marks the end of anything "interesring" we may want to save via binfmt extension
Definition: main.h:992
boolean was_renamed
Definition: main.h:926
int64_t(* rip_audio)(const lives_clip_data_t *, const char *fname, int64_t stframe, int64_t nframes, unsigned char **abuff)
Definition: plugins.h:443
void(* rip_audio_cleanup)(const lives_clip_data_t *cdata)
Definition: plugins.h:445
const char * name
plugin name
Definition: plugins.h:414
const lives_decoder_sys_t * decoder
Definition: plugins.h:450
lives_subtitle_type_t type
Definition: pangotext.h:39
LiVESWidget * autolives
Definition: mainwindow.h:1220
LiVESList * prefs_cache
file caches
Definition: mainwindow.h:1517
int64_t rec_samples
Definition: mainwindow.h:1527
LiVESList * xlays
immediately (to be) affected layout maps
Definition: mainwindow.h:1477
int def_width
default sizes for when no file is loaded
Definition: mainwindow.h:898
boolean gen_started_play
Definition: mainwindow.h:1694
LiVESWidget * video_draw
Definition: mainwindow.h:1383
_vid_playback_plugin * vpp
video plugin
Definition: mainwindow.h:1572
LiVESWidget * m_rewindbutton
Definition: mainwindow.h:1369
int swapped_clip
maintains the current cliplist postion even if we swap fg and bg clips
Definition: mainwindow.h:850
weed_plant_t * frame_layer
Definition: mainwindow.h:948
volatile int agen_key
which fx key is generating audio [1 based] (or 0 for none)
Definition: mainwindow.h:1649
LiVESWidget * redo
Definition: mainwindow.h:1147
volatile boolean video_seek_ready
Definition: mainwindow.h:939
int write_abuf
audio buffer number to write to (for multitrack)
Definition: mainwindow.h:1591
int img_concat_clip
when opening multiple, image files can get concatenated here (prefs->concat_images)
Definition: mainwindow.h:1561
int osc_auto
bypass user choices automatically
Definition: mainwindow.h:918
volatile short scratch
Definition: mainwindow.h:1026
char image_dir[PATH_MAX]
Definition: mainwindow.h:734
int preview_frame
Definition: mainwindow.h:1309
uint32_t signal_caught
Definition: mainwindow.h:1673
int audio_start
Definition: mainwindow.h:771
char msg[MAINW_MSG_SIZE]
Definition: mainwindow.h:724
int aud_rec_fd
fd of file we are recording audio to
Definition: mainwindow.h:1525
boolean open_deint
Definition: mainwindow.h:907
volatile ticks_t currticks
wall clock time, updated whenever lives_get_*_ticks is called
Definition: mainwindow.h:1005
int last_dprint_file
message output settings
Definition: mainwindow.h:1535
boolean fx1_bool
Definition: mainwindow.h:1053
void * pulsed
pulseaudio player
Definition: mainwindow.h:1463
LiVESWidget * laudio_draw
Definition: mainwindow.h:1383
LiVESWidget * framebar
Definition: mainwindow.h:1389
lives_clip_t * files[MAX_FILES+1]
+1 for the clipboard
Definition: mainwindow.h:729
LiVESWidget * top_vbox
Definition: mainwindow.h:1352
volatile boolean record
Definition: mainwindow.h:794
ticks_t origsecs
playback start seconds - subtracted from all other ticks to keep numbers smaller
Definition: mainwindow.h:1000
char * recovery_file
the filename of our recover file
Definition: mainwindow.h:1481
boolean oloop
Definition: mainwindow.h:766
const char * new_vpp
Definition: mainwindow.h:1573
boolean is_rendering
Definition: mainwindow.h:821
LiVESWidget * recent[N_RECENT_FILES]
Definition: mainwindow.h:1129
LiVESAccelGroup * accel_group
Definition: mainwindow.h:1228
volatile double rec_avel
Definition: mainwindow.h:968
boolean clip_switched
for recording - did we switch clips ?
Definition: mainwindow.h:793
boolean effects_paused
Definition: mainwindow.h:1055
volatile boolean loop_cont
Definition: mainwindow.h:764
char vid_save_dir[PATH_MAX]
Definition: mainwindow.h:731
LiVESIOChannel * iochan
encoder text output
Definition: mainwindow.h:1605
boolean ignore_screen_size
applied during frame reconfig events
Definition: mainwindow.h:1745
int def_height
Definition: mainwindow.h:898
LiVESWidget * record_perf
Definition: mainwindow.h:1165
LiVESWidget * preview_controls
Definition: mainwindow.h:1378
LiVESWidget * playframe
Definition: mainwindow.h:1098
LiVESTextView * optextview
Definition: mainwindow.h:1606
boolean noswitch
value set automatically to prevent 'inopportune' clip switching
Definition: mainwindow.h:1019
boolean cs_permitted
set to TRUE to allow overriding of noswitch in limited circumstances
Definition: mainwindow.h:1020
LiVESList * cliplist
hash table of clips in menu order
Definition: mainwindow.h:743
volatile lives_cancel_t cancelled
Definition: mainwindow.h:798
LiVESWidget * preview_spinbutton
Definition: mainwindow.h:1306
LiVESWidget * pf_grid
Definition: mainwindow.h:1101
boolean preview
Definition: mainwindow.h:757
boolean osc_block
TODO - make this a mutex and more finely grained : things we need to block are (clip switches,...
Definition: mainwindow.h:916
int current_file
Definition: mainwindow.h:727
boolean is_ready
Definition: mainwindow.h:787
lives_cancel_type_t cancel_type
Definition: mainwindow.h:799
LiVESWidget * message_box
Definition: mainwindow.h:1323
pthread_mutex_t clip_list_mutex
prevent adding/removing to cliplist while another thread could be reading it
Definition: mainwindow.h:1500
ticks_t orignsecs
usecs at start of playback - ditto
Definition: mainwindow.h:1001
LiVESWidget * play_window
Definition: mainwindow.h:947
LiVESWidget * eventbox4
Definition: mainwindow.h:1334
LiVESWidget * loop_video
Definition: mainwindow.h:1173
void * jackd
jack audio player / transport
Definition: mainwindow.h:1453
short endian
Definition: mainwindow.h:817
boolean loop
Definition: mainwindow.h:763
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 * frame2
Definition: mainwindow.h:1095
int untitled_number
Definition: mainwindow.h:738
LiVESWidget * spinbutton_pb_fps
Definition: mainwindow.h:1391
boolean recovering_files
Definition: mainwindow.h:1485
LiVESWidget * spinbutton_end
Definition: mainwindow.h:1288
double period
timing variables
Definition: mainwindow.h:996
volatile int blend_palette
here we can store the details of the blend file at the insertion point, if nothing changes we can tar...
Definition: mainwindow.h:980
LiVESList * recovery_list
crash recovery system
Definition: mainwindow.h:1480
boolean no_switch_dprint
Definition: mainwindow.h:1536
boolean decoders_loaded
decoders
Definition: mainwindow.h:1611
weed_plant_t * filter_map
Definition: mainwindow.h:1298
boolean fs
Definition: mainwindow.h:762
void * pulsed_read
Definition: mainwindow.h:1464
LiVESWidget * m_mutebutton
Definition: mainwindow.h:1370
boolean recoverable_layout
Definition: mainwindow.h:1483
boolean invalid_clips
Definition: mainwindow.h:1484
int pre_src_file
video file we were playing before any ext input started
Definition: mainwindow.h:971
int blend_file
background clip details
Definition: mainwindow.h:976
LiVESWidget * raudio_draw
Definition: mainwindow.h:1383
int play_sequence
currticks when last display was shown (used for fixed fps)
Definition: mainwindow.h:1013
boolean was_set
Definition: mainwindow.h:750
LiVESWidget * m_stopbutton
Definition: mainwindow.h:1369
int pwidth
PLAYBACK.
Definition: mainwindow.h:926
int pre_src_audio_file
audio file we were playing before any ext input started
Definition: mainwindow.h:972
boolean error
Definition: mainwindow.h:801
boolean ext_playback
using external video playback plugin
Definition: mainwindow.h:773
boolean suppress_dprint
tidy up, e.g. by blocking "switched to file..." and "closed file..." messages
Definition: mainwindow.h:1537
LiVESWidget * sep_image
Definition: mainwindow.h:1229
int pheight
playback height
Definition: mainwindow.h:927
int audio_end
Definition: mainwindow.h:771
weed_plant_t * audio_event
Definition: mainwindow.h:1300
pthread_mutex_t abuf_mutex
mutices
Definition: mainwindow.h:1495
frames_t play_start
Definition: mainwindow.h:931
boolean opening_loc
opening location (streaming)
Definition: mainwindow.h:790
int aud_file_to_kill
Definition: mainwindow.h:909
volatile int rec_aclip
recording values - to be inserted at the following video frame
Definition: mainwindow.h:967
boolean sep_win
Definition: mainwindow.h:761
LiVESWidget * eventbox3
Definition: mainwindow.h:1333
ulong spin_start_func
Definition: mainwindow.h:1064
char * urgency_msg
OSD.
Definition: mainwindow.h:1643
LiVESWidget * m_loopbutton
Definition: mainwindow.h:1370
volatile double rec_aseek
Definition: mainwindow.h:969
lives_funcptr_t abort_hook_func
can be set to point to a function to be run before abort, for critical functions
Definition: mainwindow.h:1081
double ptrtime
Definition: mainwindow.h:899
weed_event_t * stored_event_list
stored mt -> clip editor
Definition: mainwindow.h:804
LiVESWidget * mute_audio
Definition: mainwindow.h:1177
int fc_buttonresponse
Definition: mainwindow.h:1715
LiVESWidget * preview_box
Definition: mainwindow.h:1304
LiVESWidget * stop
Definition: mainwindow.h:1170
LiVESList * decoder_list
Definition: mainwindow.h:1612
boolean playing_sel
list of set names in current workdir, mau be NULL
Definition: mainwindow.h:756
LiVESWidget * ext_audio_mon
Definition: mainwindow.h:1359
LiVESWidget * spinbutton_start
Definition: mainwindow.h:1288
boolean jack_can_stop
Definition: mainwindow.h:934
boolean recording_recovered
Definition: mainwindow.h:1486
lives_toy_t toy_type
Definition: mainwindow.h:851
volatile boolean record_paused
pause during recording
Definition: mainwindow.h:1557
int ascrap_file
scrap file for recording audio scraps
Definition: mainwindow.h:875
char * file_open_params
extra parameters for opening special files
Definition: mainwindow.h:906
double audio_stretch
for fixed fps modes, the value is used to speed up / slow down audio
Definition: mainwindow.h:1015
lives_mt * multitrack
holds a pointer to the entire multitrack environment; NULL in Clip Edit mode
Definition: mainwindow.h:1087
boolean faded
Definition: mainwindow.h:759
boolean record_starting
start recording at next frame
Definition: mainwindow.h:1559
boolean foreign
for external window capture
Definition: mainwindow.h:824
volatile boolean agen_needs_reinit
Definition: mainwindow.h:1650
boolean save_with_sound
Definition: mainwindow.h:784
ulong pw_scroll_func
Definition: mainwindow.h:1442
boolean reverse_pb
used in osc.c
Definition: mainwindow.h:911
boolean is_processing
states
Definition: mainwindow.h:820
boolean preview_rendering
Definition: mainwindow.h:758
LiVESWidget * undo
Definition: mainwindow.h:1146
char set_name[256]
Definition: mainwindow.h:749
lives_painter_surface_t * play_surface
Definition: mainwindow.h:950
volatile int abufs_to_fill
Definition: mainwindow.h:1592
char * subt_save_file
name of file to save subtitles to
Definition: mainwindow.h:1618
uint32_t lazy
Definition: mainwindow.h:1801
int last_blend_file
Definition: mainwindow.h:976
int first_free_file
Definition: mainwindow.h:728
frames_t play_end
Definition: mainwindow.h:931
LiVESWidget * eventbox2
Definition: mainwindow.h:1332
int pred_clip
Definition: mainwindow.h:956
boolean double_size
Definition: mainwindow.h:760
LiVESWidget * m_playbutton
Definition: mainwindow.h:1369
LiVESWidget * play_image
Definition: mainwindow.h:946
boolean lockstats
Definition: mainwindow.h:1774
weed_plant_t * afilter_map
Definition: mainwindow.h:1299
volatile boolean audio_seek_ready
Definition: mainwindow.h:940
LiVESWidget * m_playselbutton
Definition: mainwindow.h:1369
int new_clip
clip we should switch to during playback; switch will happen at the designated SWITCH POINT
Definition: mainwindow.h:1022
weed_plant_t * rte_textparm
send keyboard input to this paramter (usually NULL)
Definition: mainwindow.h:1589
boolean mute
Definition: mainwindow.h:770
LiVESWidget * frame1
Definition: mainwindow.h:1094
frames_t fps_measure
show fps stats after playback
Definition: mainwindow.h:778
frames_t actual_frame
actual / last frame being displayed
Definition: mainwindow.h:959
int playing_file
which number file we are playing (or -1) [generally mainw->current_file]
Definition: mainwindow.h:943
uint32_t disk_mon
Definition: mainwindow.h:1807
weed_plant_t * frame_layer_preload
predictive caching apparatus
Definition: mainwindow.h:954
ulong spin_end_func
Definition: mainwindow.h:1065
boolean loop_locked
Definition: mainwindow.h:769
FILE * clip_header
Definition: mainwindow.h:1521
ulong record_perf_func
Definition: mainwindow.h:1066
LiVESWidget * framecounter
Definition: mainwindow.h:1390
int pre_play_file
the current file before playback started
Definition: mainwindow.h:973
LiVESXWindow * foreign_window
Definition: mainwindow.h:843
int size_warn
warn the user that incorrectly sized frames were found (threshold count)
Definition: mainwindow.h:1017
boolean is_generating
Definition: mainwindow.h:1565
boolean oloop_cont
Definition: mainwindow.h:767
void * jackd_read
dummy
Definition: mainwindow.h:1454
weed_event_t * event_list
current event_list, for recording
Definition: mainwindow.h:803
LiVESList * hdrs_cache
cache of a file header (e.g. header.lives)
Definition: mainwindow.h:1518
LiVESWidget * playarea
Definition: mainwindow.h:1321
LiVESWidget * loop_continue
Definition: mainwindow.h:1174
LiVESWidget * quit
Definition: mainwindow.h:1145
boolean is_encoding
Definition: events.h:248
LiVESWidget * debug
Definition: events.h:235
LiVESWidget * dialog
Definition: events.h:220
char * encoder_name
Definition: events.h:245
boolean non_modal
non-modal for dialogs
int monitor
monitor we are displaying on
uint64_t pan_annoy
Definition: main.h:471
uint64_t pan_res
Definition: main.h:472
#define lives_strdup_printf(fmt,...)
Definition: support.c:27
#define _(String)
Definition: support.h:44
#define P_(String, StringPlural, n)
Definition: support.h:46
uint64_t num
Definition: main.h:871
const char chars[8]
Definition: main.h:872
const char * version(void)
#define TRUE
Definition: videoplugin.h:59
#define FALSE
Definition: videoplugin.h:60
WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_present(LiVESWindow *window)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_app_paintable(LiVESWidget *widget, boolean paintable)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_container_remove(LiVESContainer *container, LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_xwindow_raise(LiVESXWindow *xwin)
void lives_set_cursor_style(lives_cursor_t cstyle, LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE void lives_menu_item_set_text(LiVESWidget *menuitem, const char *text, boolean use_mnemonic)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_unfullscreen(LiVESWindow *window)
WIDGET_HELPER_GLOBAL_INLINE int lives_widget_get_allocation_width(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_value(LiVESSpinButton *button, double value)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_bg_color(LiVESWidget *widget, LiVESWidgetState state, const LiVESWidgetColor *color)
WIDGET_HELPER_GLOBAL_INLINE char * lives_file_chooser_get_filename(LiVESFileChooser *chooser)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_frame_set_label(LiVESFrame *frame, const char *label)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_accel_group_connect(LiVESAccelGroup *group, uint32_t key, LiVESXModifierType mod, LiVESAccelFlags flags, LiVESWidgetClosure *closure)
boolean lives_window_center(LiVESWindow *window)
WIDGET_HELPER_GLOBAL_INLINE uint32_t lives_idle_add(LiVESWidgetSourceFunc function, livespointer data)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_opacity(LiVESWidget *widget, double opacity)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_button_get_active(LiVESToggleButton *button)
WIDGET_HELPER_GLOBAL_INLINE LiVESResponseType lives_dialog_run(LiVESDialog *dialog)
WIDGET_HELPER_GLOBAL_INLINE boolean clear_widget_bg(LiVESWidget *widget, lives_painter_surface_t *s)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_accel_path_disconnect(LiVESAccelGroup *group, const char *path)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_xwindow_set_keep_above(LiVESXWindow *xwin, boolean setting)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handler_unblock(livespointer instance, unsigned long handler_id)
WIDGET_HELPER_GLOBAL_INLINE boolean global_recent_manager_add(const char *full_file_name)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_queue_draw(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_fg_color(LiVESWidget *widget, LiVESWidgetState state, const LiVESWidgetColor *color)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_tool_button_set_active(LiVESToggleToolButton *button, boolean active)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_sensitive(LiVESWidget *widget, boolean state)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handler_block(livespointer instance, unsigned long handler_id)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_show(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_object_unref(livespointer object)
decrease refcount by one: if refcount==0, object is destroyed
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_queue_resize(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_frozen(LiVESWidget *widget, boolean state)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_check_menu_item_set_active(LiVESCheckMenuItem *item, boolean state)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_show_now(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE uint64_t lives_widget_get_xwinid(LiVESWidget *widget, const char *msg)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_table_set_column_homogeneous(LiVESTable *table, boolean homogeneous)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_menu_item_set_accel_path(LiVESMenuItem *menuitem, const char *path)
LIVES_GLOBAL_INLINE boolean lives_widget_destroy(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_container_add(LiVESContainer *container, LiVESWidget *widget)
void hide_cursor(LiVESXWindow *window)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_no_show_all(LiVESWidget *widget, boolean set)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_hide(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_show_all(LiVESWidget *widget)
boolean lives_widget_context_update(void)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_widget_get_parent(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_hbox_new(boolean homogeneous, int spacing)
WIDGET_HELPER_GLOBAL_INLINE boolean unhide_cursor(LiVESXWindow *window)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_text(LiVESEntry *entry, const char *text)
WIDGET_HELPER_GLOBAL_INLINE int lives_widget_get_allocation_height(LiVESWidget *widget)
char * lives_text_view_get_text(LiVESTextView *textview)
WIDGET_HELPER_GLOBAL_INLINE LiVESXWindow * lives_widget_get_xwindow(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_size_request(LiVESWidget *widget, int width, int height)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_grab_focus(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_source_remove(uint32_t handle)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_maximize(LiVESWindow *window)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_process_updates(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_queue_draw_if_visible(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_frame_get_label_widget(LiVESFrame *frame)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_accel_group_disconnect(LiVESAccelGroup *group, LiVESWidgetClosure *closure)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_range(LiVESSpinButton *button, double min, double max)
@ LIVES_CURSOR_NORMAL
must be zero
@ LIVES_CURSOR_BUSY
ulong lives_signal_connect(LiVESWidget *, const char *signal_name, ulong funcptr, livespointer data)
widget_opts_t widget_opts