LiVES  3.2.0
cvirtual.c
Go to the documentation of this file.
1 // cvirtual.c
2 // LiVES
3 // (c) G. Finch 2008 - 2020 <salsaman@gmail.com>
4 // released under the GNU GPL 3 or later
5 // see file ../COPYING or www.gnu.org for licensing details
6 
7 // functions for handling "virtual" clips (CLIP_TYPE_FILE)
8 
9 #include "main.h"
10 
11 // frame_index is for files of type CLIP_TYPE_FILE
12 // a positive number is a pointer to a frame within the video file
13 // -1 means frame is stored as the corresponding image file
14 // e.g 00000001.jpg or 00000010.png etc.
15 
16 #include "resample.h"
17 #include "cvirtual.h"
18 
21  frames_t count = 0;
22  for (register int i = start - 1; i < end; i++) if (findex[i] != -1) count++;
23  return count;
24 }
25 
26 
27 boolean create_frame_index(int fileno, boolean init, frames_t start_offset, frames_t nframes) {
28  lives_clip_t *sfile = mainw->files[fileno];
29  size_t idxsize = (ALIGN_CEIL(nframes * sizeof(frames_t), DEF_ALIGN)) / DEF_ALIGN;
30  if (!IS_VALID_CLIP(fileno) || sfile->frame_index) return FALSE;
31  sfile->frame_index = (frames_t *)lives_calloc(idxsize, DEF_ALIGN);
32  if (!sfile->frame_index) return FALSE;
33  if (init) for (int i = 0; i < sfile->frames; i++) sfile->frame_index[i] = i + start_offset;
34  return TRUE;
35 }
36 
37 
38 static boolean extend_frame_index(int fileno, frames_t start, frames_t end) {
39  lives_clip_t *sfile = mainw->files[fileno];
40  size_t idxsize = (ALIGN_CEIL(end * sizeof(frames_t), DEF_ALIGN)) / DEF_ALIGN;
41  if (!IS_VALID_CLIP(fileno) || start > end) return FALSE;
42  if (sfile->frame_index_back) lives_free(sfile->frame_index_back);
43  sfile->frame_index_back = sfile->frame_index;
44  sfile->frame_index = (frames_t *)lives_calloc(idxsize, DEF_ALIGN);
45  if (!sfile->frame_index) {
46  sfile->frame_index = sfile->frame_index_back;
47  sfile->frame_index_back = NULL;
48  return FALSE;
49  }
50  for (int i = start; i < end; i++) sfile->frame_index[i] = -1;
51  return TRUE;
52 }
53 
54 
55 // save frame_index to disk
56 boolean save_frame_index(int fileno) {
57  int fd, i;
58  int retval;
59  char *fname, *fname_new;
60  lives_clip_t *sfile = mainw->files[fileno];
61 
62  if (fileno == 0) return TRUE;
63 
64  if (!sfile || !sfile->frame_index) return FALSE;
65 
66  fname = lives_build_filename(prefs->workdir, sfile->handle, FRAME_INDEX_FNAME "." LIVES_FILE_EXT_BACK, NULL);
67  fname_new = lives_build_filename(prefs->workdir, sfile->handle, FRAME_INDEX_FNAME, NULL);
68 
69  do {
70  retval = 0;
72  if (fd < 0) {
73  retval = do_write_failed_error_s_with_retry(fname, lives_strerror(errno));
74  } else {
75  for (i = 0; i < sfile->frames; i++) {
76  lives_write_le_buffered(fd, &sfile->frame_index[i], sizeof(frames_t), TRUE);
77  if (THREADVAR(write_failed) == fd + 1) {
78  THREADVAR(write_failed) = 0;
79  break;
80  }
81  }
82 
84 
85  if (mainw->is_exiting) return TRUE;
86 
87  if (THREADVAR(write_failed) == fd + 1) {
88  THREADVAR(write_failed) = 0;
89  retval = do_write_failed_error_s_with_retry(fname, NULL);
90  } else {
91  if (sget_file_size(fname) != (off_t)sfile->frames * sizeof(frames_t)) {
92  retval = do_write_failed_error_s_with_retry(fname, NULL);
93  } else {
94  lives_cp(fname, fname_new);
95  if (sget_file_size(fname_new) != (off_t)sfile->frames * sizeof(frames_t)) {
96  retval = do_write_failed_error_s_with_retry(fname, NULL);
97  // *INDENT-OFF*
98  }}}}
99  // *INDENT-ON*
100  } while (retval == LIVES_RESPONSE_RETRY);
101 
102  lives_free(fname);
103  lives_free(fname_new);
104 
105  if (retval == LIVES_RESPONSE_CANCEL) return FALSE;
106 
107  return TRUE;
108 }
109 
110 // load frame_index from disk
111 // returns -1 (error)
112 // or maxframe pointed to in clip
113 
115  lives_clip_t *sfile = mainw->files[fileno];
116  off_t filesize;
117  char *fname, *fname_back;
118  boolean backuptried = FALSE;
119  int fd, retval;
120  frames_t maxframe = -1;
121 
122  int i;
123 
124  if (!sfile || sfile->frame_index) return -1;
125 
126  lives_freep((void **)&sfile->frame_index);
127 
128  fname = lives_build_filename(prefs->workdir, sfile->handle, FRAME_INDEX_FNAME, NULL);
129  filesize = sget_file_size(fname);
130 
131  if (filesize <= 0) {
132  lives_free(fname);
133  return 0;
134  }
135 
136  if (filesize >> 2 > (off_t)sfile->frames) sfile->frames = (frames_t)(filesize >> 2);
137  fname_back = lives_build_filename(prefs->workdir, sfile->handle, FRAME_INDEX_FNAME "." LIVES_FILE_EXT_BACK, NULL);
138 
139  do {
140  retval = 0;
141  fd = lives_open_buffered_rdonly(fname);
142  if (fd < 0) {
143  THREADVAR(read_failed) = 0;
144  retval = do_read_failed_error_s_with_retry(fname, lives_strerror(errno));
145  if (!backuptried) {
146  fd = lives_open_buffered_rdonly(fname_back);
147  if (fd >= 0) {
149  if (findex_bk_dialog(fname_back)) {
150  lives_cp(fname_back, fname);
151  backuptried = TRUE;
152  continue;
153  }
154  }
155  } else if (sfile->frame_index_back) {
156  if (findex_bk_dialog(fname_back)) {
157  sfile->frame_index = sfile->frame_index_back;
158  }
159  }
160  if (retval == LIVES_RESPONSE_CANCEL) {
161  lives_free(fname);
162  lives_free(fname_back);
163  return -1;
164  }
165  } else {
166  LiVESResponseType response;
167  char *what = (_("creating the frame index for the clip"));
168  do {
169  response = LIVES_RESPONSE_OK;
170  create_frame_index(fileno, FALSE, 0, sfile->frames);
171  if (!cfile->frame_index) {
172  response = do_memory_error_dialog(what, sfile->frames * sizeof(frames_t));
173  }
174  } while (response == LIVES_RESPONSE_RETRY);
175  lives_free(what);
176  if (response == LIVES_RESPONSE_CANCEL) {
177  break;
178  }
179 
180  for (i = 0; i < sfile->frames; i++) {
181  lives_read_le_buffered(fd, &sfile->frame_index[i], sizeof(frames_t), FALSE);
182  if (THREADVAR(read_failed) == fd + 1) {
183  break;
184  }
185  if (sfile->frame_index[i] > maxframe) {
186  maxframe = sfile->frame_index[i];
187  }
188  }
190 
191  if (THREADVAR(read_failed) == fd + 1) {
192  THREADVAR(read_failed) = 0;
193  retval = do_read_failed_error_s_with_retry(fname, NULL);
194  }
195 
196  if (!backuptried) {
197  backuptried = TRUE;
198  fd = lives_open_buffered_rdonly(fname_back);
199  if (fd >= 0) {
200  LiVESList *list = NULL;
201  frames_t vframe;
202  int count = 0;
203  for (; lives_read_le_buffered(fd, &vframe, sizeof(frames_t), TRUE) == sizeof(frames_t); count++) {
204  if (THREADVAR(read_failed) == fd + 1) break;
205  list = lives_list_prepend(list, LIVES_INT_TO_POINTER(vframe));
206  }
208  if (THREADVAR(read_failed) == fd + 1) {
209  THREADVAR(read_failed) = 0;
210  } else if (count) {
211  frames_t *f_index = sfile->frame_index;
212  list = lives_list_reverse(list);
213  lives_freep((void **)&sfile->frame_index_back);
214  sfile->frame_index = NULL;
215  create_frame_index(fileno, FALSE, 0, count);
216  sfile->frame_index_back = sfile->frame_index;
217  sfile->frame_index = f_index;
218  if (sfile->frame_index_back) {
219  LiVESList *xlist;
220  sfile->old_frames = count;
221  count = 0;
222  for (xlist = list; xlist; xlist = xlist->next) {
223  sfile->frame_index_back[count++] = LIVES_POINTER_TO_INT(xlist->data);
224  // *INDENT-OFF*
225  }}}
226  if (list) lives_list_free(list);
227  }}}} while (retval == LIVES_RESPONSE_RETRY);
228  // *INDENT-ON*
229 
230  lives_free(fname);
231  lives_free(fname_back);
232 
233  if (maxframe >= 0) sfile->clip_type = CLIP_TYPE_FILE;
234  return ++maxframe;
235 }
236 
237 
239  // physically delete the frame_index for a clip
240  // only done once all
241 
242  char *idxfile;
243 
244  // cannot call check_if_non_virtual() else we end up recursing
245 
246  if (sfile->frame_index) {
247  for (frames_t i = 1; i <= sfile->frames; i++) {
248  if (sfile->frame_index[i - 1] != -1) {
249  LIVES_ERROR("deleting frame_index with virtual frames in it !");
250  return;
251  }
252  }
253  }
254 
255  if (sfile != clipboard) {
256  idxfile = lives_build_filename(prefs->workdir, sfile->handle, FRAME_INDEX_FNAME, NULL);
257  lives_rm(idxfile);
258  lives_free(idxfile);
259  }
260 
261  lives_freep((void **)&sfile->frame_index);
262 }
263 
264 
265 static frames_t scan_frames(lives_clip_t *sfile, frames_t vframes, frames_t last_real_frame) {
266  frames_t i;
267  for (i = 0; i < sfile->frames; i++) {
268  // assume all real frames up to last_real_frame are there
269  if ((sfile->frame_index[i] == -1 && i >= last_real_frame) || (sfile->frame_index[i] > vframes)) return i;
270  }
271  return i;
272 }
273 
274 
276  lives_img_type_t ximgtype;
277  int nimty = (int)N_IMG_TYPES;
278  char *fname;
279  for (frames_t i = sfile->frames - 1; i >= 0; i--) {
280  if (!sfile->frame_index || sfile->frame_index[i] == -1) {
281  for (int j = 1; j < nimty; j++) {
282  ximgtype = (lives_img_type_t)j;
283  fname = make_image_file_name(sfile, i + 1, get_image_ext_for_type(ximgtype));
284  if (lives_file_test(fname, LIVES_FILE_TEST_EXISTS)) {
285  lives_free(fname);
286  return j;
287  }
288  lives_free(fname);
289  // *INDENT-OFF*
290  }}}
291  // *INDENT-ON*
292  return IMG_TYPE_BEST;
293 }
294 
295 
296 boolean check_clip_integrity(int fileno, const lives_clip_data_t *cdata, frames_t maxframe) {
297  lives_clip_t *sfile = mainw->files[fileno], *binf = NULL;
298  lives_img_type_t empirical_img_type = sfile->img_type, oemp = empirical_img_type;
299  lives_img_type_t ximgtype;
300  frames_t last_real_frame = sfile->frames;
301  int nimty = (int)N_IMG_TYPES, j;
302  boolean has_missing_frames = FALSE, bad_imgfmts = FALSE;
303  boolean mismatch = FALSE;
304  boolean isfirst = TRUE;
305  boolean backup_more_correct = FALSE;
306  char *fname;
307 
308  frames_t i;
309  // check clip integrity upon loading
310 
311  // check that cached values match with sfile (on disk) values
312  // also check sfile->frame_index to make sure all frames are present
313 
314  // return FALSE if we find any omissions/inconsistencies
315 
316  /* if (sfile->frames > maxframe) { */
317  /* has_missing_frames = TRUE; */
318  /* sfile->frames = maxframe; */
319  /* } */
320 
321  if (prefs->vj_mode) return TRUE;
322 
323  // check the image type
324  for (i = sfile->frames - 1; i >= 0; i--) {
325  if (!sfile->frame_index || sfile->frame_index[i] == -1) {
326  // this is a non-virtual frame
327  ximgtype = empirical_img_type;
328  fname = NULL;
329  if (ximgtype != IMG_TYPE_UNKNOWN) fname = make_image_file_name(sfile, i + 1, get_image_ext_for_type(ximgtype));
330  if (!fname || !lives_file_test(fname, LIVES_FILE_TEST_EXISTS)) {
331  if (fname) lives_free(fname);
332  for (j = 1; j < nimty; j++) {
333  ximgtype = (lives_img_type_t)j;
334  if (ximgtype == empirical_img_type) continue;
335  fname = make_image_file_name(sfile, i + 1, get_image_ext_for_type(ximgtype));
336  if (lives_file_test(fname, LIVES_FILE_TEST_EXISTS)) {
337  if (isfirst) {
338  empirical_img_type = ximgtype;
339  if (oemp == IMG_TYPE_UNKNOWN) oemp = ximgtype;
340  } else {
341  if (ximgtype == oemp) empirical_img_type = oemp;
342  bad_imgfmts = TRUE;
343  }
344  lives_free(fname);
345  isfirst = FALSE;
346  break;
347  }
348  lives_free(fname);
349  }
350  if (j == nimty) {
351  has_missing_frames = TRUE;
352  if (prefs->show_dev_opts) {
353  g_printerr("clip %s is missing image frame %d\n", sfile->handle, i + 1);
354  }
355  } else {
356  last_real_frame = i;
357  isfirst = FALSE;
358  // *INDENT-OFF*
359  }}
360  else lives_free(fname);
361  }}
362  // *INDENT-ON*
363 
364  if (empirical_img_type == IMG_TYPE_UNKNOWN) {
366  empirical_img_type = sfile->img_type = IMG_TYPE_BEST; // read_headers() will have set this to "jpeg" (default)
367  }
368 
369  if (cdata) {
370  // check frame count
371  if (maxframe > cdata->nframes || has_missing_frames) {
372  if (prefs->show_dev_opts) {
373  if (maxframe > cdata->nframes) {
374  g_printerr("frame count mismatch for clip %d, %s, maxframe is %d, decoder claims only %ld\nRescaning...",
375  fileno, sfile->handle, maxframe, cdata-> nframes);
376  }
377  }
378 
379  has_missing_frames = TRUE;
380  sfile->frames = scan_frames(sfile, cdata->nframes, last_real_frame);
381  if (prefs->show_dev_opts) {
382  g_printerr("rescan counted %d frames\n.", sfile->frames);
383  }
384  }
385  }
386 
387  if (sfile->frame_index) {
388  frames_t lgoodframe = -1;
389  int goodidx;
390  frames_t xframes = sfile->frames;
391 
392  if (sfile->frame_index_back) {
393  if (sfile->old_frames > sfile->frames) xframes = sfile->old_frames;
394  backup_more_correct = TRUE;
395  }
396 
397  // check and attempt to correct frame_index
398  for (i = 0; i < xframes; i++) {
399  frames_t fr;
400  if (i < sfile->frames) fr = sfile->frame_index[i];
401  else fr = sfile->frame_index_back[i];
402  if (fr < -1 || (!cdata && (frames64_t)fr > sfile->frames - 1)
403  || (cdata && (frames64_t)fr > cdata->nframes - 1)) {
404  if (i >= sfile->frames) {
405  backup_more_correct = FALSE;
406  break;
407  }
408  if (backup_more_correct && i < sfile->old_frames) {
409  frames_t fr2 = sfile->frame_index_back[i];
410  if (fr2 < -1 || (!cdata && (frames64_t)fr2 > sfile->frames - 1)
411  || (cdata && (frames64_t)fr2 > cdata->nframes - 1)) {
412  backup_more_correct = FALSE;
413  }
414  }
415 
416  if (prefs->show_dev_opts) {
417  g_printerr("bad frame index %d, points to %d.....", i, fr);
418  }
419  if (fr < sfile->frames) has_missing_frames = TRUE;
420  fname = make_image_file_name(sfile, i + 1, get_image_ext_for_type(empirical_img_type));
421  if (lives_file_test(fname, LIVES_FILE_TEST_EXISTS)) {
422  sfile->frame_index[i] = -1;
423  if (prefs->show_dev_opts) {
424  g_printerr("relinked to image frame %d\n", i + 1);
425  }
426  } else {
427  if (backup_more_correct && i < sfile->old_frames && sfile->frame_index_back[i] == -1)
428  backup_more_correct = FALSE;
429  if (lgoodframe != -1) {
430  sfile->frame_index[i] = lgoodframe + i - goodidx;
431  if (prefs->show_dev_opts) {
432  g_printerr("relinked to clip frame %d\n", lgoodframe + i - goodidx);
433  }
434  } else {
435  sfile->frame_index[i] = i;
436  if (prefs->show_dev_opts) {
437  g_printerr("reset to clip frame %d\n", i);
438  }
439  }
440  if (sfile->frame_index[i] >= cdata->nframes) sfile->frame_index[i] = cdata->nframes - 1;
441  }
442  lives_free(fname);
443  } else {
444  if (cdata && fr != -1) {
445  lgoodframe = fr;
446  goodidx = i;
447  // *INDENT-OFF*
448  }}}}
449  // *INDENT-ON*
450  if (has_missing_frames && backup_more_correct) {
451  lives_freep((void **)&sfile->frame_index);
452  sfile->frame_index = sfile->frame_index_back;
453  if (sfile->old_frames > sfile->frames) {
454  sfile->frames = sfile->old_frames;
455  sfile->frames = scan_frames(sfile, sfile->frames, last_real_frame);
456  } else sfile->frames = sfile->old_frames;
457  }
458 
459  if (sfile->frames > 0) {
460  int hsize = sfile->hsize, chsize = hsize;
461  int vsize = sfile->vsize, cvsize = vsize;
462  frames_t last_img_frame = -1;
463  if (last_real_frame > 0) {
464  if (sfile->frame_index) {
465  for (i = last_real_frame; i > 0; i--) {
466  if (sfile->frame_index[i - 1] == -1) {
467  last_img_frame = i;
468  break;
469  }
470  }
471  } else last_img_frame = last_real_frame;
472  if (last_img_frame > -1) {
473  sfile->img_type = empirical_img_type;
474  get_frames_sizes(fileno, last_img_frame, &hsize, &vsize);
475  }
476  }
477 
478  if (cdata) {
479  if (!prefs->auto_nobord) {
481  cvsize = cdata->frame_height;
482  } else {
484  cvsize = cdata->height;
485  }
486  }
487 
488  if (chsize == hsize && hsize != sfile->hsize) sfile->hsize = hsize;
489  if (cvsize == vsize && vsize != sfile->vsize) sfile->vsize = vsize;
490 
491  if (last_real_frame > 0) {
492  if (hsize == sfile->hsize && vsize == sfile->vsize) {
493  frames_t fframe = 0;
496  if (sfile->clip_type == CLIP_TYPE_DISK) fframe = 1;
497  else {
498  for (i = 1; i < last_real_frame; i++) {
499  if (sfile->frame_index[i - 1] == -1) {
500  fname = make_image_file_name(sfile, i, get_image_ext_for_type(empirical_img_type));
501  if (lives_file_test(fname, LIVES_FILE_TEST_EXISTS)) {
502  fframe = i;
503  lives_free(fname);
504  break;
505  }
506  has_missing_frames = TRUE;
507  lives_free(fname);
508  // *INDENT-OFF*
509  }}}
510  if (fframe) get_frames_sizes(fileno, fframe, &hsize, &vsize);
511  }}
512  // *INDENT-ON*
513 
514  if (sfile->hsize != hsize || sfile->vsize != vsize) {
515  LiVESResponseType resp = do_resize_dlg(sfile->hsize, sfile->vsize, hsize, vsize);
516  if (prefs->show_dev_opts) {
517  g_printerr("incorrect frame size %d X %d, corrected to %d X %d\n", hsize, vsize, sfile->hsize, sfile->vsize);
518  }
519  if (resp == LIVES_RESPONSE_ACCEPT) {
520  sfile->hsize = hsize;
521  sfile->vsize = vsize;
522  } else if (resp == LIVES_RESPONSE_YES) {
523  int missing = 0, nbadsized = 0;
525  do_threaded_dialog(_("Resizing all frames\n"), TRUE);
527  if (resize_all(fileno, sfile->hsize, sfile->vsize, empirical_img_type, FALSE,
528  &nbadsized, &missing)) {
529  g_printerr("resize detected %d bad sized, %d missing \n", nbadsized, missing);
530  if (missing) has_missing_frames = TRUE;
531  if (mainw->cancelled == CANCEL_NONE) bad_imgfmts = FALSE;
532  else mismatch = TRUE;
533  }
537  } else mismatch = TRUE;
538  }
539  }
540  if (bad_imgfmts) {
541  LiVESResponseType resp = do_imgfmts_error(empirical_img_type);
542  if (resp == LIVES_RESPONSE_OK) {
543  int missing = 0, nbadsized = 0;
545  do_threaded_dialog(_("Correcting Image Formats\n"), TRUE);
546  if (resize_all(fileno, sfile->hsize, sfile->vsize, empirical_img_type, FALSE,
547  &nbadsized, &missing)) {
548  g_printerr("change fmts detected %d bad sized, %d missing \n", nbadsized, missing);
549  if (missing) has_missing_frames = TRUE;
550  if (mainw->cancelled == CANCEL_NONE) bad_imgfmts = FALSE;
551  else mismatch = TRUE;
552  }
556  } else mismatch = TRUE;
558  }
559 
560  if (has_missing_frames) mismatch = TRUE;
561  else {
562  if (sfile->frame_index) {
563  for (i = 0; i < sfile->frames; i++) {
564  if (sfile->frame_index[i] != -1) {
565  fname = make_image_file_name(sfile, i + 1, get_image_ext_for_type(empirical_img_type));
566  if (lives_file_test(fname, LIVES_FILE_TEST_EXISTS)) {
567  lives_rm(fname);
568  // *INDENT-OFF*
569  }
570  lives_free(fname);
571  }}}}
572  // *INDENT-ON*
573  if (cdata && (fabs(sfile->fps - (double)cdata->fps) > prefs->fps_tolerance)) {
574  if (prefs->show_dev_opts) {
575  g_printerr("fps mismtach, claimed %f, cdata said %f\n", sfile->fps, cdata->fps);
576  }
577  mismatch = TRUE;
578  }
579  if (sfile->img_type != empirical_img_type) {
580  if (prefs->show_dev_opts) {
581  g_printerr("corrected image type from %d to %d\n", sfile->img_type, empirical_img_type);
582  }
583  sfile->img_type = empirical_img_type;
584  }
585 
586  if (mismatch) goto mismatch;
587 
588  /*
589  // ignore since we may have resampled audio
590  if (sfile->achans != cdata->achans || sfile->arps != cdata->arate || sfile->asampsize != cdata->asamps ||
591  cdata->asigned == (sfile->signed_endian & AFORM_UNSIGNED)) return FALSE;
592  */
593 
594  // all things equal as far as we can tell
595  return TRUE;
596 
597 mismatch:
598  // something mismatched - commence further investigation
599 
600  if ((binf = clip_forensic(mainw->current_file))) {
601  if (has_missing_frames) {
602  if (cdata) {
603  if (binf->frames == cdata->nframes && binf->frames < sfile->frames) sfile->frames = binf->frames;
604  else if (binf->frames == sfile->frames && binf->frames < sfile->frames) {
605  if (sfile->frames > cdata->nframes) if (!extend_frame_index(fileno, cdata->nframes, sfile->frames)) return FALSE;
606  ((lives_clip_data_t *)cdata)->nframes = sfile->frames;
607  }
608  } else if (binf->frames <= sfile->frames) sfile->frames = binf->frames;
609  }
610  if (binf->fps == cdata->fps) {
611  ((lives_clip_data_t *)cdata)->fps = sfile->pb_fps = sfile->fps;
612  }
613  }
614 
615  sfile->img_type = empirical_img_type;
616 
617  sfile->needs_update = TRUE;
618 
619  sfile->afilesize = reget_afilesize_inner(fileno);
620 
621  if (has_missing_frames && sfile->frame_index) {
622  if (sfile->frames > maxframe) extend_frame_index(fileno, maxframe, sfile->frames);
623  save_frame_index(fileno);
624  }
625  return FALSE;
626 }
627 
628 
630  // check all franes in frame_index betweem start and end inclusive
631  // if we find a virtual frame, we stop checking and return the frame number
632  // if all are non - virtual we return 0
633  lives_clip_t *sfile = mainw->files[fileno];
634 
635  if (!sfile->frame_index) return 0;
636  for (frames_t i = start; i <= end; i++) {
637  if (sfile->frame_index[i - 1] != -1) return i;
638  }
639 
640  return 0;
641 }
642 
643 
644 boolean check_if_non_virtual(int fileno, frames_t start, frames_t end) {
645  // check if there are no virtual frames from start to end inclusive in clip fileno
646 
647  // return FALSE if any virtual frames are found in the region
648  // return TRUE if all frames in region are non-virtual
649 
650  // also may change the clip_type and the interlace
651 
652  lives_clip_t *sfile = mainw->files[fileno];
653  frames_t i;
654 
655  if (sfile->clip_type != CLIP_TYPE_FILE) return TRUE;
656 
657  if (sfile->frame_index) {
658  for (i = start; i <= end; i++) {
659  if (sfile->frame_index[i - 1] != -1) return FALSE;
660  }
661  }
662 
663  if (start > 1 || end < sfile->frames) return TRUE;
664 
665  // no virtual frames in entire clip - change to CLIP_TYPE_DISK
666 
667  sfile->clip_type = CLIP_TYPE_DISK;
668  del_frame_index(sfile);
669  close_clip_decoder(fileno);
670 
671  if (sfile->interlace != LIVES_INTERLACE_NONE) {
672  sfile->interlace = LIVES_INTERLACE_NONE; // all frames should have been deinterlaced
673  sfile->deinterlace = FALSE;
674  if (fileno > 0) {
675  if (!save_clip_value(fileno, CLIP_DETAILS_INTERLACE, &sfile->interlace))
676  do_header_write_error(fileno);
677  }
678  }
679 
680  return TRUE;
681 }
682 
683 #define DS_SPACE_CHECK_FRAMES 100
684 
685 static boolean save_decoded(int fileno, frames_t i, LiVESPixbuf * pixbuf, boolean silent, int progress) {
686  lives_clip_t *sfile = mainw->files[fileno];
687  boolean retb;
688  int retval;
689  LiVESError *error = NULL;
690  char *oname = make_image_file_name(sfile, i, get_image_ext_for_type(sfile->img_type));
691 
692  do {
693  retval = LIVES_RESPONSE_NONE;
694  retb = lives_pixbuf_save(pixbuf, oname, sfile->img_type, 100 - prefs->ocp, sfile->hsize, sfile->vsize, &error);
695  if (error && !silent) {
696  retval = do_write_failed_error_s_with_retry(oname, error->message);
697  lives_error_free(error);
698  error = NULL;
699  } else if (!retb) {
700  retval = do_write_failed_error_s_with_retry(oname, NULL);
701  }
702  } while (retval == LIVES_RESPONSE_RETRY);
703 
704  lives_freep((void **)&oname);
705 
706  if (progress % DS_SPACE_CHECK_FRAMES == 1) {
707  if (!check_storage_space(fileno, FALSE)) {
708  retval = LIVES_RESPONSE_CANCEL;
709  }
710  }
711 
712  if (retval == LIVES_RESPONSE_CANCEL) return FALSE;
713  return TRUE;
714 }
715 
716 
717 #define STRG_CHECK 1000
718 
719 frames_t virtual_to_images(int sfileno, frames_t sframe, frames_t eframe, boolean update_progress, LiVESPixbuf **pbr) {
720  // pull frames from a clip to images
721  // from sframe to eframe inclusive (first frame is 1)
722 
723  // if update_progress, set mainw->msg with number of frames pulled
724 
725  // should be threadsafe apart from progress update
726 
727  // if pbr is non-null, it will be set to point to the pulled pixbuf
728 
729  // return FALSE on write error
730 
731  lives_clip_t *sfile = mainw->files[sfileno];
732  LiVESPixbuf *pixbuf = NULL;
733  lives_proc_thread_t tinfo = THREADVAR(tinfo);
734  int progress = 1, count = 0;
735  frames_t i;
736 
737  if (tinfo) lives_proc_thread_set_cancellable(tinfo);
738 
739  if (sframe < 1) sframe = 1;
740 
741  for (i = sframe; i <= eframe; i++) {
742  if (i > sfile->frames) break;
743 
744  if (sfile->pumper && lives_proc_thread_cancelled(sfile->pumper)) break;
745 
746  if (update_progress) {
747  threaded_dialog_spin((double)(i - sframe) / (double)(eframe - sframe + 1));
748  }
749 
750  if (sfile->frame_index[i - 1] >= 0) {
751  if (pbr && pixbuf) lives_widget_object_unref(pixbuf);
752 
753  pixbuf = pull_lives_pixbuf_at_size(sfileno, i, get_image_ext_for_type(sfile->img_type),
754  q_gint64((i - 1.) / sfile->fps, sfile->fps), sfile->hsize,
755  sfile->vsize, LIVES_INTERP_BEST, FALSE);
756 
757  if (!pixbuf) return -i;
758  if (!save_decoded(sfileno, i, pixbuf, pbr != NULL, progress)) {
760  return -i;
761  }
762  if (!pbr) {
763  if (pixbuf) lives_widget_object_unref(pixbuf);
764  pixbuf = NULL;
765  }
766  if (++count == STRG_CHECK) {
767  if (!check_storage_space(-1, TRUE)) break;
768  }
769 
770  // another thread may have called check_if_non_virtual - TODO : use a mutex
771  if (!sfile->frame_index) break;
772  sfile->frame_index[i - 1] = -1;
773 
774  if (update_progress) {
775  // sig_progress...
776  lives_snprintf(mainw->msg, MAINW_MSG_SIZE, "%d", progress++);
777  threaded_dialog_spin((double)(i - sframe) / (double)(eframe - sframe + 1));
779  }
780 
781  if (mainw->cancelled != CANCEL_NONE) {
782  if (!check_if_non_virtual(sfileno, 1, sfile->frames)) save_frame_index(sfileno);
783  if (pbr) *pbr = pixbuf;
784  return i;
785  }
786  }
787  }
788 
789  if (pbr) *pbr = pixbuf;
790  if (!check_if_non_virtual(sfileno, 1, sfile->frames) && !save_frame_index(sfileno)) {
792  return -i;
793  }
794  return i;
795 }
796 
797 
798 static void restore_gamma_cb(int gamma_type) {
799  // experimental, will move to another file
800  lives_clip_t *ocb = clipboard, *ncb;
801  LiVESPixbuf *pixbuf;
802  int cf = mainw->current_file;
803  int ogamma;
804  int i, found = -1, progress = 0;
805  boolean is_stored = FALSE;
806 
807  for (i = 0; i < mainw->ncbstores; i++) {
808  if (mainw->cbstores[i] == clipboard) is_stored = TRUE;
809  if (mainw->cbstores[i]->gamma_type == cfile->gamma_type) found = i;
810  if (found > -1 && is_stored) break;
811  }
812  if (!is_stored) {
813  if (mainw->ncbstores >= MAX_CBSTORES) return;
815  }
816  if (found > -1) {
817  clipboard = mainw->cbstores[found];
818  return;
819  }
820  // not found,
821  // we'll actually make a copy of the clipboard but with the new gamma_type
822  clipboard = NULL;
823  init_clipboard();
824  lives_memcpy(clipboard, ocb, sizeof(lives_clip_t));
825  lives_memcpy(clipboard->frame_index, ocb->frame_index, clipboard->frames * sizeof(frames_t));
826  ncb = clipboard;
827  ogamma = ocb->gamma_type;
828  ocb->gamma_type = ncb->gamma_type = gamma_type; // force conversion
829  for (i = 0; i < clipboard->frames; i++) {
830  if (clipboard->frame_index[i] == -1) {
831  progress++;
832  clipboard = ocb;
834  0, 0, 0, LIVES_INTERP_BEST, FALSE);
835  clipboard = ncb;
836  if (!save_decoded(0, i, pixbuf, FALSE, progress)) {
837  mainw->current_file = 0;
838  close_current_file(cf);
839  clipboard = ocb;
840  ocb->gamma_type = ogamma;
841  return;
842  }
843  }
844  }
845  ocb->gamma_type = ogamma;
846 }
847 
848 
849 frames_t realize_all_frames(int clipno, const char *msg, boolean enough) {
850  // if enough is set, we show Enough button instead of Cancel.
851  frames_t ret;
852  int current_file = mainw->current_file;
854  if (!IS_VALID_CLIP(clipno)) return 0;
855 
856  // if its the clipboard and we have exotic gamma types we need to do a special thing
857  // - fix the gamma_type of the clipboard existing frames before inserting in cfile
858  if (clipno == 0 && prefs->btgamma && CURRENT_CLIP_HAS_VIDEO && cfile->gamma_type
859  != clipboard->gamma_type) {
860  restore_gamma_cb(cfile->gamma_type);
861  }
862 
863  if (!check_if_non_virtual(clipno, 1, mainw->files[clipno]->frames)) {
864  mainw->current_file = clipno;
865  cfile->progress_start = 1;
866  cfile->progress_end = count_virtual_frames(cfile->frame_index, 1, cfile->frames);
867  if (enough) mainw->cancel_type = CANCEL_SOFT; // force "Enough" button to be shown
868  do_threaded_dialog((char *)msg, TRUE);
871  ret = virtual_to_images(mainw->current_file, 1, cfile->frames, TRUE, NULL);
873  mainw->current_file = current_file;
874 
875  if (mainw->cancelled != CANCEL_NONE) {
877  return ret;
878  }
879  if (ret <= 0) return ret;
880  }
881  return mainw->files[clipno]->frames;
882 }
883 
884 
885 void insert_images_in_virtual(int sfileno, frames_t where, frames_t frames, frames_t *frame_index, frames_t start) {
886  // insert physical (frames) images (or virtual possibly) into sfile at position where [0 = before first frame]
887  // this is the virtual (book-keeping) part
888 
889  // need to update the frame_index
890 
891  // this is for clip type CLIP_TYPE_FILE only
892 
893  lives_clip_t *sfile = mainw->files[sfileno];
894  LiVESResponseType response;
895 
896  char *what;
897  frames_t nframes = sfile->frames;
898  frames_t i, j = start - 1;
899 
900  if (!sfile->frame_index) return;
901 
902  what = (_("creating the new frame index for the clip"));
903  lives_freep((void **)&sfile->frame_index_back);
904 
905  sfile->frame_index_back = sfile->frame_index;
906  sfile->frame_index = NULL;
907 
908  do {
909  response = LIVES_RESPONSE_OK;
910  create_frame_index(sfileno, FALSE, 0, nframes + frames);
911  if (!sfile->frame_index) {
912  response = do_memory_error_dialog(what, (nframes + frames) * sizeof(frames_t));
913  }
914  } while (response == LIVES_RESPONSE_RETRY);
915  lives_free(what);
916  if (response == LIVES_RESPONSE_CANCEL) {
917  sfile->frame_index = sfile->frame_index_back;
918  sfile->frame_index_back = NULL;
919  return;
920  }
921 
922  lives_memcpy(sfile->frame_index, sfile->frame_index_back, where * sizeof(frames_t));
923 
924  for (i = where; i < where + frames; i++) {
925  if (frame_index && frame_index[j] != -1) sfile->frame_index[i] = frame_index[j];
926  else sfile->frame_index[i] = -1;
927  if (++j >= sfile->frames) j = 0;
928  }
929 
930  lives_memcpy(&sfile->frame_index[where + frames], &sfile->frame_index_back[where], (nframes - where) * sizeof(frames_t));
931 
932  sfile->frames += frames;
933  save_frame_index(sfileno);
934  sfile->frames -= frames;
935 }
936 
937 
938 void delete_frames_from_virtual(int sfileno, frames_t start, frames_t end) {
939  // delete (frames) images from sfile at position start to end
940  // this is the virtual (book-keeping) part
941 
942  // need to update the frame_index
943 
944  // this is for clip type CLIP_TYPE_FILE only
945 
946  lives_clip_t *sfile = mainw->files[sfileno];
947  LiVESResponseType response;
948 
949  char *what = (_("creating the new frame index for the clip"));
950  frames_t nframes = sfile->frames, frames = end - start + 1;
951 
952  lives_freep((void **)&sfile->frame_index_back);
953 
954  sfile->frame_index_back = sfile->frame_index;
955  sfile->frame_index = NULL;
956 
957  if (nframes - frames == 0) {
958  del_frame_index(sfile);
959  return;
960  }
961 
962  do {
963  response = LIVES_RESPONSE_OK;
964  create_frame_index(sfileno, FALSE, 0, nframes - frames);
965  if (!sfile->frame_index) {
966  response = do_memory_error_dialog(what, (nframes - frames) * sizeof(frames_t));
967  }
968  } while (response == LIVES_RESPONSE_RETRY);
969  lives_free(what);
970  if (response == LIVES_RESPONSE_CANCEL) {
971  sfile->frame_index = sfile->frame_index_back;
972  sfile->frame_index_back = NULL;
973  return;
974  }
975 
976  lives_memcpy(sfile->frame_index, sfile->frame_index_back, (start - 1) * sizeof(frames_t));
977  lives_memcpy(&sfile->frame_index[start - 1], &sfile->frame_index_back[end], (nframes - end) * sizeof(frames_t));
978 
979  sfile->frames = nframes - frames;
980  save_frame_index(sfileno);
981  sfile->frames = nframes;
982 }
983 
984 
985 void reverse_frame_index(int sfileno) {
986  // reverse order of (virtual) frames in clip (only used fro clipboard)
987  lives_clip_t *sfile = mainw->files[sfileno];
988  int bck;
989 
990  if (!sfile || !sfile->frame_index) return;
991 
992  for (frames_t i = 0; i < sfile->frames >> 1; i++) {
993  bck = sfile->frame_index[i];
994  sfile->frame_index[i] = sfile->frame_index[sfile->frames - 1 - i];
995  sfile->frame_index[sfile->frames - 1 - i] = bck;
996  }
997 }
998 
999 
1000 void restore_frame_index_back(int sfileno) {
1001  // undo an operation
1002  // this is the virtual (book-keeping) part
1003 
1004  // need to update the frame_index
1005 
1006  // this is for clip type CLIP_TYPE_FILE only
1007 
1008  lives_clip_t *sfile = mainw->files[sfileno];
1009 
1010  lives_freep((void **)&sfile->frame_index);
1011 
1012  sfile->frame_index = sfile->frame_index_back;
1013  sfile->frame_index_back = NULL;
1014 
1015  if (sfile->frame_index) {
1016  sfile->clip_type = CLIP_TYPE_FILE;
1017  save_frame_index(sfileno);
1018  } else {
1019  del_frame_index(sfile);
1020  sfile->clip_type = CLIP_TYPE_DISK;
1021  }
1022 }
1023 
1024 
1025 void clean_images_from_virtual(lives_clip_t *sfile, frames_t oldsframe, frames_t oldframes) {
1026  // remove images on disk where the frame_index points to a frame in
1027  // the original clip
1028 
1029  // only needed if frames were reordered when rendered and the process is
1030  // then undone
1031 
1032  // oldsframe is > 1 if we rendered to a selection
1033 
1034  // should be threadsafe, provided the frame_index does not change
1035 
1036  // the only purpose of this is to reclaim disk space
1037 
1038  char *iname = NULL;
1039 
1040  if (!sfile || !sfile->frame_index) return;
1041 
1042  for (frames_t i = oldsframe; i <= oldframes; i++) {
1044  if ((i <= sfile->frames && sfile->frame_index[i - 1] != -1) || i > sfile->frames) {
1045  iname = make_image_file_name(sfile, i, get_image_ext_for_type(sfile->img_type));
1046  lives_rm(iname);
1047  }
1048  }
1049 }
1050 
1051 
1053  // copy first nframes from findex and return them, adding offset to each value
1054  // no checking is done to make sure nframes is in range
1055 
1056  // start at frame offset
1057  frames_t *findexc = (frames_t *)lives_calloc(nframes, sizeof(frames_t));;
1058  for (int i = 0; i < nframes; i++) findexc[i] = findex[i + offset];
1059  return findexc;
1060 }
1061 
1062 
1063 boolean is_virtual_frame(int sfileno, frames_t frame) {
1064  // frame is virtual if it is still inside a video clip (read only)
1065  // once a frame is on disk as an image it is no longer virtual
1066 
1067  // frame starts at 1 here
1068 
1069  // a CLIP_TYPE_FILE with no virtual frames becomes a CLIP_TYPE_DISK
1070 
1071  lives_clip_t *sfile = mainw->files[sfileno];
1072  if (!IS_VALID_CLIP(sfileno)) return FALSE;
1073  if (!sfile->frame_index) return FALSE;
1074  if (frame < 1 || frame > sfile->frames) return FALSE;
1075  if (sfile->frame_index[frame - 1] != -1) return TRUE;
1076  return FALSE;
1077 }
1078 
1079 
1080 void insert_blank_frames(int sfileno, frames_t nframes, frames_t after, int palette) {
1081  // insert blank frames in clip (only valid just after clip is opened)
1082 
1083  // this is ugly, it should be moved to another file
1084 
1085  lives_clip_t *sfile = mainw->files[sfileno];
1086  LiVESPixbuf *blankp = NULL;
1087  LiVESError *error = NULL;
1088  char oname[PATH_MAX];
1089  char nname[PATH_MAX];
1090  char *tmp;
1091 
1092  frames_t i;
1093 
1094  if (first_virtual_frame(sfileno, 1, sfile->frames) != 0) {
1095  for (i = after + 1; i <= sfile->frames; i++) {
1096  if (!sfile->frame_index || sfile->frame_index[i - 1] == -1) {
1097  tmp = make_image_file_name(sfile, i, get_image_ext_for_type(sfile->img_type));
1098  lives_snprintf(oname, PATH_MAX, "%s", tmp);
1099  lives_free(tmp);
1100  if (lives_file_test(oname, LIVES_FILE_TEST_EXISTS)) {
1101  tmp = make_image_file_name(sfile, i + nframes, get_image_ext_for_type(sfile->img_type));
1102  lives_snprintf(nname, PATH_MAX, "%s", tmp);
1103  lives_free(tmp);
1104  lives_mv(oname, nname);
1105  if (THREADVAR(com_failed)) {
1106  return;
1107  // *INDENT-OFF*
1108  }}}}}
1109  // *INDENT-ON*
1110 
1111  for (i = after; i < after + nframes; i++) {
1112  tmp = make_image_file_name(sfile, i + 1, get_image_ext_for_type(sfile->img_type));
1113  lives_snprintf(oname, PATH_MAX, "%s", tmp);
1114  lives_free(tmp);
1115  if (!blankp) blankp = lives_pixbuf_new_blank(sfile->hsize, sfile->vsize, palette);
1116  lives_pixbuf_save(blankp, oname, sfile->img_type, 100 - prefs->ocp, sfile->hsize, sfile->vsize, &error);
1117  if (error) {
1118  char *msg = lives_strdup_printf(_("Padding: Unable to write blank frame with size %d x %d to %s"),
1119  sfile->hsize, sfile->vsize, oname);
1120  LIVES_ERROR(msg);
1121  lives_free(msg);
1122  lives_error_free(error);
1123  break;
1124  }
1125  }
1126 
1127  nframes = i - after; // in case we bailed
1128 
1129  if (sfile->clip_type == CLIP_TYPE_FILE)
1130  insert_images_in_virtual(sfileno, after, nframes, NULL, 0);
1131 
1132  sfile->frames += nframes;
1133 
1134  if (blankp) lives_widget_object_unref(blankp);
1135 }
1136 
1137 
1138 boolean pull_frame_idle(livespointer data) {
1139  if (cfile->fx_frame_pump >= cfile->end) return FALSE;
1140  if (virtual_to_images(mainw->current_file, cfile->fx_frame_pump, cfile->fx_frame_pump, FALSE, NULL) <= 0) {
1141  return FALSE;
1142  }
1143  cfile->fx_frame_pump++;
1144  return TRUE;
1145 }
lives_freep
boolean lives_freep(void **ptr)
Definition: utils.c:1411
create_frame_index
boolean create_frame_index(int fileno, boolean init, frames_t start_offset, frames_t nframes)
Definition: cvirtual.c:27
lives_img_type_t
lives_img_type_t
Definition: main.h:774
first_virtual_frame
frames_t first_virtual_frame(int fileno, frames_t start, frames_t end)
Definition: cvirtual.c:629
lives_clip_data_t::height
int height
Definition: plugins.h:348
lives_proc_thread_cancelled
LIVES_GLOBAL_INLINE boolean lives_proc_thread_cancelled(lives_proc_thread_t tinfo)
Definition: machinestate.c:1971
lives_free
#define lives_free
Definition: machinestate.h:52
resolve_img_type
lives_img_type_t resolve_img_type(lives_clip_t *sfile)
Definition: cvirtual.c:275
lives_clip_t::interlace
lives_interlace_t interlace
interlace type (if known - none, topfirst, bottomfirst or : see plugins.h)
Definition: main.h:899
get_frames_sizes
boolean get_frames_sizes(int fileno, int frame_to_test, int *hsize, int *vsize)
Definition: utils.c:3124
LIVES_FILE_EXT_BACK
#define LIVES_FILE_EXT_BACK
Definition: mainwindow.h:496
STRG_CHECK
#define STRG_CHECK
Definition: cvirtual.c:717
N_IMG_TYPES
@ N_IMG_TYPES
Definition: main.h:778
_prefs::workdir
char workdir[PATH_MAX]
kept in locale encoding
Definition: preferences.h:61
mainwindow::is_exiting
volatile boolean is_exiting
set during shutdown (inverse of only_close then)
Definition: mainwindow.h:1440
mainwindow::current_file
int current_file
Definition: mainwindow.h:727
IS_VALID_CLIP
#define IS_VALID_CLIP(clip)
Definition: main.h:808
lives_cp
int lives_cp(const char *from, const char *to)
Definition: utils.c:4414
cfile
#define cfile
Definition: main.h:1833
pull_frame_idle
boolean pull_frame_idle(livespointer data)
Definition: cvirtual.c:1138
lives_clip_data_t::current_palette
int current_palette
plugin should init this to palettes[0] if URI changes
Definition: plugins.h:378
LIVES_ERROR
#define LIVES_ERROR(x)
Definition: main.h:1870
lives_clip_t::frames
frames_t frames
number of video frames
Definition: main.h:890
lives_clip_t::clip_type
lives_clip_type_t clip_type
Definition: main.h:886
cvirtual.h
prefs
_prefs * prefs
Definition: preferences.h:847
virtual_to_images
frames_t virtual_to_images(int sfileno, frames_t sframe, frames_t eframe, boolean update_progress, LiVESPixbuf **pbr)
Definition: cvirtual.c:719
check_clip_integrity
boolean check_clip_integrity(int fileno, const lives_clip_data_t *cdata, frames_t maxframe)
Definition: cvirtual.c:296
do_read_failed_error_s_with_retry
LiVESResponseType do_read_failed_error_s_with_retry(const char *fname, const char *errtext)
Definition: dialogs.c:4122
lives_proc_thread_t
weed_plantptr_t lives_proc_thread_t
lives proc_threads API
Definition: machinestate.c:1670
restore_frame_index_back
void restore_frame_index_back(int sfileno)
Definition: cvirtual.c:1000
_prefs::btgamma
boolean btgamma
allows clips to be stored with bt709 gamma - CAUTION not backwards compatible, untested
Definition: preferences.h:453
frames64_t
int64_t frames64_t
Definition: main.h:100
lives_clip_t::needs_update
boolean needs_update
loaded values were incorrect, update header
Definition: main.h:1088
delete_frames_from_virtual
void delete_frames_from_virtual(int sfileno, frames_t start, frames_t end)
Definition: cvirtual.c:938
CANCEL_KILL
@ CANCEL_KILL
normal - kill background processes working on current clip
Definition: main.h:759
CANCEL_USER
@ CANCEL_USER
user pressed stop
Definition: main.h:704
check_storage_space
boolean check_storage_space(int clipno, boolean is_processing)
Definition: dialogs.c:1086
check_if_non_virtual
boolean check_if_non_virtual(int fileno, frames_t start, frames_t end)
Definition: cvirtual.c:644
lives_clip_data_t::width
int width
Definition: plugins.h:347
lives_proc_thread_set_cancellable
LIVES_GLOBAL_INLINE void lives_proc_thread_set_cancellable(lives_proc_thread_t tinfo)
only threads with no return value can possibly be cancellable. For threads with a value,...
Definition: machinestate.c:1938
del_frame_index
void del_frame_index(lives_clip_t *sfile)
Definition: cvirtual.c:238
lives_open_buffered_rdonly
int lives_open_buffered_rdonly(const char *pathname)
Definition: utils.c:636
IMG_TYPE_BEST
#define IMG_TYPE_BEST
Definition: main.h:781
do_header_write_error
boolean do_header_write_error(int clip)
Definition: dialogs.c:4169
end_threaded_dialog
void end_threaded_dialog(void)
Definition: dialogs.c:3883
threaded_dialog_spin
void threaded_dialog_spin(double fraction)
Definition: dialogs.c:3823
TRUE
#define TRUE
Definition: videoplugin.h:59
lives_clip_t::img_type
lives_img_type_t img_type
Definition: main.h:887
CLIP_TYPE_DISK
@ CLIP_TYPE_DISK
imported video, broken into frames
Definition: main.h:764
realize_all_frames
frames_t realize_all_frames(int clipno, const char *msg, boolean enough)
Definition: cvirtual.c:849
THREADVAR
#define THREADVAR(var)
Definition: machinestate.h:531
CLIP_DETAILS_INTERLACE
@ CLIP_DETAILS_INTERLACE
Definition: main.h:1163
mainwindow::cancelled
volatile lives_cancel_t cancelled
Definition: mainwindow.h:798
lives_clip_t::fps
double fps
Definition: main.h:893
lives_write_le_buffered
ssize_t lives_write_le_buffered(int fd, livesconstpointer buf, ssize_t count, boolean allow_fail)
_prefs::auto_nobord
boolean auto_nobord
Definition: preferences.h:303
threaded_dialog_pop
void threaded_dialog_pop(void)
Definition: dialogs.c:3771
MAX_CBSTORES
#define MAX_CBSTORES
this is not really used yet, but the idea is that in future the clipboard may be reproduced in variou...
Definition: mainwindow.h:1780
lives_clip_t::pumper
lives_proc_thread_t pumper
Definition: main.h:1059
_prefs::ocp
int ocp
open_compression_percent : get/set in prefs
Definition: preferences.h:217
close_current_file
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
reget_afilesize_inner
off_t reget_afilesize_inner(int fileno)
Definition: machinestate.c:1001
lives_clip_data_t::frame_width
int frame_width
frame is the surrounding part, including any black border (>=width)
Definition: plugins.h:357
mainwindow::msg
char msg[MAINW_MSG_SIZE]
Definition: mainwindow.h:724
CLIP_TYPE_FILE
@ CLIP_TYPE_FILE
unimported video, not or partially broken in frames
Definition: main.h:765
lives_mv
int lives_mv(const char *from, const char *to)
Definition: utils.c:4446
lives_clip_t::frame_index
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
resize_all
int resize_all(int fileno, int width, int height, lives_img_type_t imgtype, boolean do_back, int *nbad, int *nmiss)
utility funcs for GUI
Definition: colourspace.c:13622
lives_clip_t::afilesize
size_t afilesize
Definition: main.h:912
lives_clip_data_t::frame_height
int frame_height
Definition: plugins.h:358
do_memory_error_dialog
LiVESResponseType do_memory_error_dialog(char *op, size_t bytes)
Definition: dialogs.c:904
CURRENT_CLIP_HAS_VIDEO
#define CURRENT_CLIP_HAS_VIDEO
Definition: main.h:815
clip_forensic
lives_clip_t * clip_forensic(int clipno)
Definition: saveplay.c:6029
save_frame_index
boolean save_frame_index(int fileno)
Definition: cvirtual.c:56
load_frame_index
frames_t load_frame_index(int fileno)
Definition: cvirtual.c:114
mainwindow::files
lives_clip_t * files[MAX_FILES+1]
+1 for the clipboard
Definition: mainwindow.h:729
save_clip_value
boolean save_clip_value(int which, lives_clip_details_t, void *val)
Definition: utils.c:5175
CANCEL_NONE
@ CANCEL_NONE
no cancel
Definition: main.h:701
ALIGN_CEIL
#define ALIGN_CEIL(a, b)
Definition: main.h:286
lives_close_buffered
int lives_close_buffered(int fd)
Definition: utils.c:716
palette
_palette * palette
interface colour settings
Definition: main.c:101
q_gint64
LIVES_GLOBAL_INLINE ticks_t q_gint64(ticks_t in, double fps)
Definition: resample.c:25
update_progress
void update_progress(boolean visible)
Definition: dialogs.c:1275
sget_file_size
off_t sget_file_size(const char *name)
Definition: machinestate.c:962
error
error("LSD_RANDFUNC(ptr, size) must be defined")
lives_clip_t::frame_index_back
frames_t * frame_index_back
for undo
Definition: main.h:1005
clipboard
#define clipboard
Definition: main.h:1835
count_virtual_frames
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
do_threaded_dialog
void do_threaded_dialog(const char *trans_text, boolean has_cancel)
Definition: dialogs.c:3849
lives_strdup_printf
#define lives_strdup_printf(fmt,...)
Definition: support.c:27
lives_calloc
#define lives_calloc
Definition: machinestate.h:67
lives_clip_t::deinterlace
boolean deinterlace
auto deinterlace
Definition: main.h:938
lives_create_buffered
int lives_create_buffered(const char *pathname, int mode)
Definition: utils.c:698
lives_clip_t::hsize
int hsize
frame width (horizontal) in pixels (NOT macropixels !)
Definition: main.h:896
lives_pixbuf_new_blank
LiVESPixbuf * lives_pixbuf_new_blank(int width, int height, int palette)
Definition: colourspace.c:11953
mainwindow::ncbstores
int ncbstores
Definition: mainwindow.h:1781
close_clip_decoder
void close_clip_decoder(int clipno)
Definition: plugins.c:2382
lives_clip_data_t
Definition: plugins.h:319
lives_memcpy
#define lives_memcpy
Definition: machinestate.h:55
is_virtual_frame
boolean is_virtual_frame(int sfileno, frames_t frame)
Definition: cvirtual.c:1063
lives_clip_t::old_frames
frames_t old_frames
for deordering, etc.
Definition: main.h:977
do_write_failed_error_s_with_retry
LiVESResponseType do_write_failed_error_s_with_retry(const char *fname, const char *errtext)
Definition: dialogs.c:4058
lives_read_le_buffered
ssize_t lives_read_le_buffered(int fd, void *buf, ssize_t count, boolean allow_less)
Definition: utils.c:1158
xprocess::processing
LiVESWidget * processing
Definition: mainwindow.h:706
DEF_ALIGN
#define DEF_ALIGN
Definition: main.h:629
main.h
make_image_file_name
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
clean_images_from_virtual
void clean_images_from_virtual(lives_clip_t *sfile, frames_t oldsframe, frames_t oldframes)
Definition: cvirtual.c:1025
insert_images_in_virtual
void insert_images_in_virtual(int sfileno, frames_t where, frames_t frames, frames_t *frame_index, frames_t start)
Definition: cvirtual.c:885
resample.h
_prefs::vj_mode
boolean vj_mode
Definition: preferences.h:459
do_imgfmts_error
LIVES_GLOBAL_INLINE LiVESResponseType do_imgfmts_error(lives_img_type_t imgtype)
Definition: dialogs.c:4449
mainw
mainwindow * mainw
Definition: main.c:103
get_image_ext_for_type
const char * get_image_ext_for_type(lives_img_type_t imgtype)
Definition: utils.c:3025
do_resize_dlg
LIVES_GLOBAL_INLINE LiVESResponseType do_resize_dlg(int cwidth, int cheight, int fwidth, int fheight)
Definition: dialogs.c:4417
lives_clip_data_t::fps
float fps
Definition: plugins.h:364
mainwindow::proc_ptr
xprocess * proc_ptr
Definition: mainwindow.h:1090
frames_t
int frames_t
Definition: main.h:99
lives_clip_t::pb_fps
double pb_fps
current playback rate, may vary from fps, can be 0. or negative
Definition: main.h:1007
DS_SPACE_CHECK_FRAMES
#define DS_SPACE_CHECK_FRAMES
Definition: cvirtual.c:683
insert_blank_frames
void insert_blank_frames(int sfileno, frames_t nframes, frames_t after, int palette)
Definition: cvirtual.c:1080
lives_widget_show_all
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_show_all(LiVESWidget *widget)
Definition: widget-helper.c:1523
reverse_frame_index
void reverse_frame_index(int sfileno)
Definition: cvirtual.c:985
init_clipboard
void init_clipboard(void)
Definition: utils.c:2238
mainwindow::cbstores
lives_clip_t * cbstores[8]
Definition: mainwindow.h:1782
lives_clip_t::vsize
int vsize
frame height (vertical) in pixels
Definition: main.h:897
PATH_MAX
#define PATH_MAX
Definition: main.h:255
LIVES_INTERLACE_NONE
@ LIVES_INTERLACE_NONE
Definition: main.h:791
IMG_TYPE_UNKNOWN
@ IMG_TYPE_UNKNOWN
Definition: main.h:775
CANCEL_SOFT
@ CANCEL_SOFT
just cancel in GUI (for keep, etc)
Definition: main.h:760
lives_clip_t
corresponds to one clip in the GUI
Definition: main.h:877
lives_clip_t::gamma_type
int gamma_type
Definition: main.h:903
threaded_dialog_push
void threaded_dialog_push(void)
Definition: dialogs.c:3762
mainwindow::cancel_type
lives_cancel_type_t cancel_type
Definition: mainwindow.h:799
FRAME_INDEX_FNAME
#define FRAME_INDEX_FNAME
Definition: cvirtual.h:12
lives_widget_object_unref
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_object_unref(livespointer object)
decrease refcount by one: if refcount==0, object is destroyed
Definition: widget-helper.c:815
pull_lives_pixbuf_at_size
LiVESPixbuf * pull_lives_pixbuf_at_size(int clip, int frame, const char *image_ext, weed_timecode_t tc, int width, int height, LiVESInterpType interp, boolean fordisp)
Definition: main.c:7678
findex_bk_dialog
LIVES_GLOBAL_INLINE boolean findex_bk_dialog(const char *fname_back)
Definition: dialogs.c:3261
DEF_FILE_PERMS
#define DEF_FILE_PERMS
non-executable, is modified by the umask
Definition: main.h:209
_prefs::fps_tolerance
double fps_tolerance
Definition: preferences.h:221
FALSE
#define FALSE
Definition: videoplugin.h:60
weed_palette_get_pixels_per_macropixel
LIVES_GLOBAL_INLINE int weed_palette_get_pixels_per_macropixel(int pal)
Definition: colourspace.c:1403
lives_clip_t::handle
char handle[256]
Definition: main.h:881
_
#define _(String)
Definition: support.h:44
lives_rm
int lives_rm(const char *file)
Definition: utils.c:4395
lives_widget_context_update
boolean lives_widget_context_update(void)
Definition: widget-helper.c:11878
frame_index_copy
frames_t * frame_index_copy(frames_t *findex, frames_t nframes, frames_t offset)
Definition: cvirtual.c:1052
lives_pixbuf_save
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
MAINW_MSG_SIZE
#define MAINW_MSG_SIZE
mainw->msg bytesize
Definition: mainwindow.h:702
lives_clip_data_t::nframes
int64_t nframes
Definition: plugins.h:349
_prefs::show_dev_opts
boolean show_dev_opts
Definition: preferences.h:463