80 #include "giw/giwvslider.h"
81 #include "giw/giwled.h"
85 #include "giw/giwtimeline.h"
92 #ifndef WEED_AUDIO_LITTLE_ENDIAN
93 #define WEED_AUDIO_LITTLE_ENDIAN 0
94 #define WEED_AUDIO_BIG_ENDIAN 1
98 static uint32_t event_list_get_byte_size(lives_mt *mt, weed_plant_t *event_list,
boolean nxprev,
int *num_events);
103 static boolean mt_add_block_effect_idle(livespointer mt);
104 static boolean mt_add_region_effect_idle(livespointer mt);
105 static boolean mt_fx_edit_idle(livespointer mt);
107 static void paint_lines(lives_mt *mt,
double currtime,
boolean unpaint, lives_painter_t *cr);
109 static int *update_layout_map(weed_plant_t *event_list);
110 static double *update_layout_map_audio(weed_plant_t *event_list);
112 static boolean check_can_resetp(lives_mt *mt);
115 static int renumbered_clips[
MAX_FILES + 1];
118 static void **pchain;
120 static int xachans, xarate, xasamps, xse;
121 static boolean ptaud;
127 static int dclick_time = 0;
129 static boolean force_pertrack_audio;
130 static int force_backing_tracks;
134 static boolean pb_audio_needs_prerender;
135 static weed_plant_t *pb_loop_event, *pb_filter_map, *pb_afilter_map;
137 static boolean nb_ignore =
FALSE;
139 static LiVESWidget *dummy_menuitem;
141 static boolean doubleclick =
FALSE;
143 static uint32_t last_press_time = 0;
144 static int last_x = 0;
145 static int last_y = 0;
147 static boolean needs_clear;
149 static LiVESList *pkg_list;
151 static LiVESWidget *mainw_message_box;
152 static LiVESWidget *mainw_msg_area;
153 static LiVESWidget *mainw_msg_scrollbar;
154 static LiVESAdjustment *mainw_msg_adj;
169 static void on_delblock_activate(LiVESMenuItem *, livespointer mt);
178 static void mt_render_vid_toggled(LiVESMenuItem *, livespointer mt);
179 static void mt_render_aud_toggled(LiVESMenuItem *, livespointer mt);
180 static void mt_norm_aud_toggled(LiVESMenuItem *, livespointer mt);
181 static void mt_fplay_toggled(LiVESMenuItem *, livespointer mt);
184 static void on_move_fx_changed(LiVESMenuItem *, livespointer mt);
185 static void select_all_time(LiVESMenuItem *, livespointer mt);
186 static void select_from_zero_time(LiVESMenuItem *, livespointer mt);
187 static void select_to_end_time(LiVESMenuItem *, livespointer mt);
188 static void select_all_vid(LiVESMenuItem *, livespointer mt);
189 static void select_no_vid(LiVESMenuItem *, livespointer mt);
198 static void mt_view_audio_toggled(LiVESMenuItem *, livespointer mt);
199 static void mt_ign_ins_sel_toggled(LiVESMenuItem *, livespointer mt);
202 static void mt_ac_audio_toggled(LiVESMenuItem *, livespointer mt);
206 #define LIVES_AVOL_SCALE ((double)1000000.)
217 return clips_to_files[clip];
224 if (clips_to_files[i] == file)
return i;
232 return LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"layer_number"));
237 return (lives_widget_object_get_data(track,
"blocks") == NULL);
241 double vol = (double)(LIVES_POINTER_TO_INT(lives_list_nth_data(mt->audio_vols, trackno)));
248 lives_list_nth(mt->audio_vols, trackno)->data = LIVES_INT_TO_POINTER(x);
266 if (!event_list)
return TRUE;
274 weed_set_int_value(event_list, WEED_LEAF_WIDTH,
mainw->
files[mt->render_file]->
hsize);
275 weed_set_int_value(event_list, WEED_LEAF_HEIGHT,
mainw->
files[mt->render_file]->
vsize);
276 weed_set_int_value(event_list, WEED_LEAF_AUDIO_CHANNELS,
mainw->
files[mt->render_file]->
achans);
277 weed_set_int_value(event_list, WEED_LEAF_AUDIO_RATE,
mainw->
files[mt->render_file]->
arate);
288 if (
prefs->
letterbox_mt) weed_set_boolean_value(event_list, WEED_LEAF_KEEP_ASPECT, WEED_TRUE);
289 else weed_set_boolean_value(event_list, WEED_LEAF_KEEP_ASPECT, WEED_FALSE);
291 if (mt && mt->audio_vols && mt->audio_draws) {
292 int natracks = lives_list_length(mt->audio_draws);
299 for (i = 0; i < natracks; i++) {
300 atracks[i] = i - mt->opts.back_audio_tracks;
305 if (mt->opts.gang_audio) navols = 1 + mt->opts.back_audio_tracks;
306 else navols = natracks;
308 avols = (
double *)
lives_malloc(navols *
sizeof(
double));
309 for (i = 0; i < navols; i++) {
317 int nvtracks = lives_list_length(mt->video_draws);
320 char **
const labels = (
char **)
lives_malloc(nvtracks *
sizeof(
char *));
322 for (i = 0; i < nvtracks; i++) {
324 const char *tname = (
const char *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(ebox),
"track_name");
325 labels[i] = (
char *)tname;
337 if (!mem && fd < 0)
return TRUE;
344 while (!
THREADVAR(write_failed) && event) {
361 for (i = 0; i < nivs; i++) {
362 uievs[i] = (int64_t)(uint64_t)ievs[i];
372 weed_leaf_copy(event,
WEED_LEAF_HINT, event, WEED_LEAF_EVENT_TYPE);
395 if (++count == 100) {
405 LiVESPixbuf *
make_thumb(lives_mt *mt,
int file,
int width,
int height,
frames_t frame, LiVESInterpType interp,
407 LiVESPixbuf *thumbnail = NULL, *pixbuf;
408 LiVESError *
error = NULL;
412 boolean tried_all =
FALSE;
413 boolean needs_idlefunc =
FALSE;
415 boolean did_backup =
FALSE;
417 int nframe, oframe = frame;
420 LIVES_WARN(
"Warning - make thumb for file -1");
424 if (width < 4 || height < 4)
return NULL;
426 if (mt) did_backup = mt->did_backup;
428 if (mt && mt->idlefunc > 0) {
429 needs_idlefunc =
TRUE;
445 width, height, LIVES_INTERP_FAST,
TRUE);
448 if (
error || !pixbuf) {
449 lives_error_free(
error);
450 if (mt && (needs_idlefunc || (!did_backup && mt->auto_changed))) {
460 }
else thumbnail = pixbuf;
463 if (tried_all) noblanks =
FALSE;
467 nframe = frame + sfile->
frames / 10.;
468 if (nframe == frame) nframe++;
469 if (nframe > sfile->
frames) {
480 if (needs_idlefunc || (!did_backup && mt->auto_changed)) {
494 LIVES_WARN(
"Warning - make thumb for file -1");
498 if (width < 2 || height < 2)
return NULL;
500 for (i = 1; i <= range; i++) {
502 nvframe = tframe - i;
505 if (tframe + i <= mainw->files[fileno]->frames && !
is_virtual_frame(fileno, tframe + i)) {
506 nvframe = tframe + i;
512 return make_thumb(mt, fileno, width, height, nvframe, LIVES_INTERP_FAST,
FALSE);
526 static void mt_set_cursor_style(lives_mt *mt,
lives_cursor_t cstyle,
int width,
int height,
int clip,
int hsx,
int hsy) {
527 LiVESXCursor *cursor;
530 LiVESPixbuf *pixbuf = NULL;
531 LiVESPixbuf *thumbnail = NULL;
533 uint8_t *cpixels, *tpixels;
539 unsigned int cwidth, cheight;
541 int twidth = 0, twidth3, twidth4, trow;
544 register int i, j, k;
554 gdk_display_get_maximal_cursor_size(disp, &cwidth, &cheight);
557 cwidth = MAX_CURSOR_WIDTH;
560 if (width > cwidth) width = cwidth;
562 mt->cursor_style = cstyle;
565 if (sfile && sfile->
frames > 0) {
566 frame_start = mt->opts.ign_ins_sel ? 1 : sfile->
start;
567 frames_width = (double)(mt->opts.ign_ins_sel ? sfile->
frames : sfile->
end - sfile->
start + 1.);
574 if ((i + twidth) > width) twidth = width - i;
576 thumbnail =
make_thumb(mt, clip, twidth, height, frame_start + (
int)((
double)i / (
double)width * frames_width),
577 LIVES_INTERP_NORMAL,
FALSE);
586 twidth3 = twidth * 3;
587 for (j = 0; j < height; j++) {
588 for (k = 0; k < twidth3; k += 3) {
594 cpixels += (width - twidth) << 2;
597 twidth4 = twidth * 4;
598 for (j = 0; j < height; j++) {
601 cpixels += width << 2;
615 for (j = 0; j < height; j++) {
616 for (k = 0; k < width; k++) {
623 cpixels += (trow - width * 4);
630 for (j = 0; j < height; j++) {
631 for (k = 0; k < width; k++) {
638 cpixels += (trow - width * 4);
645 for (j = 0; j < height; j++) {
646 for (k = 0; k < width; k++) {
653 cpixels += (trow - width * 4);
672 int fd, i, vali, hdlsize;
685 i = LIVES_POINTER_TO_INT(clist->data);
693 hdlsize = strlen(sfile->
handle);
705 static void upd_layout_maps(weed_plant_t *event_list) {
707 double *layout_map_audio;
711 layout_map_audio = update_layout_map_audio(event_list);
720 static void renumber_from_backup_layout_numbering(lives_mt *mt) {
731 boolean gotvalid =
FALSE;
732 int fd, vari, clipn, offs, restart = 0;
739 upd_layout_maps(NULL);
753 if (vari > 511) vari = 511;
756 if (clipn < 0 || clipn >
MAX_FILES)
continue;
760 if (!gotvalid) restart = offs;
769 renumbered_clips[clipn] = offs;
782 static void save_mt_autoback(lives_mt *mt) {
792 char *asave_file = lives_build_filename(
prefs->
workdir, fname, NULL);
795 boolean retval =
TRUE;
801 mt->auto_changed =
FALSE;
827 paint_lines(mt, mt->ptr_time,
FALSE, NULL);
835 if (!retval ||
THREADVAR(write_failed)) {
839 }
while (retval2 == LIVES_RESPONSE_RETRY);
845 gettimeofday(&otv, NULL);
847 d_print(
"Auto backup of timeline at %s\n", tmp);
852 static void on_mt_backup_activate(LiVESMenuItem *menuitem, livespointer user_data) {
853 lives_mt *mt = (lives_mt *)user_data;
854 if (!mt->auto_changed)
return;
855 if (mt->idlefunc > 0) {
859 save_mt_autoback(mt);
866 lives_mt *mt = (lives_mt *)user_data;
868 if (!mt->idlefunc)
return FALSE;
873 if (!mt->auto_changed && mt->did_backup) {
885 if (mt->auto_back_time == 0) mt->auto_back_time = stime;
887 diff = stime - mt->auto_back_time;
891 save_mt_autoback(mt);
908 if (mt->idlefunc > 0)
return mt->idlefunc;
942 boolean recovered =
TRUE;
943 char *aload_file = NULL, *eload_file;
950 mt->auto_reloading =
TRUE;
952 mt->auto_reloading =
FALSE;
953 if (mt->event_list) {
958 save_mt_autoback(mt);
985 if (lives_file_test(uldir, LIVES_FILE_TEST_IS_DIR)) {
989 if (lives_file_test(eload_file, LIVES_FILE_TEST_EXISTS)) {
992 if (lives_file_test(aload_file, LIVES_FILE_TEST_EXISTS)) {
1011 boolean loaded =
TRUE;
1040 LiVESWidget *xeventbox;
1041 if (track_num < 0)
return (
_(
"Backing audio"));
1042 if (!is_audio) xeventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, track_num);
1043 else xeventbox = (LiVESWidget *)lives_list_nth_data(mt->audio_draws, track_num + mt->opts.back_audio_tracks);
1044 return lives_strdup((
char *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"track_name"));
1050 (mt->tl_max - mt->tl_min) + mt->tl_min;
1051 if (time < 0.) time = 0.;
1052 else if (time > mt->end_secs + 1. / mt->fps) time = mt->end_secs + 1. / mt->fps;
1058 weed_plant_t *wparam;
1059 weed_plant_t *inst = rfx->
source;
1068 for (j = 0; j < nvals; j++) {
1069 ign_array[j] = WEED_TRUE;
1071 weed_set_boolean_array(wparam, WEED_LEAF_IGNORE, nvals, ign_array);
1082 static int get_track_height(lives_mt * mt) {
1083 LiVESWidget *eventbox;
1084 LiVESList *list = mt->video_draws;
1087 eventbox = (LiVESWidget *)list->data;
1088 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
HIDDEN_KEY)) == 0)
1097 static boolean is_audio_eventbox(LiVESWidget * ebox) {
1098 return LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(ebox),
"is_audio"));
1102 static boolean add_to_thumb_cache(
int fnum,
frames_t frame,
frames_t range,
int height,
1103 LiVESPixbuf * pixbuf) {
1107 for (; list; list = list->next) {
1110 if (tce->
frame <= frame - range)
continue;
1111 if (tce->
frame <= frame + range)
return FALSE;
1117 xlist = lives_list_append(NULL, tce);
1118 xlist->data = (livespointer)tce;
1120 xlist->prev = list->prev;
1121 if (list->prev) list->prev->next = xlist;
1127 llist->next = xlist;
1128 xlist->prev = llist;
1137 static LiVESPixbuf *get_from_thumb_cache(
int fnum,
frames_t frame,
frames_t range) {
1139 for (; list; list = list->next) {
1141 if (tcentry->
frame <= frame - range)
continue;
1142 if (tcentry->
frame >= frame + range)
return NULL;
1150 boolean has_some =
FALSE;
1151 for (; list; list = list->next) {
1154 if (tcentry->
frame < fromframe) {
1159 list->prev->next = NULL;
1167 if (freestart) lives_list_free(freestart);
1176 static void draw_block(lives_mt * mt, lives_painter_t *cairo,
1177 lives_painter_surface_t *surf, track_rect * block,
int x1,
int x2) {
1179 lives_painter_t *cr;
1180 weed_event_t *
event = block->start_event, *nxevent = NULL;
1182 LiVESWidget *eventbox = block->eventbox;
1183 LiVESPixbuf *thumbnail = NULL;
1185 double tl_span = mt->tl_max - mt->tl_min;
1188 frames_t framenum, last_framenum = -1, range = 0;
1190 boolean needs_text =
TRUE;
1191 boolean is_audio =
FALSE;
1193 int offset_start, offset_end;
1196 int hidden = (int)LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
HIDDEN_KEY));
1200 if (mt->no_expose)
return;
1205 if (offset_startd >= mt->tl_max)
return;
1209 if ((x1 > 0 || x2 > 0) && offset_start > (x1 + x2))
return;
1216 if (offset_end < x1)
return;
1218 if (!surf) cr = cairo;
1225 track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"layer_number"));
1226 is_audio = is_audio_eventbox(eventbox);
1227 if (track < 0) is_audio =
TRUE;
1233 switch (block->state) {
1248 if (!is_audio && track > -1) {
1249 boolean in_cache =
FALSE;
1252 if (i > x2 - x1)
break;
1260 if (last_framenum == -1) {
1267 range = (xframenum - framenum) / 2;
1274 range = (framenum - xframenum) / 2;
1280 if (i + width >= 0) {
1293 if (!(thumbnail = get_from_thumb_cache(filenum, framenum, range))) {
1299 framenum, last_framenum == -1 ? 0
1300 : framenum - last_framenum);
1302 thumbnail =
make_thumb(mt, filenum, width, height,
1303 framenum, LIVES_INTERP_FAST,
FALSE);
1306 thumbnail =
make_thumb(mt, filenum, width, height,
1307 framenum, LIVES_INTERP_FAST,
FALSE);
1309 in_cache = add_to_thumb_cache(filenum, framenum, range, height, thumbnail);
1314 last_framenum = framenum;
1318 if (i + width > offset_end) {
1319 width = offset_end - i;
1327 if (i + width > offset_end) width = offset_end - i;
1334 mt->no_expose =
TRUE;
1337 mt->no_expose =
FALSE;
1354 const char *sfont =
"Sans";
1357 LingoLayout *layout;
1358 lives_painter_surface_t *surface;
1361 int text_start = offset_start + 2, text_end = offset_end;
1363 if (text_start < 2) text_start = 2;
1374 if (luma > 0.2) colr = &col_black;
1380 text_end - text_start, &height);
1382 lingo_painter_show_layout(cr, layout);
1392 mt->no_expose =
TRUE;
1394 mt->no_expose =
FALSE;
1425 static void draw_aparams(lives_mt * mt, LiVESWidget * eventbox, lives_painter_t *cr, LiVESList * param_list,
1426 weed_plant_t *init_event,
1427 int startx,
int width) {
1434 weed_plant_t **in_params, *param, *ptmpl;
1435 weed_plant_t *filter, *inst, *deinit_event;
1437 weed_timecode_t tc, start_tc, end_tc;
1439 double tl_span = mt->tl_max - mt->tl_min;
1442 double vald, mind, maxd, *valds;
1446 int vali, mini, maxi, *valis;
1448 int offset_start, offset_end, startpos;
1453 void **pchainx = NULL;
1463 in_params = weed_get_plantptr_array(inst, WEED_LEAF_IN_PARAMETERS, NULL);
1481 if (offset_start > startx) startpos = offset_start;
1482 else startpos = startx;
1484 track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
1485 "layer_number")) + mt->opts.back_audio_tracks;
1490 pchainx = weed_get_voidptr_array(init_event, WEED_LEAF_IN_PARAMETERS, NULL);
1493 for (i = startpos; i < startx + width; i++) {
1496 if (tc >= end_tc)
break;
1502 pnum = LIVES_POINTER_TO_INT(plist->data);
1503 param = in_params[pnum];
1507 case WEED_PARAM_INTEGER:
1508 valis = weed_get_int_array(param, WEED_LEAF_VALUE, NULL);
1510 else vali = valis[0];
1511 mini = weed_get_int_value(ptmpl, WEED_LEAF_MIN, NULL);
1512 maxi = weed_get_int_value(ptmpl, WEED_LEAF_MAX, NULL);
1513 ratio = (double)(vali - mini) / (double)(maxi - mini);
1516 case WEED_PARAM_FLOAT:
1517 valds = weed_get_double_array(param, WEED_LEAF_VALUE, NULL);
1519 else vald = valds[0];
1520 mind = weed_get_double_value(ptmpl, WEED_LEAF_MIN, NULL);
1521 maxd = weed_get_double_value(ptmpl, WEED_LEAF_MAX, NULL);
1522 ratio = (vald - mind) / (maxd - mind);
1534 plist = plist->next;
1549 static void redraw_eventbox(lives_mt * mt, LiVESWidget * eventbox) {
1550 if (!LIVES_IS_WIDGET_OBJECT(eventbox))
return;
1552 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"drawn", LIVES_INT_TO_POINTER(
FALSE));
1555 if (is_audio_eventbox(eventbox)) {
1557 LiVESWidget *xeventbox;
1559 xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"achan0");
1560 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
"drawn", LIVES_INT_TO_POINTER(
FALSE));
1563 xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"achan1");
1564 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
"drawn", LIVES_INT_TO_POINTER(
FALSE));
1572 static EXPOSE_FN_DECL(expose_track_event, eventbox, user_data) {
1573 lives_painter_t *cr;
1575 lives_mt *mt = (lives_mt *)user_data;
1578 track_rect *sblock = NULL;
1582 lives_painter_surface_t *bgimage;
1584 int startx, starty, width, height;
1587 if (mt->no_expose)
return TRUE;
1590 if (event->count > 0) {
1593 startx =
event->area.x;
1594 starty =
event->area.y;
1595 width =
event->area.width;
1596 height =
event->area.height;
1598 startx = starty = 0;
1603 if (width == 0)
return FALSE;
1605 hidden = (int)LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
HIDDEN_KEY));
1607 LiVESWidget *label = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"label");
1613 idlefunc = mt->idlefunc;
1614 if (mt->idlefunc > 0) {
1621 bgimage = (lives_painter_surface_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"bgimg");
1624 #if !GTK_CHECK_VERSION(3, 22, 0)
1631 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"drawn"))) {
1637 if (mt->block_selected && mt->block_selected->eventbox == eventbox) {
1638 draw_block(mt, cr, NULL, mt->block_selected, -1, -1);
1641 if (is_audio_eventbox(eventbox) && mt->avol_init_event && mt->opts.aparam_view_list)
1642 draw_aparams(mt, eventbox, cr, mt->opts.aparam_view_list, mt->avol_init_event, startx, width);
1673 if (mt->block_selected) {
1674 sblock = mt->block_selected;
1678 block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks");
1681 draw_block(mt, NULL, bgimage, block, startx, width);
1682 block = block->next;
1686 mt->block_selected = sblock;
1691 }
else if (bgimage) {
1696 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"bgimg", (livespointer)bgimage);
1697 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"drawn", LIVES_INT_TO_POINTER(bgimage != NULL));
1699 if (bgimage)
goto draw1;
1710 static char *mt_params_label(lives_mt * mt) {
1716 layer_name =
get_track_name(mt, mt->current_track, mt->aud_track_selected);
1718 ltext = lives_markup_escape_text(tmp, -1);
1720 }
else ltext = lives_strdup(fname);
1723 if (mt->framedraw) {
1724 char *someparms =
lives_big_and_bold(
_(
"<--- Some parameters can be altered by clicking / dragging in the Preview window"));
1725 char *tmp2 = lives_markup_escape_text(ltext, -1);
1748 weed_plant_t *deinit_event;
1752 double fx_start_time, fx_end_time;
1753 double cur_time = mt->ptr_time;
1757 boolean res =
FALSE;
1773 if (mt->fx_params_label) {
1785 fx_end_time - fx_start_time, 1. / mt->fps, 10. / mt->fps);
1795 ltext = mt_params_label(mt);
1819 if (!mt->sel_locked) {
1827 static track_rect *get_block_from_time(LiVESWidget * eventbox,
double time, lives_mt * mt) {
1832 block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks");
1838 mt->fps) > tc)
break;
1839 block = block->next;
1845 static int track_to_channel(weed_plant_t *ievent,
int track) {
1854 int nc = 0, rpts, ntracks;
1859 if (ntracks == 0)
return -1;
1863 for (i = 0; i < ntracks; i++) {
1864 rpts = nc < i ? 1 : carray[i];
1865 if (in_tracks[i] + rpts > track) {
1878 static boolean get_track_index(lives_mt * mt, weed_timecode_t tc) {
1884 int *clips, *in_tracks, numtracks;
1887 boolean retval =
FALSE;
1890 int opwidth, opheight;
1891 int track_index = mt->track_index;
1895 mt->track_index = -1;
1897 if (!event || !mt->play_width || !mt->play_height)
return retval;
1901 calc_maxspect(mt->play_width, mt->play_height, &opwidth, &opheight);
1903 clips = weed_get_int_array_counted(event,
WEED_LEAF_CLIPS, &numtracks);
1905 chindx = track_to_channel(mt->init_event, mt->current_track);
1907 if (mt->current_track < numtracks && clips[mt->current_track] < 1 &&
1908 (!mt->current_rfx || !mt->init_event || !mt->current_rfx->source || chindx == -1 ||
1910 if (track_index != -1 && mt->fx_box) {
1918 in_tracks = weed_get_int_array_counted(mt->init_event,
WEED_LEAF_IN_TRACKS, &num_in_tracks);
1919 if (num_in_tracks > 0) {
1920 for (i = 0; i < num_in_tracks; i++) {
1921 if (in_tracks[i] == mt->current_track) {
1922 mt->track_index = i;
1923 if (track_index == -1 && mt->fx_box) {
1933 if (track_index != -1 && mt->track_index == -1 && mt->fx_box) {
1942 LiVESWidget *labelbox, *label, *hbox, *dummy, *ahbox, *arrow, *eventbox, *oeventbox, *checkbutton = NULL;
1950 if (mt->current_track < 0) {
1976 for (list = mt->audio_draws; list; list = list->next, i++) {
1977 eventbox = (LiVESWidget *)list->data;
1978 if ((oeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"owner")))
1979 hidden = !LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(oeventbox),
"expanded"));
1980 if (hidden == 0) hidden = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
HIDDEN_KEY));
1982 labelbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"labelbox");
1983 label = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"label");
1984 dummy = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"dummy");
1985 ahbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"ahbox");
1986 hbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"hbox");
1987 arrow = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"arrow");
1988 if (mt->current_track == i - mt->opts.back_audio_tracks && (mt->current_track < 0 || mt->aud_track_selected)) {
2006 lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks") != NULL);
2008 lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks") != NULL);
2028 for (list = mt->video_draws; list; list = list->next, i++) {
2029 eventbox = (LiVESWidget *)list->data;
2030 hidden = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
HIDDEN_KEY));
2032 labelbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"labelbox");
2033 label = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"label");
2034 hbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"hbox");
2035 ahbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"ahbox");
2036 arrow = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"arrow");
2037 checkbutton = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"checkbutton");
2038 if (i == mt->current_track) {
2040 if (!mt->aud_track_selected) {
2057 lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks") != NULL);
2059 lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks") != NULL);
2093 lives_check_menu_item_set_active(LIVES_CHECK_MENU_ITEM(mt->select_track), FALSE);
2103 lives_widget_set_bg_color(labelbox, LIVES_WIDGET_STATE_NORMAL, &palette->normal_back);
2104 lives_widget_set_fg_color(labelbox, LIVES_WIDGET_STATE_NORMAL, &palette->normal_fore);
2121 else if (mt->current_rfx && mt->init_event && mt->poly_state ==
POLY_PARAMS &&
2124 boolean interp =
TRUE;
2129 xx = get_track_index(mt, tc);
2130 if (mt->track_index != -1) {
2131 for (i = 0; i < mt->current_rfx->num_params; i++) {
2135 if (mt->current_rfx->params[i].changed) {
2140 if (mt->current_track >= 0) {
2146 boolean aprev = mt->opts.fx_auto_preview;
2149 mt->current_rfx->needs_reinit =
FALSE;
2153 if (mt->current_rfx->needs_reinit) {
2155 mt->current_rfx->needs_reinit =
FALSE;
2158 mt->opts.fx_auto_preview = aprev;
2166 static void show_track_info(lives_mt * mt, LiVESWidget * eventbox,
int track,
double timesecs) {
2168 track_rect *block = get_block_from_time(eventbox, timesecs, mt);
2173 (mt, (tmp = lives_markup_printf_escaped
2174 (
_(
"Current track: %s (layer %d)\n"),
2175 lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
2176 "track_name"), track)));
2178 if (track == -1)
add_context_label(mt, (tmp = (
_(
"Current track: Backing audio\n"))));
2180 lives_markup_printf_escaped(
_(
"Current track: Layer %d audio\n"), track)));
2198 static boolean atrack_ebox_pressed(LiVESWidget * labelbox, LiVESXEventButton * event, livespointer user_data) {
2199 lives_mt *mt = (lives_mt *)user_data;
2200 int current_track = mt->current_track;
2202 mt->current_track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(labelbox),
"layer_number"));
2203 if (current_track != mt->current_track) mt->fm_edit_event = NULL;
2204 mt->aud_track_selected =
TRUE;
2206 show_track_info(mt, (LiVESWidget *)lives_list_nth_data(mt->audio_draws, mt->current_track + mt->opts.back_audio_tracks),
2207 mt->current_track, mt->ptr_time);
2212 static boolean track_ebox_pressed(LiVESWidget * labelbox, LiVESXEventButton * event, livespointer user_data) {
2213 lives_mt *mt = (lives_mt *)user_data;
2214 int current_track = mt->current_track;
2216 mt->current_track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(labelbox),
"layer_number"));
2217 if (current_track != mt->current_track) mt->fm_edit_event = NULL;
2218 mt->aud_track_selected =
FALSE;
2220 show_track_info(mt, (LiVESWidget *)lives_list_nth_data(mt->video_draws, mt->current_track), mt->current_track, mt->ptr_time);
2225 static boolean on_mt_timeline_scroll(LiVESWidget * widget, LiVESXEventScroll * event, livespointer user_data) {
2227 lives_mt *mt = (lives_mt *)user_data;
2233 LiVESXModifierType kstate = (LiVESXModifierType)event->state;
2234 if ((kstate & LIVES_DEFAULT_MOD_MASK) == LIVES_CONTROL_MASK)
return on_mouse_scroll(widget, event, user_data);
2239 if (--cval < 0)
return FALSE;
2241 if (++cval >= mt->num_video_tracks)
return FALSE;
2250 static int get_top_track_for(lives_mt * mt,
int track) {
2253 LiVESWidget *eventbox;
2256 int hidden, expanded;
2258 if (mt->opts.back_audio_tracks > 0 && !mt->audio_draws) mt->opts.back_audio_tracks = 0;
2259 if (
mainw->
files[mt->render_file]->
achans > 0 && mt->opts.back_audio_tracks > 0) {
2260 eventbox = (LiVESWidget *)mt->audio_draws->data;
2261 hidden = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
HIDDEN_KEY));
2264 expanded = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"expanded"));
2271 if (extras < 0)
return track;
2273 vdraw = lives_list_nth(mt->video_draws, track);
2274 eventbox = (LiVESWidget *)vdraw->data;
2275 expanded = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"expanded"));
2277 eventbox = (LiVESWidget *)(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"atrack"));
2279 expanded = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"expanded"));
2285 if (extras < 0)
return track;
2287 vdraw = vdraw->prev;
2290 eventbox = (LiVESWidget *)vdraw->data;
2292 expanded = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"expanded"));
2295 eventbox = (LiVESWidget *)(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"atrack"));
2297 expanded = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"expanded"));
2302 if (extras < 0)
break;
2303 vdraw = vdraw->prev;
2307 if (track < 0) track = 0;
2312 static void redraw_all_event_boxes(lives_mt * mt) {
2315 slist = mt->audio_draws;
2317 redraw_eventbox(mt, (LiVESWidget *)slist->data);
2318 slist = slist->next;
2321 slist = mt->video_draws;
2323 redraw_eventbox(mt, (LiVESWidget *)slist->data);
2324 slist = slist->next;
2326 paint_lines(mt, mt->ptr_time,
TRUE, NULL);
2330 static boolean expose_paintlines(LiVESWidget * widget, lives_painter_t *cr, livespointer data) {
2331 int offset = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget),
2348 LiVESList *vdraws = mt->video_draws;
2349 LiVESList *table_children, *xlist;
2351 LiVESWidget *eventbox;
2355 LiVESWidget *checkbutton;
2356 LiVESWidget *labelbox;
2359 LiVESWidget *xeventbox, *aeventbox;
2361 LiVESWidgetColor col;
2378 if (top_track < 0) top_track = 0;
2379 if (top_track >= mt->num_video_tracks) top_track = mt->num_video_tracks - 1;
2381 mt->top_track = top_track;
2385 eventbox = (LiVESWidget *)vdraws->data;
2386 hidden = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
HIDDEN_KEY));
2388 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
HIDDEN_KEY, LIVES_INT_TO_POINTER(hidden));
2390 aeventbox = LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"atrack"));
2393 hidden = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(aeventbox),
HIDDEN_KEY));
2395 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(aeventbox),
HIDDEN_KEY, LIVES_INT_TO_POINTER(hidden));
2397 xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(aeventbox),
"achan0");
2400 hidden = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
HIDDEN_KEY));
2402 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
HIDDEN_KEY, LIVES_INT_TO_POINTER(hidden));
2405 xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(aeventbox),
"achan1");
2408 hidden = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
HIDDEN_KEY));
2410 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
HIDDEN_KEY, LIVES_INT_TO_POINTER(hidden));
2414 vdraws = vdraws->next;
2417 if (mt->timeline_table) {
2422 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(mt->timeline_table),
"has_line", LIVES_INT_TO_POINTER(-1));
2426 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(mt->timeline_table), LIVES_WIDGET_EXPOSE_EVENT,
2427 LIVES_GUI_CALLBACK(expose_paintlines),
2435 if (mt->opts.back_audio_tracks > 0 && !mt->audio_draws) mt->opts.back_audio_tracks = 0;
2437 if (
mainw->
files[mt->render_file]->
achans > 0 && mt->opts.back_audio_tracks > 0) {
2439 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mt->audio_draws->data),
HIDDEN_KEY)) == 0) {
2442 expanded = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mt->audio_draws->data),
"expanded"));
2444 label = (LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mt->audio_draws->data),
"label")));
2445 dummy = (LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mt->audio_draws->data),
"dummy")));
2446 arrow = (LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mt->audio_draws->data),
"arrow")));
2456 lives_table_attach(LIVES_TABLE(mt->timeline_table), dummy, 0, 2, 0, 1, LIVES_FILL, (LiVESAttachOptions)0, 0, 0);
2457 lives_table_attach(LIVES_TABLE(mt->timeline_table), labelbox, 2, 6, 0, 1, LIVES_FILL, (LiVESAttachOptions)0, 0, 0);
2458 lives_table_attach(LIVES_TABLE(mt->timeline_table), ahbox, 6, 7, 0, 1, LIVES_FILL, (LiVESAttachOptions)0, 0, 0);
2460 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(mt->audio_draws->data),
"labelbox", labelbox);
2461 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(mt->audio_draws->data),
"ahbox", ahbox);
2462 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(ahbox),
"eventbox", (livespointer)mt->audio_draws->data);
2463 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(labelbox),
"layer_number", LIVES_INT_TO_POINTER(-1));
2466 LIVES_GUI_CALLBACK(atrack_ebox_pressed), (livespointer)mt);
2472 (LiVESAttachOptions)(LIVES_EXPAND | LIVES_FILL), (LiVESAttachOptions)(0), 0, 0);
2478 lives_signal_connect(LIVES_GUI_OBJECT(mt->audio_draws->data), LIVES_WIDGET_BUTTON_RELEASE_EVENT,
2483 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->audio_draws->data), LIVES_WIDGET_EXPOSE_EVENT,
2484 LIVES_GUI_CALLBACK(expose_track_event), (livespointer)mt);
2487 xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mt->audio_draws->data),
"achan0");
2489 label = (LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"label")));
2495 lives_table_attach(LIVES_TABLE(mt->timeline_table), labelbox, 2, 6, 1, 2, LIVES_FILL, (LiVESAttachOptions)0, 0, 0);
2497 (LiVESAttachOptions)(LIVES_EXPAND | LIVES_FILL),
2498 (LiVESAttachOptions)(0), 0, 0);
2505 LIVES_GUI_CALLBACK(mt_expose_audtrack_event),
2509 xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mt->audio_draws->data),
"achan1");
2511 label = (LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"label")));
2517 lives_table_attach(LIVES_TABLE(mt->timeline_table), labelbox, 2, 6, 2, 3, LIVES_FILL, (LiVESAttachOptions)0, 0, 0);
2519 (LiVESAttachOptions)(LIVES_EXPAND | LIVES_FILL),
2520 (LiVESAttachOptions)(0), 0, 0);
2527 LIVES_GUI_CALLBACK(mt_expose_audtrack_event),
2538 vdraws = lives_list_nth(mt->video_draws, top_track);
2542 while (vdraws && rows < prefs->max_disp_vtracks) {
2543 eventbox = (LiVESWidget *)vdraws->data;
2546 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
HIDDEN_KEY, LIVES_INT_TO_POINTER(hidden));
2549 label = (LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"label")));
2550 arrow = (LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"arrow")));
2551 checkbutton = (LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"checkbutton")));
2560 #if GTK_CHECK_VERSION(3, 0, 0)
2568 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(labelbox),
"layer_number",
2569 LIVES_INT_TO_POINTER(LIVES_POINTER_TO_INT
2570 (lives_widget_object_get_data
2571 (LIVES_WIDGET_OBJECT(eventbox),
"layer_number"))));
2579 rows, rows + 1, LIVES_FILL, (LiVESAttachOptions)0, 0, 0);
2580 lives_table_attach(LIVES_TABLE(mt->timeline_table), ahbox, 6, 7, rows, rows + 1, LIVES_FILL, (LiVESAttachOptions)0, 0, 0);
2582 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"labelbox", labelbox);
2583 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"hbox", hbox);
2584 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"ahbox", ahbox);
2585 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(ahbox),
"eventbox", eventbox);
2588 (LiVESAttachOptions)(LIVES_EXPAND | LIVES_FILL), (LiVESAttachOptions)(0), 0, 0);
2593 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(checkbutton), LIVES_WIDGET_TOGGLED_SIGNAL,
2596 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(checkbutton), LIVES_WIDGET_MODE_CHANGED_SIGNAL,
2601 LIVES_GUI_CALLBACK(track_ebox_pressed), (livespointer)mt);
2605 lives_signal_sync_connect(LIVES_GUI_OBJECT(eventbox), LIVES_WIDGET_EXPOSE_EVENT,
2606 LIVES_GUI_CALLBACK(expose_track_event), (livespointer)mt);
2619 if (mt->opts.pertrack_audio && lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"expanded")) {
2621 aeventbox = LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"atrack"));
2623 hidden = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(aeventbox),
2625 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(aeventbox),
HIDDEN_KEY, LIVES_INT_TO_POINTER(hidden));
2630 expanded = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(aeventbox),
"expanded"));
2632 label = (LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(aeventbox),
"label")));
2633 dummy = (LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(aeventbox),
"dummy")));
2634 arrow = (LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(aeventbox),
"arrow")));
2648 LIVES_FILL, (LiVESAttachOptions)0, 0, 0);
2650 LIVES_FILL, (LiVESAttachOptions)0, 0, 0);
2652 LIVES_FILL, (LiVESAttachOptions)0, 0, 0);
2654 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(aeventbox),
"labelbox", labelbox);
2655 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(aeventbox),
"hbox", hbox);
2656 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(aeventbox),
"ahbox", ahbox);
2657 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(ahbox),
"eventbox", aeventbox);
2658 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(labelbox),
"layer_number",
2659 LIVES_INT_TO_POINTER(LIVES_POINTER_TO_INT
2660 (lives_widget_object_get_data
2661 (LIVES_WIDGET_OBJECT(eventbox),
"layer_number"))));
2664 LIVES_GUI_CALLBACK(atrack_ebox_pressed),
2672 (LiVESAttachOptions)(LIVES_EXPAND | LIVES_FILL), (LiVESAttachOptions)(0), 0, 0);
2682 lives_signal_sync_connect(LIVES_GUI_OBJECT(aeventbox), LIVES_WIDGET_EXPOSE_EVENT,
2683 LIVES_GUI_CALLBACK(expose_track_event), (livespointer)mt);
2689 xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(aeventbox),
"achan0");
2690 hidden = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
HIDDEN_KEY))
2692 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
HIDDEN_KEY, LIVES_INT_TO_POINTER(hidden));
2695 label = (LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"label")));
2709 labelbox, 2, 6, rows, rows + 1, LIVES_FILL, (LiVESAttachOptions)0, 0, 0);
2711 (LiVESAttachOptions)(LIVES_EXPAND | LIVES_FILL),
2712 (LiVESAttachOptions)(LIVES_FILL), 0, 0);
2714 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
"labelbox", labelbox);
2715 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
"hbox", hbox);
2720 LIVES_GUI_CALLBACK(mt_expose_audtrack_event),
2728 xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(aeventbox),
"achan1");
2729 hidden = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
HIDDEN_KEY))
2731 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
HIDDEN_KEY, LIVES_INT_TO_POINTER(hidden));
2734 label = (LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"label")));
2748 LIVES_FILL, (LiVESAttachOptions)0, 0, 0);
2750 (LiVESAttachOptions)(LIVES_EXPAND | LIVES_FILL),
2751 (LiVESAttachOptions)(0), 0, 0);
2755 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
"labelbox", labelbox);
2756 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
"hbox", hbox);
2761 LIVES_GUI_CALLBACK(mt_expose_audtrack_event),
2770 vdraws = vdraws->next;
2777 (
double)(get_top_track_for(mt, mt->num_video_tracks - 1) +
2788 while (table_children) {
2789 LiVESWidget *child = (LiVESWidget *)table_children->data;
2791 table_children = table_children->next;
2794 if (xlist) lives_list_free(xlist);
2796 paint_lines(mt, mt->ptr_time,
TRUE, NULL);
2801 mt->no_expose =
FALSE;
2808 LiVESWidget *eventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(ebox),
"eventbox");
2809 LiVESWidget *arrow = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"arrow"), *new_arrow;
2810 lives_mt *mt = (lives_mt *)user_data;
2811 boolean expanded = !(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"expanded"));
2815 if (!mt->audio_draws || (!mt->opts.pertrack_audio && (mt->opts.back_audio_tracks == 0 ||
2816 eventbox != mt->audio_draws->data))) {
2817 track_ebox_pressed(eventbox, NULL, mt);
2821 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"expanded", LIVES_INT_TO_POINTER(expanded));
2845 lives_mt *mt = (lives_mt *)user_data;
2851 lives_mt *mt = (lives_mt *)user_data;
2852 if (!mt->block_selected)
return;
2859 static char *time_to_string(
double secs) {
2860 int hours, mins, rest;
2863 hours = secs / 3600;
2864 secs -= hours * 3600.;
2867 rest = (secs - ((int)secs) * 1.) * 100. + .5;
2868 secs = (int)secs * 1.;
2869 lives_snprintf(timestring,
TIMECODE_LENGTH,
"%02d:%02d:%02d.%02d", hours, mins, (
int)secs, rest);
2870 return lives_strdup(timestring);
2874 static void update_timecodes(lives_mt * mt,
double dtime) {
2875 char *timestring = time_to_string(
QUANT_TIME(dtime));
2884 static void set_fxlist_label(lives_mt * mt) {
2885 char *tname =
get_track_name(mt, mt->current_track, mt->aud_track_selected);
2893 static void renumber_clips(
void) {
2904 boolean bad_header =
FALSE;
2906 renumbered_clips[0] = 0;
2913 for (cclip = 1; i <=
MAX_FILES; cclip++) {
2918 for (j = 0; j <
FN_KEYS - 1; j++) {
2925 if (LIVES_POINTER_TO_INT(clist->data) == i) {
2926 clist->data = LIVES_INT_TO_POINTER(cclip);
2929 clist = clist->next;
2940 renumbered_clips[i] = cclip;
2945 renumbered_clips[cclip] = cclip;
2946 if (i == cclip) i++;
2965 static void rerenumber_clips(
const char *lfile, weed_plant_t *event_list) {
2979 upd_layout_maps(event_list);
2981 renumbered_clips[0] = 0;
2984 renumbered_clips[i] = 0;
2986 else lfps[i] =
cfile->fps;
2994 if (!
lives_strncmp((
char *)lmap->data, lfile, strlen(lfile))) {
2996 array = lives_strsplit((
char *)lmap->data,
"|", -1);
3000 rnc = atoi(array[1]);
3001 if (rnc < 0 || rnc >
MAX_FILES)
continue;
3002 renumbered_clips[rnc] = i;
3005 lfps[i] = strtod(array[3], NULL);
3007 lives_strfreev(array);
3026 LiVESWidget *clipbox = NULL;
3027 boolean was_neg =
FALSE;
3030 mt->file_selected = -1;
3035 if (!mt->was_undo_redo) {
3039 if (mt->clip_selected < 0) {
3041 mt->clip_selected = -mt->clip_selected;
3044 if (mt->clip_selected >= (len = lives_list_length(list)) && !was_neg) mt->clip_selected = 0;
3046 if (was_neg) mt->clip_selected--;
3048 if (mt->clip_selected < 0 || (was_neg && mt->clip_selected == 0)) mt->clip_selected = len - 1;
3050 if (mt->clip_selected < 0) {
3051 mt->file_selected = -1;
3052 lives_list_free(list);
3067 for (
int i = 0; i < len; i++) {
3068 clipbox = (LiVESWidget *)lives_list_nth_data(list, i);
3069 if (i == mt->clip_selected) {
3077 if (mt->current_track > -1) {
3092 lives_list_free(list);
3096 boolean mt_prevclip(LiVESAccelGroup * group, LiVESWidgetObject * obj, uint32_t keyval, LiVESXModifierType mod,
3097 livespointer user_data) {
3098 lives_mt *mt = (lives_mt *)user_data;
3100 mt->clip_selected--;
3107 boolean mt_nextclip(LiVESAccelGroup * group, LiVESWidgetObject * obj, uint32_t keyval, LiVESXModifierType mod,
3108 livespointer user_data) {
3109 lives_mt *mt = (lives_mt *)user_data;
3111 mt->clip_selected++;
3118 static void set_time_scrollbar(lives_mt * mt) {
3119 double page = mt->tl_max - mt->tl_min;
3120 if (mt->end_secs == 0.) mt->end_secs =
DEF_TIME;
3122 if (mt->tl_max > mt->end_secs) mt->end_secs = mt->tl_max;
3124 lives_widget_object_freeze_notify(LIVES_WIDGET_OBJECT(mt->hadjustment));
3129 lives_widget_object_thaw_notify(LIVES_WIDGET_OBJECT(mt->hadjustment));
3135 double pos = mt->ptr_time;
3137 mt->end_secs = secs;
3140 giw_timeline_set_max_size(GIW_TIMELINE(mt->timeline), mt->end_secs);
3145 lives_ruler_set_range(LIVES_RULER(mt->timeline), mt->tl_min, mt->tl_max, mt->tl_min, mt->end_secs + 1. / mt->fps);
3148 if (!mt->sel_locked || mt->region_end < mt->end_secs + 1. / mt->fps) {
3152 set_time_scrollbar(mt);
3156 redraw_all_event_boxes(mt);
3160 static weed_timecode_t set_play_position(lives_mt * mt) {
3162 boolean has_pb_loop_event =
FALSE;
3164 #ifdef ENABLE_JACK_TRANSPORT
3170 #ifdef ENABLE_JACK_TRANSPORT
3175 has_pb_loop_event =
TRUE;
3183 if (end_tc > 0) tc %= end_tc;
3184 mt->is_paused =
FALSE;
3193 mt->pb_unpaused_start_time = mt->ptr_time;
3195 mt->pb_start_time = mt->ptr_time;
3198 #ifdef ENABLE_JACK_TRANSPORT
3207 if (!has_pb_loop_event) mt->pb_loop_event = mt->pb_start_event;
3221 weed_timecode_t curr_tc;
3223 double ptr_time = mt->ptr_time;
3232 boolean needs_idlefunc =
FALSE;
3233 boolean did_backup = mt->did_backup;
3234 static boolean lastblank =
TRUE;
3237 if (mt->no_frame_update)
return;
3241 if (mt->idlefunc > 0) {
3244 needs_idlefunc =
TRUE;
3247 if (!return_layer) {
3249 if (!mt->mt_frame_preview) {
3251 mt->mt_frame_preview =
TRUE;
3274 #if GTK_CHECK_VERSION(3, 0, 0)
3275 if (!mt->frame_pixbuf || mt->frame_pixbuf !=
mainw->
imframe) {
3285 #if GTK_CHECK_VERSION(3, 0, 0)
3288 mt->frame_pixbuf = NULL;
3296 if (needs_idlefunc || (!did_backup && mt->auto_changed)) {
3303 curr_tc = set_play_position(mt);
3307 if (mt->is_rendering && actual_frame <= mainw->files[mt->render_file]->frames) {
3312 weed_plant_t *live_inst = NULL;
3315 if (mt->event_list) {
3316 if (mt->pb_start_event) {
3317 cfile->next_event = mt->pb_start_event;
3334 if (mt->current_rfx && mt->init_event) {
3336 live_inst = (weed_plant_t *)mt->current_rfx->source;
3346 int key = atoi(keystr) + 1;
3354 if (mt->current_rfx->source) {
3358 for (
int i = 0; i < nparams; i++) {
3359 weed_leaf_dup(dst_params[i], src_params[i], WEED_LEAF_VALUE);
3362 mt->solo_inst = mt->current_rfx->source;
3364 mt->solo_inst = NULL;
3385 mt->preview_layer = -100000;
3386 mt->solo_inst = NULL;
3392 if (live_inst) mt->current_rfx->source = (
void *)live_inst;
3404 if (needs_idlefunc || (!did_backup && mt->auto_changed)) {
3410 #if GTK_CHECK_VERSION(3, 0, 0)
3411 if (mt->frame_pixbuf && mt->frame_pixbuf !=
mainw->
imframe) {
3413 mt->frame_pixbuf = NULL;
3417 if (mt->frame_pixbuf && mt->frame_pixbuf ==
mainw->
imframe) {
3425 LiVESPixbuf *pixbuf = NULL;
3426 int pwidth, pheight, lb_width, lb_height;
3427 int cpal = WEED_PALETTE_RGB24, layer_palette;
3428 boolean was_letterboxed =
FALSE;
3434 pwidth = mt->play_width;
3435 pheight = mt->play_height;
3437 if (weed_get_boolean_value(
mainw->
frame_layer,
"letterboxed", NULL) == WEED_FALSE) {
3444 pheight = lb_height;
3446 LIVES_INTERP_BEST, cpal, 0))
3448 was_letterboxed =
TRUE;
3468 #if GTK_CHECK_VERSION(3, 0, 0)
3470 mt->frame_pixbuf = pixbuf;
3484 #if GTK_CHECK_VERSION(3, 0, 0)
3493 if (mt->frame_pixbuf && mt->frame_pixbuf !=
mainw->
imframe) {
3496 mt->frame_pixbuf = NULL;
3504 if (needs_idlefunc || (!did_backup && mt->auto_changed)) {
3510 static void tc_to_rs(LiVESMenuItem * menuitem, livespointer user_data) {
3511 lives_mt *mt = (lives_mt *)user_data;
3512 mt->region_start = mt->ptr_time;
3517 static void tc_to_re(LiVESMenuItem * menuitem, livespointer user_data) {
3518 lives_mt *mt = (lives_mt *)user_data;
3519 mt->region_end = mt->ptr_time;
3524 static void rs_to_tc(LiVESMenuItem * menuitem, livespointer user_data) {
3525 lives_mt *mt = (lives_mt *)user_data;
3530 static void re_to_tc(LiVESMenuItem * menuitem, livespointer user_data) {
3531 lives_mt *mt = (lives_mt *)user_data;
3538 static void _mt_tl_move(lives_mt * mt,
double pos) {
3540 if (pos < 0.) pos = 0.;
3556 if (mt->is_paused) {
3557 mt->is_paused =
FALSE;
3563 if (mt->init_event && mt->poly_state ==
POLY_PARAMS && !mt->block_node_spin) {
3564 mt->block_tl_move =
TRUE;
3567 mt->block_tl_move =
FALSE;
3570 update_timecodes(mt, pos);
3578 if (mt->init_event) {
3582 mt->init_event = NULL;
3590 paint_lines(mt, pos,
TRUE, NULL);
3605 boolean mt_tlfor(LiVESAccelGroup * group, LiVESWidgetObject * obj, uint32_t keyval, LiVESXModifierType mod,
3606 livespointer user_data) {
3607 lives_mt *mt = (lives_mt *)user_data;
3609 mt->fm_edit_event = NULL;
3615 boolean mt_tlfor_frame(LiVESAccelGroup * group, LiVESWidgetObject * obj, uint32_t keyval, LiVESXModifierType mod,
3616 livespointer user_data) {
3617 lives_mt *mt = (lives_mt *)user_data;
3619 mt->fm_edit_event = NULL;
3625 boolean mt_tlback(LiVESAccelGroup * group, LiVESWidgetObject * obj, uint32_t keyval, LiVESXModifierType mod,
3626 livespointer user_data) {
3627 lives_mt *mt = (lives_mt *)user_data;
3629 mt->fm_edit_event = NULL;
3634 boolean mt_tlback_frame(LiVESAccelGroup * group, LiVESWidgetObject * obj, uint32_t keyval, LiVESXModifierType mod,
3635 livespointer user_data) {
3636 lives_mt *mt = (lives_mt *)user_data;
3638 mt->fm_edit_event = NULL;
3644 static void scroll_track_on_screen(lives_mt * mt,
int track) {
3645 if (track > mt->top_track) track = get_top_track_for(mt, track);
3651 lives_mt *mt = (lives_mt *)user_data;
3657 static void mt_zoom(lives_mt * mt,
double scale) {
3663 double tl_span = (mt->tl_max - mt->tl_min) / 2.;
3667 tl_cur = mt->ptr_time;
3669 tl_cur = mt->tl_min + tl_span;
3673 mt->tl_min = tl_cur - tl_span * scale;
3674 mt->tl_max = tl_cur + tl_span * scale;
3676 if (mt->tl_min < 0.) {
3677 mt->tl_max -= mt->tl_min;
3684 if (mt->tl_min == mt->tl_max) mt->tl_max = mt->tl_min + 1. / mt->fps;
3687 giw_timeline_set_max_size(GIW_TIMELINE(mt->timeline), mt->tl_max);
3692 set_time_scrollbar(mt);
3696 redraw_all_event_boxes(mt);
3700 static void scroll_time_by_scrollbar(LiVESHScrollbar * sbar, livespointer user_data) {
3701 lives_mt *mt = (lives_mt *)user_data;
3706 paint_lines(mt, mt->ptr_time,
TRUE, NULL);
3710 boolean mt_trdown(LiVESAccelGroup * group, LiVESWidgetObject * obj, uint32_t keyval, LiVESXModifierType mod,
3711 livespointer user_data) {
3712 lives_mt *mt = (lives_mt *)user_data;
3715 if (mt->current_track >= 0 && mt->opts.pertrack_audio && !mt->aud_track_selected) {
3716 LiVESWidget *eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, mt->current_track);
3717 mt->aud_track_selected = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"expanded"));
3718 if (!mt->aud_track_selected && mt->current_track == mt->num_video_tracks - 1)
return TRUE;
3720 if (mt->current_track == mt->num_video_tracks - 1)
return TRUE;
3721 mt->aud_track_selected =
FALSE;
3724 if (!mt->aud_track_selected || mt->current_track == -1) {
3725 if (mt->current_track > -1) mt->current_track++;
3728 LiVESList *llist = mt->video_draws;
3730 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(llist->data),
HIDDEN_KEY)) == 0) {
3731 mt->current_track = i;
3734 llist = llist->next;
3737 mt->current_track = i;
3740 mt->selected_init_event = NULL;
3741 scroll_track_on_screen(mt, mt->current_track);
3748 boolean mt_trup(LiVESAccelGroup * group, LiVESWidgetObject * obj, uint32_t keyval, LiVESXModifierType mod,
3749 livespointer user_data) {
3750 lives_mt *mt = (lives_mt *)user_data;
3751 if (mt->current_track == -1 || (mt->current_track == 0 && !mt->aud_track_selected && !mt->opts.show_audio))
return TRUE;
3754 if (mt->aud_track_selected) mt->aud_track_selected =
FALSE;
3756 mt->current_track--;
3757 if (mt->current_track >= 0 && mt->opts.pertrack_audio) {
3758 LiVESWidget *eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, mt->current_track);
3759 mt->aud_track_selected = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"expanded"));
3762 mt->selected_init_event = NULL;
3763 if (mt->current_track != -1) scroll_track_on_screen(mt, mt->current_track);
3785 static void notebook_error(LiVESNotebook * nb, uint32_t tab,
lives_mt_nb_error_t err, lives_mt * mt) {
3789 mt->nb_label = NULL;
3795 mt->nb_label =
lives_standard_label_new(
_(
"\n\nPlease select a block\nin the timeline by\nright or double clicking on it.\n"));
3799 _(
"\n\nNo effect selected.\nSelect an effect in FX stack first to view its parameters.\n"));
3806 _(
"You must select two video tracks\nand a time region\nto apply transitions.\n\n"
3807 "Alternately, you can enable Autotransitions from the Effects menu\nbefore inserting clips into the timeline."));
3811 _(
"\n\nYou must select at least one video track\nand a time region\nto apply compositors.\n"));
3833 static void fubar(lives_mt * mt) {
3840 mt->init_event = mt->selected_init_event;
3842 mt->track_index = -1;
3844 in_tracks = weed_get_int_array_counted(mt->init_event,
WEED_LEAF_IN_TRACKS, &num_in_tracks);
3845 if (num_in_tracks > 0) {
3847 for (i = 0; i < num_in_tracks; i++) {
3848 if (mt->current_track == in_tracks[i]) {
3849 mt->track_index = i;
3860 pchainx = weed_get_voidptr_array_counted(mt->init_event, WEED_LEAF_IN_PARAMETERS, &npch);
3862 pchain = (
void **)
lives_malloc((npch + 1) *
sizeof(
void *));
3863 for (i = 0; i < npch; i++) pchain[i] = pchainx[i];
3870 static boolean notebook_page(LiVESWidget * nb, LiVESWidget * nbp, uint32_t tab, livespointer user_data) {
3875 lives_mt *mt = (lives_mt *)user_data;
3887 mt->nb_label = NULL;
3897 if (!mt->clip_labels) {
3905 if (!mt->block_selected && mt->poly_state !=
POLY_IN_OUT) {
3906 notebook_error(LIVES_NOTEBOOK(mt->nb), tab,
NB_ERROR_SEL, mt);
3917 if (!mt->block_selected && mt->poly_state !=
POLY_EFFECTS) {
3918 notebook_error(LIVES_NOTEBOOK(mt->nb), tab,
NB_ERROR_SEL, mt);
3925 if (lives_list_length(mt->selected_tracks) != 2 || mt->region_start == mt->region_end) {
3935 if (!mt->selected_tracks || mt->region_start == mt->region_end) {
3943 if (mt->poly_state !=
POLY_PARAMS && !mt->selected_init_event) {
3948 if (mt->selected_init_event && mt->poly_state !=
POLY_PARAMS) {
3973 static void select_block(lives_mt * mt) {
3974 track_rect *block = mt->putative_block;
3980 LiVESWidget *eventbox = block->eventbox;
3982 if (!
mainw->
files[mt->render_file]->
achans || !mt->audio_draws || (mt->opts.back_audio_tracks == 0 ||
3983 eventbox != mt->audio_draws->data))
3984 track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"layer_number"));
3990 mt->block_selected = block;
3994 if (
mainw->
files[mt->render_file]->
achans == 0 || !mt->audio_draws || (mt->opts.back_audio_tracks == 0 ||
3995 eventbox != mt->audio_draws->data))
3996 add_context_label(mt, (tmp2 = lives_markup_printf_escaped(
_(
"Current track: %s (layer %d)\n"),
3997 lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"track_name"), track)));
4018 redraw_eventbox(mt, eventbox);
4021 paint_lines(mt, mt->ptr_time,
TRUE, NULL);
4024 mt->context_time = -1.;
4034 pkg_list = lives_list_append(pkg_list, pkgstring);
4035 return lives_list_length(pkg_list);
4039 return strdup(lives_list_nth_data(pkg_list, pkgnum - 1));
4047 static void populate_filter_box(
int ninchans, lives_mt * mt,
int pkgnum);
4049 static boolean filter_ebox_pressed(LiVESWidget * eventbox, LiVESXEventButton * event, livespointer user_data) {
4050 lives_mt *mt = (lives_mt *)user_data;
4054 if (mt->is_rendering)
return FALSE;
4056 if ((pkgnum = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"pkgnum"))) != 0) {
4057 populate_filter_box(0, mt, pkgnum);
4061 mt->selected_filter = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"fxid"));
4063 if (event->type != LIVES_BUTTON_PRESS) {
4070 if (!mt->video_draws && !mt->audio_draws) {
4074 mt->hotspot_x = mt->hotspot_y = 0;
4082 static boolean on_drag_filter_end(LiVESWidget * widget, LiVESXEventButton * event, livespointer user_data) {
4083 LiVESXWindow *window;
4084 LiVESWidget *eventbox = NULL, *oeventbox;
4085 LiVESWidget *labelbox;
4088 lives_mt *mt = (lives_mt *)user_data;
4089 double timesecs = 0.;
4090 int win_x, win_y, nins;
4095 mt->selected_filter = -1;
4102 mt->selected_filter = -1;
4108 mt->display, &win_x, &win_y);
4111 for (list = mt->audio_draws; list; list = list->next) {
4112 eventbox = (LiVESWidget *)list->data;
4113 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
HIDDEN_KEY)) != 0)
continue;
4114 labelbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"labelbox");
4118 mt->timeline, &mt->sel_x, &mt->sel_y);
4121 tchan = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"layer_number"));
4122 if ((oeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"owner")) != NULL) {
4123 eventbox = oeventbox;
4132 for (list = mt->video_draws; list; list = list->next) {
4133 eventbox = (LiVESWidget *)list->data;
4134 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
HIDDEN_KEY)) != 0)
continue;
4135 labelbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"labelbox");
4136 ahbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"ahbox");
4141 mt->timeline, &mt->sel_x, &mt->sel_y);
4144 tchan = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"layer_number"));
4152 mt->selected_filter = -1;
4156 mt->current_fx = mt->selected_filter;
4157 mt->selected_filter = -1;
4161 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(dummy_menuitem),
"idx", LIVES_INT_TO_POINTER(mt->current_fx));
4181 block = get_block_from_time(eventbox, timesecs, mt);
4188 mt->putative_block = block;
4191 if (mt->current_track < 0) mt->aud_track_selected =
TRUE;
4192 else mt->aud_track_selected =
FALSE;
4198 mt->putative_block = NULL;
4200 }
else if (nins == 2) {
4202 if (lives_list_length(mt->selected_tracks) == 2 && mt->region_start != mt->region_end) {
4204 lives_timer_add_simple(0, mt_add_region_effect_idle, mt);
4206 }
else if (nins >= 1000000) {
4208 if (mt->selected_tracks && mt->region_start != mt->region_end) {
4210 lives_timer_add_simple(0, mt_add_region_effect_idle, mt);
4219 static void add_to_listbox(lives_mt * mt, LiVESWidget * xeventbox,
char *fname,
boolean add_top) {
4247 lives_signal_sync_connect(LIVES_GUI_OBJECT(xeventbox), LIVES_WIDGET_BUTTON_PRESS_EVENT,
4248 LIVES_GUI_CALLBACK(filter_ebox_pressed), (livespointer)mt);
4249 lives_signal_sync_connect(LIVES_GUI_OBJECT(xeventbox), LIVES_WIDGET_BUTTON_RELEASE_EVENT,
4250 LIVES_GUI_CALLBACK(on_drag_filter_end), (livespointer)mt);
4254 static void populate_filter_box(
int ninchans, lives_mt * mt,
int pkgnum) {
4255 static int oxninchans = 0;
4257 LiVESWidget *eventbox = NULL, *xeventbox;
4258 char *fname, *pkgstring = NULL, *pkg_name = NULL, *catstring;
4268 LIVES_POLICY_AUTOMATIC, LIVES_POLICY_AUTOMATIC);
4279 if (!mt->block_selected && ninchans == 1)
return;
4281 if (mt->block_selected) eventbox = mt->block_selected->eventbox;
4284 ninchans = oxninchans;
4285 if (pkgnum == -1) pkgnum = 0;
4291 oxninchans = ninchans;
4297 for (i = 0; i < nfilts; i++) {
4301 int mandouts = 0, nouts = 0;
4302 weed_plant_t **ctmpls;
4305 (!
is_pure_audio(filter,
FALSE) && eventbox && is_audio_eventbox(eventbox)))
continue;
4312 for (j = 0; j < nouts; j++) {
4319 if (j < nouts)
continue;
4321 if ((nins == ninchans || (ninchans == 1000000 && nins >= ninchans)) && mandouts == 1) {
4327 if (pkg_name && strcmp(pkgstring, pkg_name)) {
4333 if (!pkg_name || !(*pkg_name)) {
4338 fname =
lives_strdup_printf(
_(
"%s from %s package (CLICK TO SHOW) ---->"), catstring, pkgstring);
4353 if (pkg_name && *pkg_name && !pkgstring) {
4363 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
"fxid", LIVES_INT_TO_POINTER(sorted));
4364 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
"pkgnum", LIVES_INT_TO_POINTER(pkgnum));
4368 add_to_listbox(mt, xeventbox, fname,
FALSE);
4376 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
"fxid", LIVES_INT_TO_POINTER(0));
4377 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
"pkgnum", LIVES_INT_TO_POINTER(-1));
4380 add_to_listbox(mt, xeventbox, fname,
TRUE);
4388 static track_rect *mt_selblock(LiVESMenuItem * menuitem, livespointer user_data) {
4390 lives_mt *mt = (lives_mt *)user_data;
4391 LiVESWidget *eventbox;
4392 double timesecs = mt->ptr_time;
4393 boolean desel =
TRUE;
4395 if (mt->current_track == -1 || mt->aud_track_selected)
4396 eventbox = (LiVESWidget *)lives_list_nth_data(mt->audio_draws, mt->current_track + mt->opts.back_audio_tracks);
4397 else eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, mt->current_track);
4399 if (!menuitem)
return get_block_from_time(eventbox, timesecs, mt);
4401 mt->putative_block = get_block_from_time(eventbox, timesecs, mt);
4406 if (!desel) select_block((lives_mt *)user_data);
4408 return mt->putative_block;
4413 lives_mt *mt = (lives_mt *)user_data;
4415 paint_lines(mt, mt->ptr_time,
TRUE, NULL);
4419 void mt_zoom_in(LiVESMenuItem * menuitem, livespointer user_data) {
4420 lives_mt *mt = (lives_mt *)user_data;
4425 paint_lines(mt, mt->ptr_time,
TRUE, NULL);
4430 lives_mt *mt = (lives_mt *)user_data;
4435 paint_lines(mt, mt->ptr_time,
TRUE, NULL);
4439 static void hpaned_position(LiVESWidgetObject *
object, livespointer pspec, livespointer user_data) {
4440 lives_mt *mt = (lives_mt *)user_data;
4445 static void no_time_selected(lives_mt * mt) {
4453 lives_mt *mt = (lives_mt *)user_data;
4454 boolean has_region = (mt->region_start != mt->region_end);
4466 if ((((mt->region_start != mt->region_end && !has_region) || (mt->region_start == mt->region_end && has_region))) &&
4469 if (mt->selected_tracks) {
4471 if (mt->region_start != mt->region_end) {
4476 switch (lives_list_length(mt->selected_tracks)) {
4485 if (!mt->opts.pertrack_audio)
4500 if (mt->region_start == mt->region_end) no_time_selected(mt);
4507 lives_mt *mt = (lives_mt *)user_data;
4508 boolean has_region = (mt->region_start != mt->region_end);
4520 if ((((mt->region_start != mt->region_end && !has_region) || (mt->region_start == mt->region_end && has_region))) &&
4523 if (mt->selected_tracks) {
4525 if (mt->region_start != mt->region_end) {
4531 switch (lives_list_length(mt->selected_tracks)) {
4541 if (!mt->opts.pertrack_audio)
4556 if (mt->region_start == mt->region_end) no_time_selected(mt);
4562 static boolean in_out_ebox_pressed(LiVESWidget * eventbox, LiVESXEventButton * event, livespointer user_data) {
4568 lives_mt *mt = (lives_mt *)user_data;
4572 if (mt->block_selected)
return FALSE;
4579 if (!mt->video_draws && !mt->audio_draws) {
4583 if (!mt->opts.ign_ins_sel) {
4584 width = (sfile->
end - sfile->
start + 1.) / sfile->
fps;
4589 if (width == 0)
return FALSE;
4590 width = width / (mt->tl_max - mt->tl_min) * (
double)ebwidth;
4591 if (width > ebwidth) width = ebwidth;
4592 if (width < 2) width = 2;
4593 height = get_track_height(mt);
4598 mt->hotspot_x = mt->hotspot_y = 0;
4605 static void do_clip_context(lives_mt * mt, LiVESXEventButton * event,
lives_clip_t *sfile) {
4608 LiVESWidget *edit_start_end, *edit_clipedit, *close_clip, *show_clipinfo;
4625 lives_signal_sync_connect(LIVES_GUI_OBJECT(edit_clipedit), LIVES_WIDGET_ACTIVATE_SIGNAL,
4656 static boolean clip_ebox_pressed(LiVESWidget * eventbox, LiVESXEventButton * event, livespointer user_data) {
4657 lives_mt *mt = (lives_mt *)user_data;
4664 if (!mt->is_ready)
return FALSE;
4668 if (event->type != LIVES_BUTTON_PRESS && !mt->is_rendering) {
4682 if (event->button == 3) {
4685 mt->timeline, &mt->sel_x, &mt->sel_y);
4689 do_clip_context(mt, event, sfile);
4694 if (!mt->video_draws && !mt->audio_draws) {
4698 if (!mt->opts.ign_ins_sel) {
4699 width = (sfile->
end - sfile->
start + 1.) / sfile->
fps;
4704 if (width == 0)
return FALSE;
4705 width = width / (mt->tl_max - mt->tl_min) * (
double)ebwidth;
4706 if (width > ebwidth) width = ebwidth;
4707 if (width < 2) width = 2;
4708 height = get_track_height(mt);
4711 mt->hotspot_x = mt->hotspot_y = 0;
4718 static boolean on_drag_clip_end(LiVESWidget * widget, LiVESXEventButton * event, livespointer user_data) {
4719 lives_mt *mt = (lives_mt *)user_data;
4721 LiVESXWindow *window;
4722 LiVESWidget *eventbox;
4723 LiVESWidget *labelbox;
4726 double timesecs, osecs;
4735 if (mt->is_rendering)
return FALSE;
4739 osecs = mt->ptr_time;
4747 mt->display, &win_x, &win_y);
4749 if (
mainw->
files[mt->render_file]->
achans > 0 && mt->opts.back_audio_tracks > 0 &&
4750 LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mt->audio_draws->data),
HIDDEN_KEY)) == 0) {
4751 labelbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mt->audio_draws->data),
"labelbox");
4752 ahbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mt->audio_draws->data),
"ahbox");
4761 mt->timeline, &mt->sel_x, &mt->sel_y);
4764 mt->current_track = -1;
4769 if (!mt->is_paused) {
4774 if (timesecs > 0.) {
4792 for (LiVESList *list = mt->video_draws; list; list = list->next) {
4793 eventbox = (LiVESWidget *)list->data;
4795 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
HIDDEN_KEY)) != 0)
continue;
4797 labelbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"labelbox");
4798 ahbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"ahbox");
4804 mt->timeline, &mt->sel_x, &mt->sel_y);
4807 mt->current_track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"layer_number"));
4808 mt->aud_track_selected =
FALSE;
4814 if (!mt->is_paused) {
4816 if (timesecs > 0.) {
4836 static boolean on_clipbox_enter(LiVESWidget * widget, LiVESXEventCrossing * event, livespointer user_data) {
4837 lives_mt *mt = (lives_mt *)user_data;
4860 LIVES_KEY_m, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
4864 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->amixer_button), LIVES_WIDGET_CLICKED_SIGNAL,
4865 LIVES_GUI_CALLBACK(
amixer_show), (livespointer)mt);
4868 (tmp2 = H_(
"When active, all layers will be audible regardless of visibility")),
4869 &mt->opts.audio_bleedthru);
4882 mt->l_sel_arrow =
lives_arrow_new(LIVES_ARROW_LEFT, LIVES_SHADOW_OUT);
4891 mt->r_sel_arrow =
lives_arrow_new(LIVES_ARROW_RIGHT, LIVES_SHADOW_OUT);
4906 mt->spin_start_func = lives_signal_sync_connect_after(LIVES_GUI_OBJECT(mt->spinbutton_start), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
4910 mt->spin_end_func = lives_signal_sync_connect_after(LIVES_GUI_OBJECT(mt->spinbutton_end), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
4917 char *fname, *text, *tmp;
4947 const char *mtext = NULL;
4952 if (!mt->ins_label) {
4966 static void on_insert_mode_changed(LiVESMenuItem * menuitem, livespointer user_data) {
4967 lives_mt *mt = (lives_mt *)user_data;
4971 if (menuitem == (LiVESMenuItem *)mt->ins_normal) {
4978 static void on_mouse_mode_changed(LiVESMenuItem * menuitem, livespointer user_data) {
4979 lives_mt *mt = (lives_mt *)user_data;
4984 if (menuitem == (LiVESMenuItem *)mt->mm_move) {
4986 }
else if (menuitem == (LiVESMenuItem *)mt->mm_select) {
4992 if (!mt->ins_label) {
5014 const char *mtext = NULL;
5047 static void on_grav_mode_changed(LiVESMenuItem * menuitem, livespointer user_data) {
5048 lives_mt *mt = (lives_mt *)user_data;
5052 if (menuitem == (LiVESMenuItem *)mt->grav_normal) {
5054 }
else if (menuitem == (LiVESMenuItem *)mt->grav_left) {
5056 }
else if (menuitem == (LiVESMenuItem *)mt->grav_right) {
5063 static size_t estimate_space(lives_mt * mt,
int undo_type) {
5064 size_t needed =
sizeof(
mt_undo);
5066 switch (undo_type) {
5070 needed += event_list_get_byte_size(mt, mt->event_list,
FALSE, NULL);
5077 static char *get_undo_text(
int action,
void *extra) {
5078 char *filtname, *ret;
5082 return (
_(
"Close gaps"));
5084 return (
_(
"Move block"));
5086 return (
_(
"Move audio block"));
5088 return (
_(
"Delete block"));
5090 return (
_(
"Delete audio block"));
5092 return (
_(
"Split tracks"));
5094 return (
_(
"Split block"));
5096 filtname = weed_get_string_value((weed_plant_t *)extra, WEED_LEAF_NAME, NULL);
5101 filtname = weed_get_string_value((weed_plant_t *)extra, WEED_LEAF_NAME, NULL);
5106 return (
_(
"Insert block"));
5108 return (
_(
"Insert gap"));
5110 return (
_(
"Insert audio block"));
5112 return (
_(
"Effect order change"));
5114 return lives_strdup(
"");
5118 static void mt_set_undoable(lives_mt * mt,
int what,
void *extra,
boolean sensitive) {
5119 mt->undoable = sensitive;
5122 char *text = get_undo_text(what, extra);
5123 what_safe = lives_strdelimit(lives_strdup(text),
"_",
' ');
5124 lives_snprintf(mt->undo_text, 32,
_(
"_Undo %s"), what_safe);
5129 mt->undoable =
FALSE;
5130 lives_snprintf(mt->undo_text, 32,
"%s",
_(
"_Undo"));
5138 static void mt_set_redoable(lives_mt * mt,
int what,
void *extra,
boolean sensitive) {
5139 mt->redoable = sensitive;
5142 char *text = get_undo_text(what, extra);
5143 what_safe = lives_strdelimit(lives_strdup(text),
"_",
' ');
5144 lives_snprintf(mt->redo_text, 32,
_(
"_Redo %s"), what_safe);
5148 mt->redoable =
FALSE;
5149 lives_snprintf(mt->redo_text, 32,
"%s",
_(
"_Redo"));
5159 size_t space_avail = (size_t)(
prefs->
mt_undo_buf * 1024 * 1024) - mt->undo_buffer_used;
5160 size_t space_freed = 0;
5162 LiVESList *xundo = mt->undos, *ulist;
5168 undo = (
mt_undo *)(xundo->data);
5170 if ((space_avail + space_freed) >= space_needed) {
5171 lives_memmove(mt->undo_mem, mt->undo_mem + space_freed, mt->undo_buffer_used - space_freed);
5172 ulist = lives_list_copy(lives_list_nth(mt->undos, count));
5173 if (ulist) ulist->prev = NULL;
5174 lives_list_free(mt->undos);
5177 ulist->data = (
unsigned char *)(ulist->data) - space_freed;
5178 ulist = ulist->next;
5180 mt->undo_buffer_used -= space_freed;
5181 if (mt->undo_offset > (len = lives_list_length(mt->undos))) {
5182 mt->undo_offset = len;
5184 mt_set_redoable(mt, ((
mt_undo *)(mt->undos->data))->action, NULL,
TRUE);
5188 xundo = xundo->next;
5190 mt->undo_buffer_used = 0;
5191 lives_list_free(mt->undos);
5193 mt->undo_offset = 0;
5200 void mt_backup(lives_mt * mt,
int undo_type, weed_timecode_t tc) {
5203 size_t space_needed = 0;
5207 unsigned char *memblock, *omemblock;
5209 if (mt->did_backup)
return;
5212 mt->did_backup = mt->changed =
TRUE;
5218 if (!mt->undo_mem)
return;
5220 if (mt->undos && mt->undo_offset != 0) {
5223 if ((lives_list_length(mt->undos)) == mt->undo_offset) {
5225 mt->undo_buffer_used = 0;
5228 LiVESList *ulist = mt->undos;
5229 for (i = (
int)lives_list_length(mt->undos) - mt->undo_offset; --i > 0; ulist = ulist->next);
5231 memblock = (
unsigned char *)ulist->data;
5232 last_valid_undo = (
mt_undo *)memblock;
5233 memblock += last_valid_undo->
data_len;
5234 mt->undo_buffer_used = memblock - mt->undo_mem;
5236 ulist = ulist->next;
5237 ulist->prev->next = NULL;
5238 lives_list_free(ulist);
5243 mt->undo_offset = 0;
5250 switch (undo_type) {
5265 if ((space_needed = estimate_space(mt, undo_type) +
sizeof(
mt_undo)) >
5274 omemblock = memblock = (
unsigned char *)(mt->undo_mem + mt->undo_buffer_used +
sizeof(
mt_undo));
5276 undo->
data_len = memblock - omemblock;
5282 mt->undos = lives_list_append(mt->undos, mt->undo_mem + mt->undo_buffer_used);
5283 mt->undo_buffer_used += space_needed;
5290 lives_mt *mt = (lives_mt *)user_data;
5292 int which = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(menuitem),
"pnum"));
5295 mt->opts.aparam_view_list = lives_list_append(mt->opts.aparam_view_list, LIVES_INT_TO_POINTER(which));
5296 else mt->opts.aparam_view_list = lives_list_remove(mt->opts.aparam_view_list, LIVES_INT_TO_POINTER(which));
5297 for (list = mt->audio_draws; list; list = list->next) {
5303 static void destroy_widget(LiVESWidget * widget, livespointer user_data) {
5310 LiVESWidget *menuitem;
5311 weed_plant_t *filter;
5317 if (mt->avol_fx == -1 || !mt->audio_draws) {
5328 if (mt->opts.aparam_view_list && !
mainw->
multi_opts.aparam_view_list) {
5329 lives_list_free(mt->opts.aparam_view_list);
5330 mt->opts.aparam_view_list = NULL;
5334 if (mt->opts.pertrack_audio) {
5355 mt->opts.aparam_view_list && lives_list_find(mt->opts.aparam_view_list, LIVES_INT_TO_POINTER(i)));
5358 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(menuitem),
"pnum", LIVES_INT_TO_POINTER(i));
5369 static void apply_avol_filter(lives_mt * mt) {
5373 weed_plant_t *init_event = mt->avol_init_event, *new_end_event;
5374 weed_plant_t *deinit_event;
5375 weed_timecode_t new_tc;
5380 if (mt->opts.back_audio_tracks == 0 && !mt->opts.pertrack_audio)
return;
5384 if (!new_end_event) {
5387 if (mt->opts.aparam_view_list) {
5388 for (list = mt->audio_draws; list; list = list->next) {
5399 LiVESList *slist = lives_list_copy(mt->selected_tracks);
5401 weed_plant_t *old_mt_init = mt->init_event;
5403 double region_start = mt->region_start;
5404 double region_end = mt->region_end;
5406 boolean did_backup = mt->did_backup;
5407 int current_fx = mt->current_fx;
5409 mt->region_start = 0.;
5411 if (mt->selected_tracks) {
5412 lives_list_free(mt->selected_tracks);
5413 mt->selected_tracks = NULL;
5415 if (mt->opts.back_audio_tracks > 0) mt->selected_tracks = lives_list_append(mt->selected_tracks, LIVES_INT_TO_POINTER(-1));
5416 if (mt->opts.pertrack_audio) {
5417 for (i = 0; i < mt->num_video_tracks; i++) {
5418 mt->selected_tracks = lives_list_append(mt->selected_tracks, LIVES_INT_TO_POINTER(i));
5421 mt->current_fx = mt->avol_fx;
5423 mt->did_backup =
TRUE;
5425 mt->did_backup = did_backup;
5426 mt->avol_init_event = mt->init_event;
5428 mt->region_start = region_start;
5429 mt->region_end = region_end;
5430 lives_list_free(mt->selected_tracks);
5431 mt->selected_tracks = lives_list_copy(slist);
5432 if (slist) lives_list_free(slist);
5433 mt->current_fx = current_fx;
5434 mt->init_event = old_mt_init;
5436 if (mt->opts.aparam_view_list) {
5437 for (list = mt->audio_draws; list; list = list->next) {
5450 if (mt->opts.aparam_view_list) {
5451 for (list = mt->audio_draws; list; list = list->next) {
5458 static void set_audio_filter_channel_values(lives_mt * mt) {
5466 weed_plant_t **in_channels, **out_channels;
5468 int num_in, num_out;
5473 if (!mt->current_rfx || mt->current_fx == -1 || mt->current_fx != mt->avol_fx)
return;
5475 inst = (weed_plant_t *)mt->current_rfx->source;
5476 in_channels = weed_get_plantptr_array_counted(inst, WEED_LEAF_IN_CHANNELS, &num_in);
5478 for (i = 0; i < num_in; i++) {
5479 weed_set_int_value(in_channels[i], WEED_LEAF_AUDIO_CHANNELS,
mainw->
files[mt->render_file]->
achans);
5480 weed_set_int_value(in_channels[i], WEED_LEAF_AUDIO_RATE,
mainw->
files[mt->render_file]->
arate);
5484 out_channels = weed_get_plantptr_array_counted(inst, WEED_LEAF_OUT_CHANNELS, &num_out);
5486 for (i = 0; i < num_out; i++) {
5487 weed_set_int_value(out_channels[i], WEED_LEAF_AUDIO_CHANNELS,
mainw->
files[mt->render_file]->
achans);
5488 weed_set_int_value(out_channels[i], WEED_LEAF_AUDIO_RATE,
mainw->
files[mt->render_file]->
arate);
5500 static char *mt_set_vals_string(
void) {
5504 else lives_snprintf(sendian, 128,
"%s",
_(
"signed "));
5510 _(
"Multitrack values set to %.3f fps, frame size %d x %d, audio channels %d, "
5511 "audio rate %d, audio sample size %d, %s.\n"),
5524 if (rwidth * rheight < 64) {
5531 width = (width >> 2) << 2;
5532 height = (height >> 2) << 2;
5534 mt->play_width = width;
5535 mt->play_height = height;
5540 static weed_plant_t *load_event_list_inner(lives_mt * mt,
int fd,
boolean show_errors,
int *num_events,
5541 unsigned char **mem,
unsigned char *mem_end) {
5542 weed_plant_t *event, *eventprev = NULL;
5543 weed_plant_t *event_list;
5552 if (mt) mt->layout_set_properties =
FALSE;
5555 if (show_errors)
d_print(
_(
"invalid event list. Failed.\n"));
5559 if (show_errors && (!weed_plant_has_leaf(event_list, WEED_LEAF_FPS) ||
5560 (fps = weed_get_double_value(event_list, WEED_LEAF_FPS, NULL)) < 1. ||
5562 d_print(
_(
"event list has invalid fps. Failed.\n"));
5567 && weed_plant_has_leaf(event_list, WEED_LEAF_KEEP_ASPECT)) {
5568 boolean letterbox = weed_get_boolean_value(event_list, WEED_LEAF_KEEP_ASPECT, NULL);
5584 _(
"\nThis layout requires the set \"%s\"\nIn order to load it you must return to the Clip Editor, \n"
5585 "close the current set,\nthen load in the new set from the File menu.\n"),
5596 }
else if (mt && !show_errors && !mem)
return NULL;
5607 if (weed_plant_has_leaf(event_list, WEED_LEAF_WIDTH)) {
5608 int width = weed_get_int_value(event_list, WEED_LEAF_WIDTH, NULL);
5611 if (mt) mt->layout_set_properties =
TRUE;
5615 if (weed_plant_has_leaf(event_list, WEED_LEAF_HEIGHT)) {
5616 int height = weed_get_int_value(event_list, WEED_LEAF_HEIGHT, NULL);
5619 if (mt) mt->layout_set_properties =
TRUE;
5623 if (weed_plant_has_leaf(event_list, WEED_LEAF_AUDIO_CHANNELS)) {
5624 int achans = weed_get_int_value(event_list, WEED_LEAF_AUDIO_CHANNELS, NULL);
5625 if (achans >= 0 && mt) {
5628 _(
"\nThis layout has an invalid number of audio channels (%d) for LiVES.\n"
5629 "It cannot be loaded.\n"), achans);
5636 if (mt) mt->layout_set_properties =
TRUE;
5640 if (weed_plant_has_leaf(event_list, WEED_LEAF_AUDIO_RATE)) {
5641 int arate = weed_get_int_value(event_list, WEED_LEAF_AUDIO_RATE, NULL);
5644 if (mt) mt->layout_set_properties =
TRUE;
5650 if (asamps == 8 || asamps == 16) {
5652 if (mt) mt->layout_set_properties =
TRUE;
5662 if (asigned == WEED_TRUE) {
5669 if (mt) mt->layout_set_properties =
TRUE;
5681 if (mt) mt->layout_set_properties =
TRUE;
5687 if (mt) mt->layout_set_properties =
TRUE;
5716 if (mem && *mem >= mem_end)
break;
5725 event_id = (uint64_t)((weed_plant_t *)weed_get_voidptr_value(event,
WEED_LEAF_INIT_EVENT, NULL));
5731 if (eventprev) weed_set_voidptr_value(eventprev,
WEED_LEAF_NEXT, event);
5740 if (num_events)(*num_events)++;
5744 if (!mt)
return event_list;
5752 err = (
_(
"This layout was created using automatic gamma correction.\nFor compatibility, you may wish to"
5753 "enable this feature in Tools -> Preferences -> Effects, whilst editing and rendering the layout."));
5756 err = (
_(
"This layout was created without automatic gamma correction.\nFor compatibility, you may wish to"
5757 "disable this feature in Tools -> Preferences -> Effects, whilst editing and rendering the layout."));
5771 char *retval = NULL;
5781 load_event_list_inner(mt, -1,
TRUE, NULL, NULL, NULL);
5813 retval = mt_set_vals_string();
5820 mt->avol_init_event = NULL;
5821 }
else set_audio_filter_channel_values(mt);
5830 if (mt->undos) lives_list_free(mt->undos);
5832 mt->undo_buffer_used = 0;
5833 mt->undo_offset = 0;
5855 (LiVESCompareFunc)strcmp);
5870 if (mt->event_list) {
5872 mt->event_list = NULL;
5880 LiVESTextIter iter1, iter2;
5885 (LiVESTextMark *)markmap->next->data);
5890 markmap = markmap->next->next;
5948 }
while (resp == 2);
5953 if (resp == LIVES_RESPONSE_CANCEL) {
5960 if (resp == 1 && !exiting) {
5971 }
else if (mt && mt->event_list && (exiting || resp == 1)) {
5974 mt->event_list = NULL;
5987 LiVESList *slist = list;
5990 slist = slist->next;
5992 lives_list_free(list);
5997 lives_mt *mt = (lives_mt *)user_data;
6008 static void set_mt_title(lives_mt * mt) {
6017 static boolean timecode_string_validate(LiVESEntry * entry, lives_mt * mt) {
6022 double tl_range, pos;
6028 array = lives_strsplit(etext,
":", 3);
6031 lives_strfreev(array);
6035 hrs = atoi(array[0]);
6036 mins = atoi(array[1]);
6037 if (mins > 59) mins = 59;
6038 secs = lives_strtod(array[2], NULL);
6040 lives_strfreev(array);
6042 secs = secs + mins * 60. + hrs * 3600.;
6044 if (secs > mt->end_secs) {
6045 tl_range = mt->tl_max - mt->tl_min;
6048 mt->tl_min = secs - tl_range / 2;
6049 mt->tl_max = secs + tl_range / 2;
6051 if (mt->tl_max > mt->end_secs) {
6052 mt->tl_min -= (mt->tl_max - mt->end_secs);
6053 mt->tl_max = mt->end_secs;
6064 if (pos < 0.) pos = 0.;
6066 update_timecodes(mt, pos);
6072 static void cmi_set_inactive(LiVESWidget * widget, livespointer data) {
6073 if (widget == data)
return;
6074 lives_widget_object_freeze_notify(LIVES_WIDGET_OBJECT(widget));
6076 lives_widget_object_thaw_notify(LIVES_WIDGET_OBJECT(widget));
6092 static void mt_set_atrans_effect(LiVESMenuItem * menuitem, livespointer user_data) {
6093 lives_mt *mt = (lives_mt *)user_data;
6098 mt_set_autotrans(LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(menuitem),
"idx")));
6102 static void after_timecode_changed(LiVESWidget * entry, LiVESXEventFocus * dir, livespointer user_data) {
6103 lives_mt *mt = (lives_mt *)user_data;
6106 if (!timecode_string_validate(LIVES_ENTRY(entry), mt)) {
6109 if (pos < 0.) pos = 0.;
6110 update_timecodes(mt, pos);
6115 static char *get_tab_name(uint32_t tab) {
6118 return (
_(
"Clips"));
6120 return (
_(
"In/out"));
6122 return (
_(
"FX stack"));
6130 return (
_(
"Params."));
6134 return lives_strdup(
"");
6138 static void set_child_grad(LiVESWidget * widget, livespointer data) {
6139 char *tmp = (
char *)data;
6142 "background-image", tmp);
6143 if (LIVES_IS_CONTAINER(widget))
6213 #if GTK_CHECK_VERSION(3, 0, 0)
6222 #if GTK_CHECK_VERSION(3, 0, 0)
6230 #if GTK_CHECK_VERSION(3, 0, 0)
6249 "background-image",
"none");
6258 if (mt->hseparator2) {
6264 if (mt->hseparator2) {
6301 if (mt->ins_label) {
6338 && LIVES_IS_BIN(mt->fx_list_scroll) &&
lives_bin_get_child(LIVES_BIN(mt->fx_list_scroll)))
6345 if (mt->context_box && LIVES_IS_WIDGET_OBJECT(mt->context_box)) {
6356 #if GTK_CHECK_VERSION(3, 16, 0)
6362 "background-image", tmp);
6377 if (mt->timeline_eb) {
6380 if (mt->timeline_reg) {
6384 if (mt->timeline_reg) {
6397 #if !GTK_CHECK_VERSION(3, 0, 0)
6427 redraw_all_event_boxes(mt);
6431 static void on_solo_check_toggled(LiVESWidget * widg, livespointer user_data) {
6432 lives_mt *mt = (lives_mt *)user_data;
6437 static void multitrack_clear_marks(LiVESMenuItem * menuitem, livespointer user_data) {
6438 lives_mt *mt = (lives_mt *)user_data;
6439 lives_list_free(mt->tl_marks);
6440 mt->tl_marks = NULL;
6448 lives_mt *
multitrack(weed_plant_t *event_list,
int orig_file,
double fps) {
6449 LiVESWidget *hseparator;
6450 LiVESWidget *menuitem;
6451 LiVESWidget *menuitem2;
6452 LiVESWidget *menuitem_menu;
6453 LiVESWidget *selcopy_menu;
6454 #if LIVES_HAS_IMAGE_MENU_ITEM
6457 LiVESWidget *full_screen;
6459 LiVESWidget *show_mt_keys;
6460 LiVESWidget *view_mt_details;
6461 LiVESWidget *zoom_in;
6462 LiVESWidget *zoom_out;
6463 LiVESWidget *show_messages;
6464 LiVESWidget *scrollbar;
6467 LiVESWidget *ign_ins_sel;
6468 LiVESWidget *recent_submenu;
6469 #ifdef ENABLE_DVD_GRAB
6470 LiVESWidget *vcd_dvd_submenu;
6473 LiVESWidget *device_submenu;
6476 LiVESWidget *open_loc_submenu;
6478 LiVESWidget *submenu;
6479 LiVESWidget *submenu2;
6482 LiVESWidget *submenu_menu;
6483 LiVESWidget *submenu_menuv;
6484 LiVESWidget *submenu_menua;
6485 LiVESWidget *submenu_menuvp = NULL;
6486 LiVESWidget *submenu_menuap = NULL;
6489 LiVESWidget *submenu_menurv;
6490 LiVESWidget *submenu_menura;
6491 LiVESWidget *submenu_menurvp = NULL;
6492 LiVESWidget *submenu_menurap = NULL;
6493 LiVESWidget *submenu_menu2av;
6494 LiVESWidget *submenu_menu2v;
6495 LiVESWidget *submenu_menu2a;
6496 LiVESWidget *submenu_menu3;
6498 LiVESWidget *show_frame_events;
6499 LiVESWidget *ccursor;
6501 LiVESWidget *show_manual;
6502 LiVESWidget *donate;
6503 LiVESWidget *email_author;
6504 LiVESWidget *report_bug;
6505 LiVESWidget *suggest_feature;
6506 LiVESWidget *help_translate;
6509 LiVESWidgetObject *vadjustment;
6510 LiVESAdjustment *spinbutton_adj;
6512 boolean in_menubar =
TRUE;
6514 char *cname, *tname, *msg;
6516 char *pkg, *xpkgv = NULL, *xpkga = NULL;
6517 const char *mtext = NULL;
6524 lives_mt *mt = (lives_mt *)
lives_calloc(1,
sizeof(lives_mt));
6534 mt->frame_pixbuf = NULL;
6536 mt->is_ready =
FALSE;
6537 mt->tl_marks = NULL;
6539 mt->timestring[0] = 0;
6542 mt->auto_back_time = 0;
6544 mt->playing_sel =
FALSE;
6546 mt->in_sensitise =
FALSE;
6552 if (!mt->undo_mem) {
6555 mt->undo_buffer_used = 0;
6557 mt->undo_offset = 0;
6565 mt->preview_layer = -1000000;
6567 mt->solo_inst = NULL;
6569 mt->apply_fx_button = NULL;
6570 mt->resetp_button = NULL;
6574 mt->file_selected = orig_file;
6576 mt->auto_changed = mt->changed =
FALSE;
6578 mt->was_undo_redo =
FALSE;
6580 mt->tl_mouse =
FALSE;
6582 mt->sel_locked =
FALSE;
6584 mt->clip_labels = NULL;
6586 mt->force_load_name = NULL;
6588 mt->dumlabel1 = mt->dumlabel2 = mt->tl_label = mt->timeline = mt->timeline_eb =
6589 mt->timeline_reg = NULL;
6591 mt->tl_surf = mt->tl_ev_surf = mt->tl_reg_surf = NULL;
6593 mt->play_width = mt->play_height = 0;
6598 mt->opts.aparam_view_list = lives_list_copy(
mainw->
multi_opts.aparam_view_list);
6600 mt->opts.move_effects =
TRUE;
6601 mt->opts.fx_auto_preview =
TRUE;
6602 mt->opts.snap_over =
FALSE;
6604 mt->opts.show_audio =
TRUE;
6605 mt->opts.ign_ins_sel =
FALSE;
6606 mt->opts.follow_playback =
TRUE;
6609 mt->opts.autocross_audio =
TRUE;
6610 mt->opts.render_vidp =
TRUE;
6611 mt->opts.render_audp =
TRUE;
6612 mt->opts.normalise_audp =
TRUE;
6613 mt->opts.aparam_view_list = NULL;
6614 mt->opts.hpaned_pos = mt->opts.vpaned_pos = -1;
6615 mt->opts.overlay_timecode =
TRUE;
6616 mt->opts.ptr_time = 0.;
6619 mt->opts.insert_audio =
TRUE;
6622 mt->opts.audio_bleedthru =
FALSE;
6623 mt->opts.gang_audio =
TRUE;
6624 mt->opts.back_audio_tracks = 1;
6626 if (force_pertrack_audio) mt->opts.pertrack_audio =
TRUE;
6627 force_pertrack_audio =
FALSE;
6629 mt->tl_fixed_length = 0.;
6631 mt->video_draws = NULL;
6632 mt->block_selected = NULL;
6633 mt->event_list = event_list;
6639 mt->hotspot_x = mt->hotspot_y = 0;
6640 mt->redraw_block =
FALSE;
6642 mt->region_start = mt->region_end = 0.;
6643 mt->region_updating =
FALSE;
6644 mt->is_rendering =
FALSE;
6645 mt->pr_audio =
FALSE;
6646 mt->selected_tracks = NULL;
6647 mt->mt_frame_preview =
FALSE;
6648 mt->current_rfx = NULL;
6649 mt->current_fx = -1;
6650 mt->putative_block = NULL;
6651 mt->specific_event = NULL;
6653 mt->block_tl_move =
FALSE;
6654 mt->block_node_spin =
FALSE;
6656 mt->is_atrans =
FALSE;
6662 mt->moving_block =
FALSE;
6664 mt->insert_start = mt->insert_end = -1;
6665 mt->insert_avel = 1.;
6667 mt->selected_init_event = mt->init_event = NULL;
6669 mt->auto_reloading =
FALSE;
6670 mt->fm_edit_event = NULL;
6672 mt->nb_label = NULL;
6673 mt->fx_list_box = NULL;
6674 mt->fx_list_scroll = NULL;
6675 mt->fx_list_label = NULL;
6677 mt->moving_fx = NULL;
6682 mt->did_backup =
FALSE;
6683 mt->framedraw = NULL;
6685 mt->audio_draws = NULL;
6686 mt->audio_vols = mt->audio_vols_back = NULL;
6688 mt->ignore_load_vals =
FALSE;
6690 mt->exact_preview = 0;
6692 mt->context_time = -1.;
6693 mt->use_context =
FALSE;
6695 mt->no_expose = mt->no_expose_frame =
TRUE;
6697 mt->is_paused =
FALSE;
6699 mt->pb_start_event = NULL;
6701 mt->aud_track_selected =
FALSE;
6703 mt->has_audio_file =
FALSE;
6705 mt->fx_params_label = NULL;
6708 mt->selected_filter = -1;
6714 mt->no_frame_update =
FALSE;
6720 }
else mt->avol_fx = -1;
6721 mt->avol_init_event = NULL;
6727 mt->user_arate = xarate;
6728 mt->user_achans = xachans;
6729 mt->user_asamps = xasamps;
6730 mt->user_signed_endian = xse;
6731 mt->opts.pertrack_audio = ptaud;
6732 mt->opts.back_audio_tracks = btaud;
6741 if (force_backing_tracks > mt->opts.back_audio_tracks) mt->opts.back_audio_tracks = force_backing_tracks;
6742 force_backing_tracks = 0;
6813 #ifdef ENABLE_DVD_GRAB
6824 LIVES_INT_TO_POINTER(1));
6829 #ifdef ENABLE_DVD_GRAB
6837 LIVES_INT_TO_POINTER(2));
6873 LIVES_KEY_w, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
6906 LIVES_KEY_s, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
6916 LIVES_KEY_d, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
6931 mt->ignore_load_vals);
6943 LIVES_KEY_q, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
6958 LIVES_KEY_u, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
6960 #if LIVES_HAS_IMAGE_MENU_ITEM
6965 if (mt->undo_offset == lives_list_length(mt->undos)) mt_set_undoable(mt,
MT_UNDO_NONE, NULL,
FALSE);
6967 mt_undo *undo = (
mt_undo *)(lives_list_nth_data(mt->undos, lives_list_length(mt->undos) - mt->undo_offset - 1));
6971 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->undo), LIVES_WIDGET_ACTIVATE_SIGNAL,
6979 LIVES_KEY_z, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
6981 #if LIVES_HAS_IMAGE_MENU_ITEM
6988 mt_undo *redo = (
mt_undo *)(lives_list_nth_data(mt->undos, lives_list_length(mt->undos) - mt->undo_offset));
6992 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->redo), LIVES_WIDGET_ACTIVATE_SIGNAL,
7001 LIVES_KEY_e, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
7009 LIVES_KEY_x, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
7016 LIVES_KEY_i, (LiVESXModifierType)0, LIVES_ACCEL_VISIBLE);
7018 LIVES_KEY_i, LIVES_CONTROL_MASK, (LiVESAccelFlags)0);
7025 LIVES_KEY_i, LIVES_CONTROL_MASK,
7026 LIVES_ACCEL_VISIBLE);
7044 LIVES_KEY_j, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
7052 LIVES_KEY_l, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
7064 LIVES_KEY_j, (LIVES_CONTROL_MASK | LIVES_SHIFT_MASK),
7065 LIVES_ACCEL_VISIBLE);
7073 LIVES_KEY_l, (LIVES_CONTROL_MASK | LIVES_SHIFT_MASK),
7074 LIVES_ACCEL_VISIBLE);
7095 LIVES_KEY_p, (LiVESXModifierType)0, LIVES_ACCEL_VISIBLE);
7100 #if LIVES_HAS_IMAGE_MENU_ITEM
7107 LIVES_KEY_y, (LiVESXModifierType)0, LIVES_ACCEL_VISIBLE);
7115 LIVES_KEY_q, (LiVESXModifierType)0, LIVES_ACCEL_VISIBLE);
7117 #if LIVES_HAS_IMAGE_MENU_ITEM
7125 #if LIVES_HAS_IMAGE_MENU_ITEM
7133 LIVES_KEY_w, (LiVESXModifierType)0, LIVES_ACCEL_VISIBLE);
7141 LIVES_KEY_f, (LiVESXModifierType)0, LIVES_ACCEL_VISIBLE);
7147 LIVES_KEY_s, (LiVESXModifierType)0, LIVES_ACCEL_VISIBLE);
7153 LIVES_KEY_o, (LiVESXModifierType)0, LIVES_ACCEL_VISIBLE);
7159 LIVES_KEY_z, (LiVESXModifierType)0, LIVES_ACCEL_VISIBLE);
7172 lives_signal_connect_after(LIVES_GUI_OBJECT(mt->move_fx), LIVES_WIDGET_TOGGLED_SIGNAL,
7173 LIVES_GUI_CALLBACK(on_move_fx_changed),
7185 mt->opts.autocross_audio);
7302 for (i = 0; i < num_filters; i++) {
7306 LiVESWidget *menuitem;
7307 char *fxname = NULL;
7316 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(menuitem),
"idx", LIVES_INT_TO_POINTER(sorted));
7325 if (!xpkgv || strcmp(pkg, xpkgv)) {
7346 submenu = submenu_menuvp;
7347 submenu2 = submenu_menurvp;
7349 xpkgv = lives_strdup(pkg);
7351 submenu = submenu_menuv;
7352 submenu2 = submenu_menurv;
7357 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(menuitem),
"idx", LIVES_INT_TO_POINTER(sorted));
7364 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(menuitem),
"idx", LIVES_INT_TO_POINTER(sorted));
7370 if (!xpkga || strcmp(pkg, xpkga)) {
7391 submenu = submenu_menuap;
7392 submenu2 = submenu_menurap;
7394 xpkga = lives_strdup(pkg);
7396 submenu = submenu_menua;
7397 submenu2 = submenu_menura;
7402 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(menuitem),
"idx", LIVES_INT_TO_POINTER(sorted));
7408 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(menuitem),
"idx", LIVES_INT_TO_POINTER(sorted));
7416 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(menuitem),
"idx", LIVES_INT_TO_POINTER(sorted));
7422 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(menuitem2),
"idx", LIVES_INT_TO_POINTER(sorted));
7424 lives_signal_sync_connect(LIVES_GUI_OBJECT(menuitem2), LIVES_WIDGET_ACTIVATE_SIGNAL,
7425 LIVES_GUI_CALLBACK(mt_set_atrans_effect), (livespointer)mt);
7449 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(menuitem2),
"idx", LIVES_INT_TO_POINTER(-1));
7452 lives_signal_sync_connect(LIVES_GUI_OBJECT(menuitem2), LIVES_WIDGET_ACTIVATE_SIGNAL,
7453 LIVES_GUI_CALLBACK(mt_set_atrans_effect),
7475 LIVES_KEY_b, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
7483 LIVES_KEY_t, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
7489 LIVES_KEY_t, (LiVESXModifierType)(LIVES_CONTROL_MASK | LIVES_SHIFT_MASK),
7490 LIVES_ACCEL_VISIBLE);
7501 LIVES_KEY_s, (LiVESXModifierType)LIVES_CONTROL_MASK,
7502 LIVES_ACCEL_VISIBLE);
7533 LIVES_GUI_CALLBACK(
remove_gaps), (livespointer)mt);
7536 LIVES_KEY_g, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
7545 LIVES_KEY_f, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
7558 lives_signal_sync_connect(LIVES_GUI_OBJECT(menuitem), LIVES_WIDGET_ACTIVATE_SIGNAL,
7565 LIVES_KEY_Space, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
7571 LIVES_GUI_CALLBACK(select_all_vid), (livespointer)mt);
7577 LIVES_GUI_CALLBACK(select_no_vid), (livespointer)mt);
7583 LIVES_GUI_CALLBACK(select_all_time), (livespointer)mt);
7586 LIVES_KEY_a, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
7592 LIVES_GUI_CALLBACK(select_from_zero_time), (livespointer)mt);
7598 LIVES_GUI_CALLBACK(select_to_end_time), (livespointer)mt);
7610 LIVES_GUI_CALLBACK(tc_to_rs), (livespointer)mt);
7616 LIVES_GUI_CALLBACK(tc_to_re), (livespointer)mt);
7622 LIVES_GUI_CALLBACK(rs_to_tc), (livespointer)mt);
7628 LIVES_GUI_CALLBACK(re_to_tc), (livespointer)mt);
7639 LIVES_GUI_CALLBACK(mt_selblock), (livespointer)mt);
7642 LIVES_KEY_Return, LIVES_CONTROL_MASK,
7643 LIVES_ACCEL_VISIBLE);
7683 LIVES_GUI_CALLBACK(on_mt_backup_activate), (livespointer)mt);
7690 LIVES_KEY_p, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
7692 #if LIVES_HAS_IMAGE_MENU_ITEM
7697 lives_signal_sync_connect(LIVES_GUI_OBJECT(menuitem), LIVES_WIDGET_ACTIVATE_SIGNAL,
7713 LIVES_KEY_r, LIVES_CONTROL_MASK,
7714 LIVES_ACCEL_VISIBLE);
7755 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->show_info), LIVES_WIDGET_ACTIVATE_SIGNAL,
7765 LIVES_KEY_c, (LiVESXModifierType)0, LIVES_ACCEL_VISIBLE);
7771 LIVES_KEY_n, (LiVESXModifierType)0, LIVES_ACCEL_VISIBLE);
7779 LIVES_KEY_e, (LiVESXModifierType)0, LIVES_ACCEL_VISIBLE);
7812 LIVES_KEY_c, (LiVESXModifierType)LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
7818 LIVES_KEY_Plus, (LiVESXModifierType)LIVES_CONTROL_MASK,
7819 LIVES_ACCEL_VISIBLE);
7822 LIVES_KEY_Equal, (LiVESXModifierType)LIVES_CONTROL_MASK,
7823 (LiVESAccelFlags)0);
7829 LIVES_KEY_Minus, (LiVESXModifierType)LIVES_CONTROL_MASK,
7830 LIVES_ACCEL_VISIBLE);
7893 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->show_devopts), LIVES_WIDGET_ACTIVATE_SIGNAL,
7909 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->quit), LIVES_WIDGET_ACTIVATE_SIGNAL,
7911 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->load_vals), LIVES_WIDGET_ACTIVATE_SIGNAL,
7913 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->ac_audio_check), LIVES_WIDGET_ACTIVATE_SIGNAL,
7914 LIVES_GUI_CALLBACK(mt_ac_audio_toggled), (livespointer)mt);
7915 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->aload_subs), LIVES_WIDGET_ACTIVATE_SIGNAL,
7917 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->clipedit), LIVES_WIDGET_ACTIVATE_SIGNAL,
7929 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->view_events), LIVES_WIDGET_ACTIVATE_SIGNAL,
7931 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->view_sel_events), LIVES_WIDGET_ACTIVATE_SIGNAL,
7933 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->clear_marks), LIVES_WIDGET_ACTIVATE_SIGNAL,
7934 LIVES_GUI_CALLBACK(multitrack_clear_marks), (livespointer)mt);
7935 lives_signal_sync_connect(LIVES_GUI_OBJECT(view_mt_details), LIVES_WIDGET_ACTIVATE_SIGNAL,
7937 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->show_layout_errors), LIVES_WIDGET_ACTIVATE_SIGNAL,
7943 lives_signal_sync_connect(LIVES_GUI_OBJECT(show_messages), LIVES_WIDGET_ACTIVATE_SIGNAL,
7947 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->stop), LIVES_WIDGET_ACTIVATE_SIGNAL,
7949 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->rewind), LIVES_WIDGET_ACTIVATE_SIGNAL,
7951 mt->sepwin_func = lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->sepwin), LIVES_WIDGET_ACTIVATE_SIGNAL,
7953 lives_signal_sync_connect(LIVES_GUI_OBJECT(full_screen), LIVES_WIDGET_ACTIVATE_SIGNAL,
7955 mt->loop_cont_func = lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->loop_continue), LIVES_WIDGET_ACTIVATE_SIGNAL,
7957 mt->mute_audio_func = lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->mute_audio), LIVES_WIDGET_ACTIVATE_SIGNAL,
7959 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->rename_track), LIVES_WIDGET_ACTIVATE_SIGNAL,
7967 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->render), LIVES_WIDGET_ACTIVATE_SIGNAL,
7971 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->jumpback), LIVES_WIDGET_ACTIVATE_SIGNAL,
7973 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->jumpnext), LIVES_WIDGET_ACTIVATE_SIGNAL,
7975 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->mark_jumpback), LIVES_WIDGET_ACTIVATE_SIGNAL,
7977 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->mark_jumpnext), LIVES_WIDGET_ACTIVATE_SIGNAL,
7980 LIVES_GUI_CALLBACK(on_delblock_activate), (livespointer)mt);
7981 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->save_event_list), LIVES_WIDGET_ACTIVATE_SIGNAL,
7983 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->load_event_list), LIVES_WIDGET_ACTIVATE_SIGNAL,
7985 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->clear_event_list), LIVES_WIDGET_ACTIVATE_SIGNAL,
7987 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->view_audio), LIVES_WIDGET_ACTIVATE_SIGNAL,
7988 LIVES_GUI_CALLBACK(mt_view_audio_toggled), (livespointer)mt);
7989 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->change_max_disp), LIVES_WIDGET_ACTIVATE_SIGNAL,
7991 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->render_vid), LIVES_WIDGET_ACTIVATE_SIGNAL,
7992 LIVES_GUI_CALLBACK(mt_render_vid_toggled), (livespointer)mt);
7993 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->render_aud), LIVES_WIDGET_ACTIVATE_SIGNAL,
7994 LIVES_GUI_CALLBACK(mt_render_aud_toggled), (livespointer)mt);
7995 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->normalise_aud), LIVES_WIDGET_ACTIVATE_SIGNAL,
7996 LIVES_GUI_CALLBACK(mt_norm_aud_toggled), (livespointer)mt);
7997 lives_signal_sync_connect(LIVES_GUI_OBJECT(ign_ins_sel), LIVES_WIDGET_ACTIVATE_SIGNAL,
7998 LIVES_GUI_CALLBACK(mt_ign_ins_sel_toggled), (livespointer)mt);
7999 lives_signal_sync_connect(LIVES_GUI_OBJECT(show_frame_events), LIVES_WIDGET_ACTIVATE_SIGNAL,
8001 lives_signal_sync_connect(LIVES_GUI_OBJECT(ccursor), LIVES_WIDGET_ACTIVATE_SIGNAL,
8003 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->follow_play), LIVES_WIDGET_ACTIVATE_SIGNAL,
8004 LIVES_GUI_CALLBACK(mt_fplay_toggled), (livespointer)mt);
8006 LIVES_GUI_CALLBACK(
mt_zoom_in), (livespointer)mt);
8008 LIVES_GUI_CALLBACK(
mt_zoom_out), (livespointer)mt);
8009 mt->seltrack_func = lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->select_track), LIVES_WIDGET_ACTIVATE_SIGNAL,
8012 lives_signal_sync_connect(LIVES_GUI_OBJECT(show_manual), LIVES_WIDGET_ACTIVATE_SIGNAL,
8015 lives_signal_sync_connect(LIVES_GUI_OBJECT(email_author), LIVES_WIDGET_ACTIVATE_SIGNAL,
8018 lives_signal_sync_connect(LIVES_GUI_OBJECT(donate), LIVES_WIDGET_ACTIVATE_SIGNAL,
8021 lives_signal_sync_connect(LIVES_GUI_OBJECT(report_bug), LIVES_WIDGET_ACTIVATE_SIGNAL,
8024 lives_signal_sync_connect(LIVES_GUI_OBJECT(suggest_feature), LIVES_WIDGET_ACTIVATE_SIGNAL,
8027 lives_signal_sync_connect(LIVES_GUI_OBJECT(help_translate), LIVES_WIDGET_ACTIVATE_SIGNAL,
8030 lives_signal_sync_connect(LIVES_GUI_OBJECT(about), LIVES_WIDGET_ACTIVATE_SIGNAL,
8036 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->expl_missing), LIVES_WIDGET_ACTIVATE_SIGNAL,
8039 lives_signal_sync_connect(LIVES_GUI_OBJECT(show_mt_keys), LIVES_WIDGET_ACTIVATE_SIGNAL,
8041 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->fx_delete), LIVES_WIDGET_ACTIVATE_SIGNAL,
8049 lives_cclosure_new(LIVES_GUI_CALLBACK(
mt_mark_callback), (livespointer)mt, NULL));
8058 | LIVES_BUTTON_PRESS_MASK | LIVES_SCROLL_MASK | LIVES_SMOOTH_SCROLL_MASK);
8060 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->top_eventbox), LIVES_WIDGET_SCROLL_EVENT,
8118 #if GTK_CHECK_VERSION(3, 16, 0)
8120 set_css_value_direct(LIVES_WIDGET(mt->timecode), LIVES_WIDGET_STATE_NORMAL,
"",
"border-top-left-radius",
"20px");
8121 set_css_value_direct(LIVES_WIDGET(mt->timecode), LIVES_WIDGET_STATE_NORMAL,
"",
"border-top-right-radius",
"20px");
8122 set_css_value_direct(LIVES_WIDGET(mt->timecode), LIVES_WIDGET_STATE_NORMAL,
"",
"border-bottom-right-radius",
"20px");
8123 set_css_value_direct(LIVES_WIDGET(mt->timecode), LIVES_WIDGET_STATE_NORMAL,
"",
"border-bottom-left-radius",
"20px");
8127 update_timecodes(mt, 0.);
8132 mt->tc_func = lives_signal_sync_connect_after(LIVES_WIDGET_OBJECT(mt->timecode), LIVES_WIDGET_FOCUS_OUT_EVENT,
8133 LIVES_GUI_CALLBACK(after_timecode_changed), (livespointer) mt);
8142 (tmp2 = (
_(
"Select whether video clips are inserted and moved with their audio or not"))),
8143 &mt->opts.insert_audio);
8159 (tmp2 = (
_(
"Select whether timeline selection snaps to overlap between selected tracks or not"))),
8160 &mt->opts.snap_over);
8215 mt->grav_normal_func = lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->grav_normal), LIVES_WIDGET_TOGGLED_SIGNAL,
8216 LIVES_GUI_CALLBACK(on_grav_mode_changed), (livespointer)mt);
8221 mt->grav_left_func = lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->grav_left), LIVES_WIDGET_TOGGLED_SIGNAL,
8222 LIVES_GUI_CALLBACK(on_grav_mode_changed), (livespointer)mt);
8227 mt->grav_right_func = lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->grav_right), LIVES_WIDGET_TOGGLED_SIGNAL,
8228 LIVES_GUI_CALLBACK(on_grav_mode_changed), (livespointer)mt);
8236 mt->mm_label = NULL;
8255 mt->mm_move_func = lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->mm_move), LIVES_WIDGET_TOGGLED_SIGNAL,
8256 LIVES_GUI_CALLBACK(on_mouse_mode_changed), (livespointer)mt);
8262 mt->mm_select_func = lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->mm_select), LIVES_WIDGET_TOGGLED_SIGNAL,
8263 LIVES_GUI_CALLBACK(on_mouse_mode_changed), (livespointer)mt);
8273 mt->ins_label = NULL;
8288 mt->ins_normal_func = lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->ins_normal), LIVES_WIDGET_TOGGLED_SIGNAL,
8289 LIVES_GUI_CALLBACK(on_insert_mode_changed),
8296 }
else mt->sep4 = NULL;
8312 LIVES_ORIENTATION_HORIZONTAL)) {
8342 mt->fd_frame = mt->preview_frame;
8345 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(mt->preview_eventbox), LIVES_WIDGET_CONFIGURE_EVENT,
8363 | LIVES_BUTTON_PRESS_MASK | LIVES_ENTER_NOTIFY_MASK | LIVES_SMOOTH_SCROLL_MASK | LIVES_SCROLL_MASK);
8365 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->preview_eventbox), LIVES_WIDGET_MOTION_NOTIFY_EVENT,
8367 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->preview_eventbox), LIVES_WIDGET_BUTTON_RELEASE_EVENT,
8369 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->preview_eventbox), LIVES_WIDGET_BUTTON_PRESS_EVENT,
8371 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->preview_eventbox), LIVES_WIDGET_ENTER_EVENT,
8373 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->preview_eventbox), LIVES_WIDGET_LEAVE_NOTIFY_EVENT,
8375 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->preview_eventbox), LIVES_WIDGET_SCROLL_EVENT,
8415 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->clip_scroll), LIVES_WIDGET_SCROLL_EVENT, LIVES_GUI_CALLBACK(
on_mouse_scroll),
8496 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->apply_fx_button), LIVES_WIDGET_CLICKED_SIGNAL,
8499 mt->node_adj = (LiVESWidgetObject *)
lives_adjustment_new(0., 0., 0., 1. / mt->fps, 10. / mt->fps, 0.);
8504 3, LIVES_BOX(hbox), NULL);
8508 lives_signal_connect_after(LIVES_GUI_OBJECT(mt->node_spinbutton), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
8520 (tmp = (
_(
"Preview only the selected effect"))));
8523 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(mt->solo_check), LIVES_WIDGET_TOGGLED_SIGNAL,
8524 LIVES_GUI_CALLBACK(on_solo_check_toggled), (livespointer)mt);
8530 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->resetp_button), LIVES_WIDGET_CLICKED_SIGNAL,
8537 -1, LIVES_BOX(hbox),
TRUE, NULL);
8542 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->del_node_button), LIVES_WIDGET_CLICKED_SIGNAL,
8547 -1, LIVES_BOX(hbox),
TRUE, NULL);
8552 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->next_node_button), LIVES_WIDGET_CLICKED_SIGNAL,
8557 -1, LIVES_BOX(hbox),
TRUE, NULL);
8563 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->prev_node_button), LIVES_WIDGET_CLICKED_SIGNAL,
8632 mt->check_avel_rev_func = lives_signal_connect_after(LIVES_GUI_OBJECT(mt->checkbutton_avel_reverse),
8639 LIVES_BOX(hbox), NULL);
8641 mt->spin_avel_func = lives_signal_connect_after(LIVES_GUI_OBJECT(mt->spinbutton_avel), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
8666 LIVES_GUI_CALLBACK(in_out_ebox_pressed), (livespointer)mt);
8668 LIVES_GUI_CALLBACK(on_drag_clip_end), (livespointer)mt);
8681 LIVES_BOX(mt->in_hbox), NULL);
8685 LIVES_BOX(mt->in_hbox),
8686 (tmp2 = (
_(
"Anchor the start point to the timeline"))));
8692 mt->spin_in_func = lives_signal_connect_after(LIVES_GUI_OBJECT(mt->spinbutton_in), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
8695 mt->check_start_func = lives_signal_connect_after(LIVES_GUI_OBJECT(mt->checkbutton_start_anchored),
8711 LIVES_GUI_CALLBACK(in_out_ebox_pressed), (livespointer)mt);
8713 LIVES_GUI_CALLBACK(on_drag_clip_end), (livespointer)mt);
8721 LIVES_BOX(mt->out_hbox), NULL);
8725 LIVES_BOX(mt->out_hbox),
8726 (tmp2 = (
_(
"Anchor the end point to the timeline"))));
8733 mt->spin_out_func = lives_signal_sync_connect_after(LIVES_GUI_OBJECT(mt->spinbutton_out), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
8736 mt->check_end_func = lives_signal_sync_connect_after(LIVES_GUI_OBJECT(mt->checkbutton_end_anchored),
8743 LIVES_GUI_CALLBACK(notebook_page), (livespointer)mt);
8753 mt->context_scroll = NULL;
8763 mt->sep_image = NULL;
8764 mt->hseparator2 = NULL;
8797 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->tlx_eventbox), LIVES_WIDGET_BUTTON_PRESS_EVENT,
8800 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->tlx_eventbox), LIVES_WIDGET_BUTTON_RELEASE_EVENT,
8804 | LIVES_BUTTON_PRESS_MASK);
8805 mt->mouse_mot1 = lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->tlx_eventbox), LIVES_WIDGET_MOTION_NOTIFY_EVENT,
8818 #if GTK_CHECK_VERSION(3, 8, 0)
8819 gtk_widget_set_opacity(scrollbar, 0.);
8830 lives_signal_connect_after(LIVES_GUI_OBJECT(mt->scrollbar), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
8836 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->tl_eventbox), LIVES_WIDGET_BUTTON_PRESS_EVENT,
8843 | LIVES_BUTTON_PRESS_MASK | LIVES_SCROLL_MASK | LIVES_SMOOTH_SCROLL_MASK);
8844 mt->mouse_mot2 =
lives_signal_connect(LIVES_GUI_OBJECT(mt->tl_eventbox), LIVES_WIDGET_MOTION_NOTIFY_EVENT,
8850 LIVES_GUI_CALLBACK(on_mt_timeline_scroll), (livespointer)mt);
8869 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->time_scrollbar), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
8870 LIVES_GUI_CALLBACK(scroll_time_by_scrollbar), (livespointer)mt);
8872 mt->num_video_tracks = 0;
8874 mt->timeline_table = NULL;
8875 mt->timeline_eb = NULL;
8879 mt->auto_reloading =
TRUE;
8882 mt->auto_reloading =
FALSE;
8884 if (mt->event_list) {
8922 lives_signal_connect_after(LIVES_GUI_OBJECT(mt->msg_adj),
8923 LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
8925 (livespointer)mt->msg_area);
8929 (livespointer)mt->msg_adj);
8933 mt->msg_area = mt->msg_scrollbar = NULL;
8939 lives_accel_group_connect(LIVES_ACCEL_GROUP(mt->accel_group), LIVES_KEY_Page_Up, LIVES_CONTROL_MASK, (LiVESAccelFlags)0,
8940 lives_cclosure_new(LIVES_GUI_CALLBACK(
mt_prevclip), mt, NULL));
8941 lives_accel_group_connect(LIVES_ACCEL_GROUP(mt->accel_group), LIVES_KEY_Page_Down, LIVES_CONTROL_MASK, (LiVESAccelFlags)0,
8942 lives_cclosure_new(LIVES_GUI_CALLBACK(
mt_nextclip), mt, NULL));
8945 lives_cclosure_new(LIVES_GUI_CALLBACK(
mt_tlback), mt, NULL));
8947 lives_cclosure_new(LIVES_GUI_CALLBACK(
mt_tlfor), mt, NULL));
8952 lives_cclosure_new(LIVES_GUI_CALLBACK(
mt_tlfor_frame), mt, NULL));
8955 lives_cclosure_new(LIVES_GUI_CALLBACK(
mt_trup), mt, NULL));
8957 lives_cclosure_new(LIVES_GUI_CALLBACK(
mt_trdown), mt, NULL));
8962 if (mt->opts.mouse_mode ==
MOUSE_MODE_MOVE) on_mouse_mode_changed(LIVES_MENU_ITEM(mt->mm_move), (livespointer)mt);
8963 else if (mt->opts.mouse_mode ==
MOUSE_MODE_SELECT) on_mouse_mode_changed(LIVES_MENU_ITEM(mt->mm_select), (livespointer)mt);
8965 if (mt->opts.insert_mode ==
INSERT_MODE_NORMAL) on_insert_mode_changed(LIVES_MENU_ITEM(mt->ins_normal), (livespointer)mt);
8967 if (mt->opts.grav_mode ==
GRAV_MODE_NORMAL) on_grav_mode_changed(LIVES_MENU_ITEM(mt->grav_normal), (livespointer)mt);
8968 else if (mt->opts.grav_mode ==
GRAV_MODE_LEFT) on_grav_mode_changed(LIVES_MENU_ITEM(mt->grav_left), (livespointer)mt);
8969 else if (mt->opts.grav_mode ==
GRAV_MODE_RIGHT) on_grav_mode_changed(LIVES_MENU_ITEM(mt->grav_right), (livespointer)mt);
8978 mt->is_ready =
TRUE;
8997 track_rect *block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks"), *blocknext;
8999 LiVESWidget *label, *labelbox, *arrow, *ahbox, *xeventbox;
9000 lives_painter_surface_t *bgimg;
9003 blocknext = block->next;
9004 if (mt->block_selected == block) mt->block_selected = NULL;
9009 if ((bgimg = (lives_painter_surface_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"bgimg")) != NULL) {
9013 label = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"label");
9014 arrow = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"arrow");
9017 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
HIDDEN_KEY)) == 0) {
9018 labelbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"labelbox");
9019 ahbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"ahbox");
9024 xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"achan0");
9026 label = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"label");
9028 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
HIDDEN_KEY)) == 0) {
9029 labelbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"labelbox");
9032 if ((bgimg = (lives_painter_surface_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"bgimg")) != NULL) {
9039 xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"achan1");
9041 label = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"label");
9043 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
HIDDEN_KEY)) == 0) {
9044 labelbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"labelbox");
9047 if ((bgimg = (lives_painter_surface_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"bgimg")) != NULL) {
9055 lives_free(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"track_name"));
9060 static int *update_layout_map(weed_plant_t *event_list) {
9064 weed_plant_t *event;
9068 for (i = 1; i <=
MAX_FILES; i++) used_clips[i] = 0;
9070 if (!event_list)
return used_clips;
9077 int *clip_index = weed_get_int_array_counted(event,
WEED_LEAF_CLIPS, &numtracks);
9078 if (numtracks > 0) {
9079 int64_t *frame_index = weed_get_int64_array(event,
WEED_LEAF_FRAMES, NULL);
9080 for (
int i = 0; i < numtracks; i++) {
9081 if (clip_index[i] > 0 && (frame_index[i] > used_clips[clip_index[i]])) used_clips[clip_index[i]] = (int)frame_index[i];
9093 static double *update_layout_map_audio(weed_plant_t *event_list) {
9097 weed_plant_t *event;
9117 if (!event_list)
return used_clips;
9122 avel[i] = neg_avel[i] = 0.;
9130 double *aseek_index;
9133 for (i = 0; i < numatracks; i += 2) {
9134 if (aclip_index[i + 1] > 0) {
9135 atrack = aclip_index[i];
9141 if (avel[atrack] != 0.) {
9143 last_aclip = last_aclips[atrack];
9144 if (aval > used_clips[last_aclip]) used_clips[last_aclip] = aval;
9146 aseek[atrack] = aseek_index[i];
9147 avel[atrack] = aseek_index[i + 1];
9149 last_aclips[atrack] = aclip_index[i + 1];
9156 if (neg_avel[atrack] != 0.) {
9158 last_aclip = neg_last_aclips[atrack];
9159 if (aval > used_clips[last_aclip]) used_clips[last_aclip] = aval;
9161 neg_aseek[atrack] = aseek_index[i];
9162 neg_avel[atrack] = aseek_index[i + 1];
9163 neg_atc[atrack] = tc;
9164 neg_last_aclips[atrack] = aclip_index[i + 1];
9183 double *layout_map_audio;
9184 boolean retval =
FALSE;
9190 if (mt && mt->event_list) {
9191 layout_map = update_layout_map(mt->event_list);
9192 layout_map_audio = update_layout_map_audio(mt->event_list);
9194 if (
layout_map[file] > 0 || layout_map_audio[file] > 0.) retval =
TRUE;
9207 double *layout_map_audio = NULL;
9209 boolean needs_idlefunc =
FALSE;
9210 boolean did_backup = mt->did_backup;
9216 if (mt->idlefunc > 0) {
9217 needs_idlefunc =
TRUE;
9222 if (mt->frame_pixbuf && mt->frame_pixbuf !=
mainw->
imframe) {
9224 mt->frame_pixbuf = NULL;
9229 int file_selected = mt->file_selected;
9231 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
9234 mt->file_selected = file_selected;
9237 if (mt->event_list) {
9251 mt->event_list = NULL;
9260 mt->undo_mem = NULL;
9268 if (
mainw->
files[i] && (
layout_map[i] != 0 || (layout_map_audio && layout_map_audio[i] != 0.))) {
9270 if (layout_map_audio)
9286 mt->no_expose = mt->no_expose_frame =
TRUE;
9287 mt->is_ready =
FALSE;
9290 mainw->
multi_opts.aparam_view_list = lives_list_copy(mt->opts.aparam_view_list);
9302 if (mt->undos) lives_list_free(mt->undos);
9304 if (mt->selected_tracks) lives_list_free(mt->selected_tracks);
9308 mt->event_list = NULL;
9313 if (mt->clip_labels) lives_list_free(mt->clip_labels);
9374 LIVES_ORIENTATION_HORIZONTAL)) {
9394 if (mt->mt_frame_preview) {
9416 if (mt->audio_vols) lives_list_free(mt->audio_vols);
9424 if (mt->video_draws) {
9425 for (i = 0; i < mt->num_video_tracks; i++) {
9428 lives_list_free(mt->video_draws);
9435 lives_list_free(mt->tl_marks);
9502 if (mt->file_selected != -1) {
9536 d_print(
_(
"====== Switched to Clip Edit mode ======\n"));
9544 static void locate_avol_init_event(lives_mt * mt, weed_plant_t *event_list,
int avol_fx) {
9556 mt->avol_init_event = event;
9566 static track_rect *add_block_start_point(LiVESWidget * eventbox, weed_timecode_t tc,
int filenum,
9567 weed_timecode_t offset_start, weed_plant_t *event,
boolean ordered) {
9577 track_rect *block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks");
9578 track_rect *new_block;
9581 if (block->start_event == event)
return NULL;
9582 if (!block->next)
break;
9585 new_block = (track_rect *)
lives_malloc(
sizeof(track_rect));
9588 new_block->next = new_block->prev = NULL;
9590 new_block->start_anchored = new_block->end_anchored =
FALSE;
9591 new_block->start_event = event;
9592 new_block->ordered = ordered;
9593 new_block->eventbox = eventbox;
9594 new_block->offset_start = offset_start;
9596 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"block_last", (livespointer)new_block);
9602 block->prev->next = new_block;
9603 new_block->prev = block->prev;
9606 else lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks", (livespointer)new_block);
9607 new_block->next = block;
9608 block->prev = new_block;
9611 block->next = new_block;
9612 new_block->prev = block;
9617 if (!block) lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks", (livespointer)new_block);
9623 static track_rect *add_block_end_point(LiVESWidget * eventbox, weed_plant_t *event) {
9625 track_rect *block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"block_last");
9626 if (block) block->end_event = event;
9630 static boolean on_tlreg_enter(LiVESWidget * widget, LiVESXEventCrossing * event, livespointer user_data) {
9631 lives_mt *mt = (lives_mt *)user_data;
9638 static boolean on_tleb_enter(LiVESWidget * widget, LiVESXEventCrossing * event, livespointer user_data) {
9639 lives_mt *mt = (lives_mt *)user_data;
9649 renumbered_clips[i] = i;
9650 }
else renumbered_clips[i] = 0;
9655 static void set_track_labels(lives_mt * mt) {
9665 if (nlabs < navs) navs = nlabs;
9667 for (i = 0; i < navs; i++) {
9669 if (nt < mt->num_video_tracks) {
9682 mt->avol_init_event = NULL;
9684 tlist = mt->audio_draws;
9686 while (mt->audio_draws) {
9688 mt->audio_draws = mt->audio_draws->next;
9691 lives_list_free(tlist);
9693 tlist = mt->video_draws;
9695 while (mt->video_draws) {
9697 mt->video_draws->data = NULL;
9698 mt->video_draws = mt->video_draws->next;
9701 lives_list_free(tlist);
9702 mt->num_video_tracks = 0;
9704 mt->tl_label = NULL;
9706 #ifndef ENABLE_GIW_3
9707 if (!mt->timeline_table) {
9710 LIVES_FILL, (LiVESAttachOptions)0, 0, 0);
9714 mt->current_track = 0;
9719 if (
mainw->
files[mt->render_file]->
achans > 0 && mt->opts.back_audio_tracks > 0) {
9728 mt->current_track = 0;
9729 mt->block_selected = NULL;
9731 if (!mt->timeline_eb) {
9733 mt->timeline = giw_timeline_new_with_adjustment(LIVES_ORIENTATION_HORIZONTAL, 0., 0., 1000000., 1000000.);
9734 giw_timeline_set_unit(GIW_TIMELINE(mt->timeline), GIW_TIME_UNIT_SMH);
9735 giw_timeline_set_mouse_policy(GIW_TIMELINE(mt->timeline), GIW_TIMELINE_MOUSE_DISABLED);
9745 LIVES_BUTTON_RELEASE_MASK | LIVES_BUTTON_PRESS_MASK | LIVES_ENTER_NOTIFY_MASK);
9748 LIVES_BUTTON_RELEASE_MASK | LIVES_BUTTON_PRESS_MASK | LIVES_ENTER_NOTIFY_MASK);
9749 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->timeline_eb), LIVES_WIDGET_ENTER_EVENT, LIVES_GUI_CALLBACK(on_tleb_enter),
9751 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->timeline_reg), LIVES_WIDGET_ENTER_EVENT, LIVES_GUI_CALLBACK(on_tlreg_enter),
9754 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->timeline), LIVES_WIDGET_MOTION_NOTIFY_EVENT,
9755 LIVES_GUI_CALLBACK(return_true), NULL);
9781 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->timeline_reg), LIVES_WIDGET_EXPOSE_EVENT,
9782 LIVES_GUI_CALLBACK(expose_timeline_reg_event), (livespointer)mt);
9788 lives_table_attach(LIVES_TABLE(mt->timeline_table_header), mt->dumlabel1, 0, 7, 0, 1,
9789 (LiVESAttachOptions)(LIVES_EXPAND | LIVES_FILL),
9790 (LiVESAttachOptions)(LIVES_FILL), 0, 0);
9793 (LiVESAttachOptions)(LIVES_EXPAND | LIVES_FILL),
9794 (LiVESAttachOptions)(LIVES_FILL), 0, 0);
9798 lives_table_attach(LIVES_TABLE(mt->timeline_table_header), mt->dumlabel2, 0, 7, 1, 2,
9799 (LiVESAttachOptions)(LIVES_EXPAND | LIVES_FILL),
9800 (LiVESAttachOptions)(LIVES_FILL), 0, 0);
9803 (LiVESAttachOptions)(LIVES_EXPAND | LIVES_FILL),
9804 (LiVESAttachOptions)(LIVES_FILL), 0, 0);
9807 if (mt->event_list) {
9808 LiVESWidget *audio_draw;
9811 weed_plant_t *event, *last_event = NULL, *next_frame_event;
9812 weed_timecode_t tc, last_tc;
9813 weed_timecode_t offset_start;
9814 weed_timecode_t block_marker_tc = -1;
9815 weed_timecode_t block_marker_uo_tc = -1;
9818 int64_t *frame_index, *new_frame_index;
9819 int *clip_index, *new_clip_index;
9820 int *block_marker_uo_tracks = NULL;
9821 int *aclips, *navals;
9822 int *block_marker_tracks = NULL;
9825 boolean forced_end =
FALSE;
9826 boolean ordered =
TRUE;
9827 boolean shown_audio_warn =
FALSE;
9829 int block_marker_uo_num_tracks = 0;
9832 int last_valid_frame;
9833 int block_marker_num_tracks = 0;
9834 int last_tracks = 1;
9847 maxval = mt->num_video_tracks - 1;
9849 for (j = 0; j < navs; j++) {
9850 if (navals[j] > maxval) maxval = navals[j];
9853 num_tracks = maxval + 1;
9855 if (num_tracks > mt->num_video_tracks) {
9856 for (j = mt->num_video_tracks; j < num_tracks; j++) {
9873 block_marker_uo_tracks = weed_get_int_array_counted(event,
WEED_LEAF_TRACKS, &block_marker_uo_num_tracks);
9878 maxval = mt->num_video_tracks - 1;
9880 for (j = 0; j < navs; j++) {
9881 if (navals[j] > maxval) maxval = navals[j];
9884 num_tracks = maxval + 1;
9886 if (num_tracks > mt->num_video_tracks) {
9887 for (j = mt->num_video_tracks; j < num_tracks; j++) {
9894 clip_index = weed_get_int_array_counted(event,
WEED_LEAF_CLIPS, &num_tracks);
9897 if (num_tracks < last_tracks) {
9898 for (j = num_tracks; j < last_tracks; j++) {
9900 if (tracks[j] > 0) {
9901 add_block_end_point(LIVES_WIDGET(lives_list_nth_data(mt->video_draws, j)), last_event);
9907 if (num_tracks > mt->num_video_tracks) {
9908 for (j = mt->num_video_tracks; j < num_tracks; j++) {
9913 last_tracks = num_tracks;
9915 new_frame_index = (int64_t *)
lives_malloc(num_tracks * 8);
9916 last_valid_frame = 0;
9918 for (j = 0; j < num_tracks; j++) {
9920 if (clip_index[j] > 0 && frame_index[j] > -1 && clip_index[j] <=
MAX_FILES &&
9921 renumbered_clips[clip_index[j]] > 0 && (frame_index[j] <=
9927 if ((tracks[j] != renumbered_clips[clip_index[j]]) || forced_end) {
9929 if (tracks[j] > 0) {
9931 add_block_end_point(LIVES_WIDGET(lives_list_nth_data(mt->video_draws, j)), last_event);
9933 if (clip_index[j] > 0) {
9939 add_block_start_point(LIVES_WIDGET(lives_list_nth_data(mt->video_draws, j)), tc,
9940 renumbered_clips[clip_index[j]], offset_start, event, ordered);
9942 tracks[j] = renumbered_clips[clip_index[j]];
9944 new_clip_index[j] = renumbered_clips[clip_index[j]];
9945 new_frame_index[j] = frame_index[j];
9946 last_valid_frame = j + 1;
9951 new_clip_index[j] = -1;
9952 new_frame_index[j] = 0;
9953 if (tracks[j] > 0) {
9955 add_block_end_point(LIVES_WIDGET(lives_list_nth_data(mt->video_draws, j)), last_event);
9961 if (last_valid_frame == 0) {
9966 *new_clip_index = -1;
9967 *new_frame_index = 0;
9970 if (last_valid_frame < num_tracks) {
9974 new_frame_index = (int64_t *)
lives_malloc(last_valid_frame * 8);
9975 for (j = 0; j < last_valid_frame; j++) {
9976 new_clip_index[j] = clip_index[j];
9977 new_frame_index[j] = frame_index[j];
9979 num_tracks = last_valid_frame;
9983 weed_set_int_array(event,
WEED_LEAF_CLIPS, num_tracks, new_clip_index);
9984 weed_set_int64_array(event,
WEED_LEAF_FRAMES, num_tracks, new_frame_index);
9995 for (i = 0; i < num_aclips; i += 2) {
9996 if (aclips[i + 1] > 0) {
9998 if (!shown_audio_warn) {
9999 shown_audio_warn =
TRUE;
10004 if (aclips[i] == -1) audio_draw = (LiVESWidget *)mt->audio_draws->data;
10005 else audio_draw = (LiVESWidget *)lives_list_nth_data(mt->audio_draws, aclips[i] + mt->opts.back_audio_tracks);
10006 if (avels[aclips[i] + 1] != 0.) {
10007 add_block_end_point(audio_draw, event);
10008 if (!forced_end && tracks[aclips[i]] > 0 && next_frame_event &&
get_next_frame_event(next_frame_event)) {
10009 add_block_end_point(LIVES_WIDGET(lives_list_nth_data(mt->video_draws, aclips[i])), last_event);
10013 avels[aclips[i] + 1] = aseeks[i + 1];
10016 if (avels[aclips[i] + 1] != 0.) {
10017 add_block_start_point(audio_draw, tc, renumbered_clips[aclips[i + 1]],
10019 if (!forced_end && tracks[aclips[i]] > 0 && next_frame_event &&
get_next_frame_event(next_frame_event)) {
10022 add_block_start_point(LIVES_WIDGET(lives_list_nth_data(mt->video_draws, aclips[i])), tc,
10023 new_clip_index[aclips[i]], offset_start, event, ordered);
10028 if (aclips[i + 1] > 0) aclips[i + 1] = renumbered_clips[aclips[i + 1]];
10038 slist = mt->audio_draws;
10039 for (i = mt->opts.back_audio_tracks + 1; --i > 0; slist = slist->next);
10040 for (; slist; slist = slist->next, i++) {
10043 audio_draw = (LiVESWidget *)slist->data;
10044 if (avels[i] != 0.) {
10047 block = add_block_end_point(audio_draw, event);
10050 offset_start = block->offset_start + (weed_timecode_t)((
double)(tc - last_tc) * avels[i] + .5);
10051 add_block_start_point(audio_draw, tc, -1, offset_start, event,
TRUE);
10056 if (!next_frame_event) {
10059 for (slist = mt->video_draws; slist; slist = slist->next) {
10060 if (tracks[j++] > 0) {
10061 add_block_end_point(LIVES_WIDGET(slist->data), event);
10065 for (slist = mt->audio_draws; slist; slist = slist->next) {
10067 add_block_end_point((LiVESWidget *)slist->data, event);
10070 last_event = event;
10080 if (mt->avol_fx != -1) locate_avol_init_event(mt, mt->event_list, mt->avol_fx);
10082 if (!mt->was_undo_redo && mt->avol_fx != -1 && mt->audio_draws) {
10083 apply_avol_filter(mt);
10088 if (mt->event_list) {
10090 if (mt->end_secs == 0.)
LIVES_WARN(
"got zero length event_list");
10092 if (mt->end_secs == 0.) mt->end_secs =
DEF_TIME;
10096 mt->tl_max = mt->end_secs;
10101 if (!mt->was_undo_redo) {
10102 set_track_labels(mt);
10104 if (mt->is_ready) {
10105 if (mt->current_track != 0) {
10106 mt->current_track = 0;
10109 if (mt->region_start != mt->region_end || mt->region_start != 0.) {
10110 mt->region_start = mt->region_end = 0.;
10115 }
else mt->was_undo_redo =
FALSE;
10125 LiVESWidget *eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, layer);
10126 track_rect *block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks"), *blocknext;
10128 LiVESWidget *checkbutton;
10129 LiVESWidget *label, *labelbox, *ahbox, *arrow;
10130 lives_painter_surface_t *bgimg;
10133 blocknext = block->next;
10134 if (mt->block_selected == block) mt->block_selected = NULL;
10139 if ((bgimg = (lives_painter_surface_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"bgimg")) != NULL) {
10143 checkbutton = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"checkbutton");
10144 label = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"label");
10145 arrow = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"arrow");
10147 mt->cb_list = lives_list_remove(mt->cb_list, (livespointer)checkbutton);
10152 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
HIDDEN_KEY)) == 0) {
10153 labelbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"labelbox");
10154 ahbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"ahbox");
10158 lives_free(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"track_name"));
10168 LiVESWidgetObject *adj;
10169 LiVESWidget *label, *dummy;
10170 LiVESWidget *arrow;
10171 LiVESWidget *eventbox;
10174 char *pname, *tname;
10182 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(audio_draw),
"blocks", (livespointer)NULL);
10183 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(audio_draw),
"block_last", (livespointer)NULL);
10184 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(audio_draw),
HIDDEN_KEY, LIVES_INT_TO_POINTER(0));
10185 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(audio_draw),
"expanded", LIVES_INT_TO_POINTER(
FALSE));
10186 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(audio_draw),
"bgimg", NULL);
10187 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(audio_draw),
"is_audio", LIVES_INT_TO_POINTER(
TRUE));
10191 mt->num_video_tracks : max_disp_vtracks));
10218 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(arrow),
"layer_number", LIVES_INT_TO_POINTER(track));
10219 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(audio_draw),
"layer_number", LIVES_INT_TO_POINTER(track));
10241 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"owner", audio_draw);
10243 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
HIDDEN_KEY, LIVES_INT_TO_POINTER(0));
10244 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"bgimg", NULL);
10245 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"channel", LIVES_INT_TO_POINTER(i));
10250 if (!mt->was_undo_redo) {
10252 llen = lives_list_length(mt->audio_draws);
10256 }
else if (llen == 1) {
10257 if (mt->opts.back_audio_tracks > 0) {
10259 mt->audio_vols->data = LIVES_INT_TO_POINTER(vol);
10261 if (mt->opts.gang_audio) {
10262 vol = LIVES_POINTER_TO_INT(lives_list_nth_data(mt->audio_vols, 0));
10266 if (mt->opts.gang_audio) {
10267 vol = LIVES_POINTER_TO_INT(lives_list_nth_data(mt->audio_vols, mt->opts.back_audio_tracks));
10269 if (mt->opts.back_audio_tracks > 0) {
10278 if (!mt->was_undo_redo && mt->amixer && track >= 0) {
10280 LiVESWidget **ch_sliders;
10281 ulong *ch_slider_fns;
10285 nachans = lives_list_length(mt->audio_vols) + 1;
10287 ch_sliders = (LiVESWidget **)
lives_malloc(nachans *
sizeof(LiVESWidget *));
10291 for (i = 0; i < nachans - 1; i++) {
10292 if (!behind && i == mt->opts.back_audio_tracks) j++;
10293 ch_sliders[j] = mt->amixer->ch_sliders[i];
10294 ch_slider_fns[j] = mt->amixer->ch_slider_fns[i];
10301 mt->amixer->ch_sliders = ch_sliders;
10302 mt->amixer->ch_slider_fns = ch_slider_fns;
10306 mt->audio_draws = lives_list_prepend(mt->audio_draws, (livespointer)audio_draw);
10307 if (!mt->was_undo_redo) mt->audio_vols = lives_list_prepend(mt->audio_vols, LIVES_INT_TO_POINTER(vol));
10308 }
else if (behind) {
10309 mt->audio_draws = lives_list_append(mt->audio_draws, (livespointer)audio_draw);
10311 if (!mt->was_undo_redo) {
10319 mt->audio_vols = lives_list_append(mt->audio_vols, LIVES_INT_TO_POINTER(vol));
10322 mt->audio_draws = lives_list_insert(mt->audio_draws, (livespointer)audio_draw, mt->opts.back_audio_tracks);
10323 if (!mt->was_undo_redo) {
10324 mt->audio_vols = lives_list_insert(mt->audio_vols, LIVES_INT_TO_POINTER(vol), mt->opts.back_audio_tracks);
10337 for (i = mt->opts.back_audio_tracks + 1; i < nachans; i++) {
10338 label = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mt->amixer->ch_sliders[i]),
"label");
10345 adj = (LiVESWidgetObject *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mt->amixer->ch_sliders[i]),
"adj");
10346 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(adj),
"layer", LIVES_INT_TO_POINTER(i));
10355 static void set_track_label(LiVESEventBox * xeventbox,
int tnum) {
10356 LiVESWidget *label = LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"label"));
10357 const char *tname = (
const char *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"track_name");
10369 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(ebox),
"track_name", (livespointer)label);
10370 set_track_label(LIVES_EVENT_BOX(ebox), track);
10374 static int add_video_track(lives_mt * mt,
boolean behind) {
10376 LiVESWidget *label;
10377 LiVESWidget *checkbutton;
10378 LiVESWidget *arrow;
10379 LiVESWidget *eventbox;
10380 LiVESWidget *aeventbox;
10386 if (mt->audio_draws && mt->audio_draws->data && mt->opts.back_audio_tracks > 0 &&
10387 LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mt->audio_draws->data),
HIDDEN_KEY)) == 0) {
10388 max_disp_vtracks--;
10389 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mt->audio_draws->data),
10393 mt->num_video_tracks++;
10401 checkbutton = giw_led_new();
10402 giw_led_enable_mouse(GIW_LED(checkbutton),
TRUE);
10407 mt->cb_list = lives_list_append(mt->cb_list, checkbutton);
10409 if (LIVES_IS_WIDGET(checkbutton)) {
10421 mt->num_video_tracks));
10424 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"expanded", LIVES_INT_TO_POINTER(
FALSE));
10426 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks", (livespointer)NULL);
10427 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"block_last", (livespointer)NULL);
10428 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
HIDDEN_KEY, LIVES_INT_TO_POINTER(0));
10429 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"bgimg", NULL);
10432 mt->num_video_tracks : max_disp_vtracks));
10440 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"layer_number", LIVES_INT_TO_POINTER(0));
10441 for (i = 0; i < mt->num_video_tracks - 1; i++) {
10443 LiVESWidget *xeventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, i);
10444 LiVESWidget *xcheckbutton = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"checkbutton");
10445 LiVESWidget *xarrow = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"arrow");
10446 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
"layer_number", LIVES_INT_TO_POINTER(i + 1));
10447 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xcheckbutton),
"layer_number", LIVES_INT_TO_POINTER(i + 1));
10448 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xarrow),
"layer_number", LIVES_INT_TO_POINTER(i + 1));
10449 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
"is_audio", LIVES_INT_TO_POINTER(
FALSE));
10451 set_track_label(LIVES_EVENT_BOX(xeventbox), i + 1);
10453 if (mt->opts.pertrack_audio) {
10454 LiVESWidget *aeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"atrack");
10455 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(aeventbox),
"layer_number", LIVES_INT_TO_POINTER(i + 1));
10456 xarrow = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(aeventbox),
"arrow");
10457 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xarrow),
"layer_number", LIVES_INT_TO_POINTER(i + 1));
10458 label = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(aeventbox),
"label");
10461 newtext =
lives_strdup_printf(
_(
" %s"), lives_widget_object_get_data(LIVES_WIDGET_OBJECT(aeventbox),
"track_name"));
10465 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(aeventbox),
"is_audio", LIVES_INT_TO_POINTER(
TRUE));
10472 mt->video_draws = lives_list_prepend(mt->video_draws, (livespointer)eventbox);
10473 mt->current_track = 0;
10476 liste = mt->selected_tracks;
10478 liste->data = LIVES_INT_TO_POINTER(LIVES_POINTER_TO_INT(liste->data) + 1);
10479 liste = liste->next;
10483 mt->video_draws = lives_list_append(mt->video_draws, (livespointer)eventbox);
10484 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"layer_number", LIVES_INT_TO_POINTER(mt->num_video_tracks - 1));
10485 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(checkbutton),
"layer_number",
10486 LIVES_INT_TO_POINTER(mt->num_video_tracks - 1));
10487 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(arrow),
"layer_number", LIVES_INT_TO_POINTER(mt->num_video_tracks - 1));
10488 mt->current_track = mt->num_video_tracks - 1;
10493 lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"track_name"),
10494 LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
10495 "layer_number")))));
10503 if (mt->opts.pertrack_audio) {
10505 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(aeventbox),
"owner", eventbox);
10506 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"atrack", aeventbox);
10508 if (mt->avol_init_event) {
10513 if (!behind) scroll_track_on_screen(mt, 0);
10514 else scroll_track_on_screen(mt, mt->num_video_tracks - 1);
10518 if (!behind)
return 0;
10519 else return mt->num_video_tracks - 1;
10525 lives_mt *mt = (lives_mt *)user_data;
10527 tnum = add_video_track(mt,
TRUE);
10535 lives_mt *mt = (lives_mt *)user_data;
10537 tnum = add_video_track(mt,
FALSE);
10544 lives_mt *mt = (lives_mt *)user_data;
10545 if (!mt->selected_init_event)
return;
10554 static boolean mt_fx_edit_idle(livespointer user_data) {
10560 static void mt_avol_quick(LiVESMenuItem * menuitem, livespointer user_data) {
10561 lives_mt *mt = (lives_mt *)user_data;
10562 mt->selected_init_event = mt->avol_init_event;
10567 static void rdrw_cb(LiVESMenuItem * menuitem, livespointer user_data) {
10568 lives_mt *mt = (lives_mt *)user_data;
10569 redraw_all_event_boxes(mt);
10576 LiVESWidget *edit_effect;
10577 LiVESWidget *delete_effect;
10580 weed_plant_t *filter;
10585 fhash = weed_get_string_value(mt->selected_init_event,
WEED_LEAF_FILTER, NULL);
10601 if (mt->selected_init_event != mt->avol_init_event) {
10619 static boolean fx_ebox_pressed(LiVESWidget * eventbox, LiVESXEventButton * event, livespointer user_data) {
10620 lives_mt *mt = (lives_mt *)user_data;
10621 LiVESList *children, *xlist;
10622 weed_plant_t *osel = mt->selected_init_event;
10624 if (mt->is_rendering)
return FALSE;
10626 mt->selected_init_event = (weed_plant_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"init_event");
10628 if (event->type == LIVES_BUTTON2_PRESS) {
10630 mt->moving_fx = NULL;
10632 lives_timer_add_simple(0, mt_fx_edit_idle, mt);
10639 if (osel != mt->selected_init_event && osel != mt->avol_init_event) {
10640 switch (mt->fx_order) {
10647 mt->current_track,
FALSE);
10654 mt->selected_init_event = osel;
10664 mt->current_track,
TRUE);
10672 mt->did_backup =
FALSE;
10673 mt->selected_init_event = osel;
10675 mt->selected_init_event = NULL;
10700 LiVESWidget *child = (LiVESWidget *)children->data;
10701 if (child != eventbox) {
10708 children = children->next;
10710 if (xlist) lives_list_free(xlist);
10720 static void set_clip_labels_variable(lives_mt * mt,
int i) {
10722 LiVESLabel *label1, *label2;
10725 if (!mt->clip_labels)
return;
10730 label1 = (LiVESLabel *)lives_list_nth_data(mt->clip_labels, i);
10731 label2 = (LiVESLabel *)lives_list_nth_data(mt->clip_labels, ++i);
10748 for (i = 0; i < mt->num_video_tracks; i++) {
10751 lives_list_free(mt->video_draws);
10752 mt->video_draws = NULL;
10753 mt->num_video_tracks = 0;
10756 if (mt->selected_tracks) lives_list_free(mt->selected_tracks);
10757 mt->selected_tracks = NULL;
10762 mt->audio_draws = NULL;
10763 if (mt->audio_vols) lives_list_free(mt->audio_vols);
10764 mt->audio_vols = NULL;
10769 mt->changed =
FALSE;
10786 }
else mt->avol_fx = -1;
10787 mt->avol_init_event = NULL;
10803 LiVESList *clist = mt->clip_labels, *clist_nnext;
10805 boolean removed =
FALSE;
10806 int neg = 0, i = 0;
10808 for (; list; i++) {
10809 list_next = list->next;
10812 clist_nnext = clist->next->next;
10813 if (clips_to_files[i] == file) {
10818 if (clist_nnext) clist_nnext->prev = clist->prev;
10819 if (clist->prev) clist->prev->next = clist_nnext;
10820 else mt->clip_labels = clist_nnext;
10821 clist->prev = clist->next->next = NULL;
10822 lives_list_free(clist);
10828 clips_to_files[i] = clips_to_files[i + neg];
10830 clist = clist_nnext;
10831 if (mt->file_selected == file) {
10836 if (olist) lives_list_free(olist);
10865 LiVESWidget *thumb_image = NULL;
10866 LiVESWidget *vbox, *hbox, *label;
10867 LiVESWidget *eventbox;
10869 LiVESPixbuf *thumbnail;
10879 int count = lives_list_length(mt->clip_labels) / 2;
10881 mt->clip_selected = -1;
10883 if (add) i = orig_file;
10885 while (add || cliplist) {
10886 if (add) i = orig_file;
10887 else i = LIVES_POINTER_TO_INT(cliplist->data);
10890 cliplist = cliplist->next;
10898 mt->file_selected = i;
10899 mt->clip_selected = count;
10900 renumbered_clips[i] = i;
10907 mt->nb_label = NULL;
10913 lives_widget_add_events(eventbox, LIVES_BUTTON_RELEASE_MASK | LIVES_BUTTON_PRESS_MASK | LIVES_ENTER_NOTIFY_MASK);
10914 lives_signal_sync_connect(LIVES_GUI_OBJECT(eventbox), LIVES_WIDGET_ENTER_EVENT, LIVES_GUI_CALLBACK(on_clipbox_enter),
10917 clips_to_files[count] = i;
10942 mt->clip_labels = lives_list_append(mt->clip_labels, label);
10949 mt->clip_labels = lives_list_append(mt->clip_labels, label);
10953 set_clip_labels_variable(mt, i);
10956 mt->clip_labels = lives_list_append(mt->clip_labels, label);
10964 mt->clip_labels = lives_list_append(mt->clip_labels, label);
10971 lives_signal_sync_connect(LIVES_GUI_OBJECT(eventbox), LIVES_WIDGET_BUTTON_PRESS_EVENT,
10972 LIVES_GUI_CALLBACK(clip_ebox_pressed), (livespointer)mt);
10973 lives_signal_sync_connect(LIVES_GUI_OBJECT(eventbox), LIVES_WIDGET_BUTTON_RELEASE_EVENT,
10974 LIVES_GUI_CALLBACK(on_drag_clip_end), (livespointer)mt);
10982 if (cliplist) cliplist = cliplist->next;
10987 static void set_audio_mixer_vols(lives_mt * mt, weed_plant_t *elist) {
10990 int catracks, xtrack, xavol, natracks, navols;
10993 if (!atracks)
return;
10995 if (!avols)
return;
10997 catracks = lives_list_length(mt->audio_vols);
10998 for (
int i = 0; i < natracks; i++) {
10999 xtrack = atracks[i];
11000 if (xtrack < -mt->opts.back_audio_tracks)
continue;
11001 if (xtrack >= catracks - mt->opts.back_audio_tracks)
continue;
11004 if (xavol >= navols) {
11005 mt->opts.gang_audio =
TRUE;
11006 xavol = navols - 1;
11016 lives_mt *mt = (lives_mt *)data;
11030 xachans = xarate = xasamps = xse = 0;
11058 if (response == LIVES_RESPONSE_CANCEL) {
11088 xarate = xachans = xasamps = 0;
11089 xse =
cfile->signed_endian;
11156 force_pertrack_audio =
FALSE;
11157 force_backing_tracks = 0;
11161 rerenumber_clips(NULL, event_list);
11167 if (!qevent_list) {
11177 weed_set_double_value(event_list, WEED_LEAF_FPS,
cfile->fps);
11194 if (!multi->event_list) {
11196 multi->file_selected = orig_file;
11208 set_audio_mixer_vols(multi, multi->event_list);
11218 multi->file_selected = orig_file;
11238 if (multi->clip_labels) {
11243 scroll_track_on_screen(multi, 0);
11244 if (multi->nb_label) {
11250 if (
cfile->achans == 0) {
11251 multi->opts.pertrack_audio =
FALSE;
11265 if (multi->hseparator2) {
11270 if (!multi->opts.pertrack_audio) {
11292 mt_zoom(multi, 1.);
11305 redraw_all_event_boxes(multi);
11307 if (multi->opts.pertrack_audio) {
11317 multi->no_expose = multi->no_expose_frame =
FALSE;
11343 if (multi->opts.hpaned_pos != -1)
11349 LIVES_GUI_CALLBACK(hpaned_position), (livespointer)multi);
11361 d_print(
_(
"====== Switched to Multitrack mode ======\n"));
11372 track_rect *block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks");
11377 block = block->next;
11383 static track_rect *get_block_before(LiVESWidget * eventbox,
double time,
boolean allow_cur) {
11389 track_rect *block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks"), *last_block = NULL;
11394 last_block = block;
11395 block = block->next;
11401 static track_rect *get_block_after(LiVESWidget * eventbox,
double time,
boolean allow_cur) {
11407 track_rect *block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks");
11411 block = block->next;
11417 track_rect *
move_block(lives_mt * mt, track_rect * block,
double timesecs,
int old_track,
int new_track) {
11418 weed_timecode_t new_start_tc, end_tc;
11421 ulong uid = block->uid;
11423 LiVESWidget *eventbox, *oeventbox;
11425 int clip, current_track = -1;
11427 boolean did_backup = mt->did_backup;
11428 boolean needs_idlefunc =
FALSE;
11430 if (mt->idlefunc > 0) {
11431 needs_idlefunc =
TRUE;
11439 if (is_audio_eventbox(block->eventbox) && (oeventbox =
11440 (LiVESWidget *)lives_widget_object_get_data
11441 (LIVES_WIDGET_OBJECT(block->eventbox),
"owner")) != NULL) {
11446 mt->block_selected = block;
11451 weed_plant_t *
event = NULL;
11452 weed_timecode_t tc = 0, tcnow;
11453 weed_timecode_t tclen = end_tc - start_tc;
11454 while (tc <= tclen) {
11457 if (old_track == new_track && tcnow >= start_tc && tcnow <= end_tc)
continue;
11460 if (new_track >= 0) {
11464 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
11474 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
11489 if (old_track > -1) {
11491 mt->insert_start = block->offset_start;
11497 mt->insert_end =
q_gint64(mt->insert_start + (end_tc - start_tc), mt->fps);
11500 mt->moving_block =
TRUE;
11501 mt->current_track = old_track;
11503 mt->block_selected = NULL;
11504 mt->current_track = new_track;
11514 mt->insert_avel = 1.;
11517 mt->insert_start = mt->insert_end = -1;
11524 if (mt->opts.move_effects)
update_filter_events(mt, mt->specific_event, start_tc, end_tc, old_track, new_start_tc,
11525 mt->current_track);
11528 mt->moving_block =
FALSE;
11529 mt->specific_event = NULL;
11531 if (new_track != -1) eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, mt->current_track);
11532 else eventbox = (LiVESWidget *)mt->audio_draws->data;
11533 block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"block_last");
11538 double oldr_start = mt->region_start;
11539 double oldr_end = mt->region_end;
11540 LiVESList *tracks_sel = NULL;
11541 track_rect *lblock;
11547 lblock = block->prev;
11553 lblock = block->next;
11558 mt->region_start = rstart;
11559 mt->region_end = rend;
11561 if (new_track > -1) {
11562 tracks_sel = lives_list_copy(mt->selected_tracks);
11563 if (mt->selected_tracks) lives_list_free(mt->selected_tracks);
11564 mt->selected_tracks = NULL;
11565 mt->selected_tracks = lives_list_append(mt->selected_tracks, LIVES_INT_TO_POINTER(new_track));
11567 current_track = mt->current_track;
11568 mt->current_track = old_track;
11572 if (old_track > -1) {
11573 lives_list_free(mt->selected_tracks);
11574 mt->selected_tracks = lives_list_copy(tracks_sel);
11575 if (tracks_sel) lives_list_free(tracks_sel);
11576 }
else mt->current_track = current_track;
11577 mt->region_start = oldr_start;
11578 mt->region_end = oldr_end;
11583 block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"block_last");
11586 if (mt->avol_fx != -1 && (!block || !block->next) && mt->audio_draws &&
11588 apply_avol_filter(mt);
11595 mt->did_backup = did_backup;
11597 mt->did_backup =
TRUE;
11600 if (!did_backup && mt->framedraw && mt->current_rfx && mt->init_event &&
11604 get_track_index(mt, tc);
11608 if (block) block->uid = uid;
11611 mt->did_backup =
FALSE;
11612 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
11622 LiVESWidget *eventbox;
11629 for (list = mt->audio_draws; list; list = list->next) {
11630 eventbox = (LiVESWidget *)list->data;
11632 trec = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks");
11640 for (list = mt->video_draws; list; list = list->next) {
11641 eventbox = (LiVESWidget *)list->data;
11643 trec = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks");
11650 mt->block_selected = NULL;
11661 static void _clear_context(lives_mt * mt) {
11664 if (mt->context_scroll) {
11674 LIVES_POLICY_AUTOMATIC);
11700 LiVESWidget *label;
11724 if (!mt->event_list || !
get_first_event(mt->event_list) || mt->tl_fixed_length > 0.)
return FALSE;
11728 if (end_secs > mt->end_secs) {
11733 redraw_all_event_boxes(mt);
11739 static void set_in_out_spin_ranges(lives_mt * mt, weed_timecode_t start_tc, weed_timecode_t end_tc) {
11740 track_rect *block = mt->block_selected;
11741 weed_timecode_t min_tc = 0, max_tc = -1;
11745 out_start_range = in_val + 1. / mt->fps;
11746 double out_end_range, real_out_end_range;
11747 double in_end_range = out_val - 1. / mt->fps, real_in_start_range = in_start_range;
11750 int track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"layer_number"));
11772 real_out_end_range = out_end_range;
11775 if (!block->end_anchored && max_tc > -1 &&
11779 if (!block->start_anchored && min_tc > -1 &&
11783 if (!block->start_anchored) out_end_range = real_out_end_range;
11784 if (!block->end_anchored) in_start_range = real_in_start_range;
11787 if (block->end_anchored && (out_val - in_val > out_start_range)) out_start_range = in_start_range + out_val - in_val;
11788 if (block->start_anchored && (out_end_range - out_val + in_val) < in_end_range) in_end_range = out_end_range - out_val + in_val;
11790 in_end_range =
lives_fix(in_end_range, 2);
11791 real_out_end_range =
lives_fix(real_out_end_range, 2);
11793 out_start_range =
lives_fix(out_start_range, 2);
11794 real_in_start_range =
lives_fix(real_in_start_range, 2);
11809 static void update_in_image(lives_mt * mt) {
11810 LiVESPixbuf *thumb;
11811 track_rect *block = mt->block_selected;
11818 if (!mt->insurface)
return;
11821 track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"layer_number"));
11826 filenum = mt->file_selected;
11843 static void update_out_image(lives_mt * mt, weed_timecode_t end_tc) {
11844 LiVESPixbuf *thumb;
11845 track_rect *block = mt->block_selected;
11852 if (!mt->outsurface)
return;
11855 track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"layer_number"));
11861 filenum = mt->file_selected;
11879 lives_mt *mt = (lives_mt *)user_data;
11880 track_rect *block = mt->block_selected;
11881 weed_timecode_t end_tc;
11883 if (!block)
return FALSE;
11884 track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"layer_number"));
11885 if (track < 0)
return FALSE;
11888 if (!mt->insurface || !mt->outsurface)
return TRUE;
11891 update_in_image(mt);
11892 update_out_image(mt, end_tc);
11898 lives_mt *mt = (lives_mt *)user_data;
11900 track_rect *block = mt->block_selected, *ablock = NULL;
11902 weed_plant_t *event;
11903 weed_plant_t *start_event = NULL, *event_next;
11905 weed_timecode_t new_start_tc, orig_start_tc, offset_end, tl_start;
11906 weed_timecode_t new_tl_tc;
11909 double avel = 1., aseek = 0.;
11912 boolean start_anchored;
11913 boolean needs_idlefunc =
FALSE;
11914 boolean did_backup = mt->did_backup;
11922 if (mt->idlefunc > 0) {
11923 needs_idlefunc =
TRUE;
11934 set_clip_labels_variable(mt, mt->file_selected);
11935 update_in_image(mt);
11940 if (needs_idlefunc || (!did_backup && mt->auto_changed)) {
11949 event = block->start_event;
11950 orig_start_tc = block->offset_start;
11951 track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"layer_number"));
11952 new_start_tc =
q_dbl(new_start, mt->fps);
11954 if (new_start_tc == orig_start_tc || !block->ordered) {
11956 if (needs_idlefunc || (!did_backup && mt->auto_changed)) {
11967 if (!mt->aud_track_selected) {
11968 if (mt->opts.pertrack_audio) {
11969 LiVESWidget *aeventbox = LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"atrack"));
11972 start_anchored = block->start_anchored;
11974 LiVESWidget *eventbox = LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"owner"));
11977 start_anchored = ablock->start_anchored;
11982 start_anchored = block->start_anchored;
11987 if (!start_anchored) {
11988 if (new_start_tc > block->offset_start) {
11993 if ((
get_event_timecode(event) - tl_start) >= (new_start_tc - block->offset_start) / avel) {
12001 if (ablock->prev && ablock->prev->end_event == ablock->start_event) {
12009 ablock->start_event = event;
12010 ablock->offset_start = new_start_tc;
12012 if (block != ablock) {
12013 block->start_event = event;
12014 block->offset_start = new_start_tc;
12019 if (event == block->end_event) {
12020 if (needs_idlefunc || (!did_backup && mt->auto_changed)) {
12047 if (event == start_event) start_event = NULL;
12061 event = event_next;
12076 q_gint64(tl_start + (new_start_tc - ablock->offset_start) / avel, mt->fps),
12082 if (block != ablock) {
12085 block->offset_start = new_start_tc;
12090 event = block->start_event;
12093 start_event = event;
12103 event = start_event;
12118 block->eventbox, mt, block);
12126 mt->opts.insert_mode = insert_mode;
12129 offset_end = (new_start_tc = block->offset_start) + (weed_timecode_t)((double)(track >= 0) *
TICKS_PER_SECOND_DBL / mt->fps) +
12133 set_in_out_spin_ranges(mt, new_start_tc, offset_end);
12145 update_in_image(mt);
12146 if (start_anchored) update_out_image(mt, offset_end);
12147 update_in_image(mt);
12148 if (start_anchored) update_out_image(mt, offset_end);
12153 redraw_eventbox(mt, block->eventbox);
12154 paint_lines(mt, mt->ptr_time,
TRUE, NULL);
12158 mt->auto_changed =
TRUE;
12175 lives_mt *mt = (lives_mt *)user_data;
12177 track_rect *block = mt->block_selected, *ablock = NULL;
12179 weed_timecode_t offset_end, orig_end_tc;
12180 weed_timecode_t new_end_tc, tl_end;
12181 weed_timecode_t new_tl_tc;
12183 weed_plant_t *event, *prevevent, *shortcut = NULL;
12184 weed_plant_t *start_event, *event_next, *init_event, *new_end_event;
12188 double aseek, avel = 1.;
12191 boolean end_anchored;
12192 boolean needs_idlefunc =
FALSE;
12193 boolean did_backup = mt->did_backup;
12203 if (mt->idlefunc > 0) {
12204 needs_idlefunc =
TRUE;
12211 sfile->
end = (int)new_end;
12212 set_clip_labels_variable(mt, mt->file_selected);
12213 update_out_image(mt, 0);
12216 if (needs_idlefunc || (!did_backup && mt->auto_changed)) {
12224 event = block->end_event;
12225 track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"layer_number"));
12231 if (!mt->aud_track_selected) {
12232 if (mt->opts.pertrack_audio) {
12233 LiVESWidget *aeventbox = LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"atrack"));
12236 end_anchored = block->end_anchored;
12238 LiVESWidget *eventbox = LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"owner"));
12241 end_anchored = ablock->end_anchored;
12246 end_anchored = block->end_anchored;
12261 orig_end_tc = offset_end;
12263 #ifdef DEBUG_BL_MOVE
12264 g_print(
"pt a %ld %ld %ld %.4f %ld %ld\n", block->offset_start,
get_event_timecode(block->end_event),
12272 if (needs_idlefunc || (!did_backup && mt->auto_changed)) {
12281 if (!end_anchored) {
12286 #ifdef DEBUG_BL_MOVE
12287 g_print(
"new tl tc is %ld %ld %.4f %.4f\n", new_tl_tc, tl_end, new_end, start_val);
12289 if (tl_end > new_tl_tc) {
12296 if (!ablock->next || ablock->next->start_event != ablock->end_event)
12300 block->end_event = event;
12310 if (!new_end_event) {
12311 weed_plant_t *shortcut = ablock->end_event;
12313 q_gint64(new_tl_tc + (weed_timecode_t)((
double)(track >= 0) *
12316 ablock->end_event = shortcut;
12317 }
else ablock->end_event = new_end_event;
12323 start_event = block->end_event;
12332 if (event == start_event) start_event = NULL;
12337 if (init_event != mt->avol_init_event) {
12348 event = event_next;
12360 block->end_event,
TRUE);
12365 shortcut = last_frame_event;
12366 while (final_tc < new_tl_tc) {
12373 ablock->end_event,
TRUE);
12374 if (new_end_event == ablock->end_event) {
12381 if (!new_end_event) {
12382 if (!shortcut) shortcut = ablock->end_event;
12385 ablock->end_event = shortcut;
12386 }
else ablock->end_event = new_end_event;
12388 if (!ablock->next || ablock->next->start_event != ablock->end_event) {
12396 start_event = event;
12401 if (init_event != mt->avol_init_event) {
12407 event = start_event;
12416 weed_timecode_t offset_start;
12419 offset_end =
q_gint64((offset_start = block->offset_start + new_end_tc - orig_end_tc) +
12426 if (track >= 0)
insert_frames(filenum, offset_end, offset_start, tl_end +
12427 (weed_timecode_t)((
double)(track >= 0
12431 block->offset_start =
q_gint64(offset_start, mt->fps);
12442 mt->opts.insert_mode = insert_mode;
12446 new_end_tc = (block->offset_start + (weed_timecode_t)((
double)(track >= 0) *
TICKS_PER_SECOND_DBL / mt->fps) +
12449 #ifdef DEBUG_BL_MOVE
12454 if (mt->avol_fx != -1 && mt->avol_init_event && mt->audio_draws &&
12455 mt->audio_draws->data && !block->next) {
12456 apply_avol_filter(mt);
12460 set_in_out_spin_ranges(mt, block->offset_start, new_end_tc);
12470 update_out_image(mt, new_end_tc);
12471 if (end_anchored) update_in_image(mt);
12474 #ifdef DEBUG_BL_MOVE
12475 g_print(
"pt b %ld\n",
q_gint64(new_end_tc / avel, mt->fps));
12478 redraw_eventbox(mt, block->eventbox);
12479 if (ablock && ablock != block) redraw_eventbox(mt, block->eventbox);
12480 paint_lines(mt, mt->ptr_time,
TRUE, NULL);
12484 mt->auto_changed =
TRUE;
12501 lives_mt *mt = (lives_mt *)user_data;
12502 track_rect *block = mt->block_selected;
12503 int track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"layer_number"));
12538 if (!block->start_anchored || !block->end_anchored) {
12549 lives_mt *mt = (lives_mt *)user_data;
12550 track_rect *block = mt->block_selected;
12551 int track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"layer_number"));
12555 weed_timecode_t new_end_tc, old_tl_tc, start_tc, new_tl_tc, min_tc;
12556 weed_plant_t *new_end_event, *new_start_event;
12557 double orig_end_val, orig_start_val;
12558 boolean was_adjusted =
FALSE;
12564 start_tc = block->offset_start;
12569 if (!block->end_anchored) {
12570 new_end_tc =
q_gint64(start_tc + ((orig_end_val =
12583 set_in_out_spin_ranges(mt, block->offset_start, new_end_tc);
12592 if (new_tl_tc != old_tl_tc) {
12593 weed_plant_t *shortcut;
12594 if (new_tl_tc > old_tl_tc) shortcut = block->end_event;
12595 else shortcut = block->start_event;
12596 if (!block->next || block->next->start_event != block->end_event)
remove_audio_for_track(block->end_event, -1);
12598 if (new_end_event == block->start_event)
return;
12599 block->end_event = new_end_event;
12601 if (!block->end_event) {
12606 if (!block->next || block->next->start_event != block->end_event)
12618 if (mt->avol_fx != -1 && !block->next) {
12619 apply_avol_filter(mt);
12623 redraw_eventbox(mt, block->eventbox);
12624 paint_lines(mt, mt->ptr_time,
TRUE, NULL);
12637 if (new_tl_tc < min_tc) {
12640 new_tl_tc = min_tc;
12641 was_adjusted =
TRUE;
12646 if (was_adjusted || new_tl_tc != old_tl_tc) {
12647 weed_plant_t *shortcut;
12648 if (new_tl_tc > old_tl_tc) shortcut = block->start_event;
12650 if (block->prev) shortcut = block->prev->end_event;
12651 else shortcut = NULL;
12655 if (new_start_event == block->end_event)
return;
12657 if (!block->prev || block->start_event != block->prev->end_event)
remove_audio_for_track(block->start_event, -1);
12659 block->start_event = new_start_event;
12665 set_in_out_spin_ranges(mt, start_tc, new_end_tc);
12676 if (mt->avol_fx != -1 && !block->next) {
12677 apply_avol_filter(mt);
12684 lives_mt *mt = (lives_mt *)user_data;
12685 track_rect *block = mt->block_selected;
12686 weed_timecode_t offset_end;
12691 if (mt->current_track < 0) {
12695 offset_end = block->offset_start + (double)(mt->current_track >= 0 && !mt->aud_track_selected) *
12699 block->start_anchored = !block->start_anchored;
12701 set_in_out_spin_ranges(mt, block->offset_start, offset_end);
12711 if (mt->current_track >= 0 && mt->opts.pertrack_audio) {
12712 LiVESWidget *xeventbox;
12713 track_rect *xblock;
12716 if (mt->aud_track_selected) {
12717 xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"owner");
12719 xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"atrack");
12723 if (xblock) xblock->start_anchored = block->start_anchored;
12730 lives_mt *mt = (lives_mt *)user_data;
12731 track_rect *block = mt->block_selected;
12732 weed_timecode_t offset_end;
12737 if (mt->current_track < 0) {
12741 offset_end = block->offset_start + (double)(mt->current_track >= 0 && !mt->aud_track_selected) *
12745 block->end_anchored = !block->end_anchored;
12747 set_in_out_spin_ranges(mt, block->offset_start, offset_end);
12757 if (mt->current_track >= 0 && mt->opts.pertrack_audio) {
12758 LiVESWidget *xeventbox;
12759 track_rect *xblock;
12762 if (mt->aud_track_selected) {
12763 xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"owner");
12765 xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"atrack");
12769 if (xblock) xblock->end_anchored = block->end_anchored;
12775 #define POLY_WIDTH_MARGIN 4 // I think this is the frame border width (1 px) * 2 * 2
12778 LiVESPixbuf *thumb;
12780 weed_timecode_t offset_end = 0;
12781 weed_timecode_t tc;
12783 weed_plant_t *filter, *inst;
12784 weed_plant_t *frame_event, *filter_map = NULL;
12785 weed_plant_t *init_event;
12786 weed_plant_t *prev_fm_event, *next_fm_event, *shortcut;
12788 track_rect *block = mt->block_selected;
12790 void **init_events;
12792 int *in_tracks, *out_tracks;
12795 LiVESWidget *eventbox, *xeventbox, *yeventbox, *label, *vbox;
12798 double out_end_range;
12802 char *fname, *otrackname, *txt;
12804 boolean is_input, is_output;
12805 boolean has_effect =
FALSE;
12806 boolean has_params;
12807 boolean tab_set =
FALSE;
12808 boolean start_anchored, end_anchored;
12810 int num_in_tracks, num_out_tracks;
12811 int def_out_track = 0;
12819 int track, fromtrack;
12820 int frame_start, frame_end = 0;
12823 static int xxwidth = 0, xxheight = 0;
12827 if (mt->in_sensitise)
return;
12833 switch (mt->poly_state) {
12845 if (mt->framedraw) {
12847 mt->framedraw = NULL;
12849 if (mt->current_rfx) {
12853 mt->current_rfx = NULL;
12859 mt->fx_params_label = NULL;
12863 if (mt->mt_frame_preview) {
12883 mt->init_event = NULL;
12890 mt->selected_init_event = NULL;
12891 mt->fm_edit_event = NULL;
12892 mt->context_time = -1.;
12900 mt->fx_list_scroll = NULL;
12907 mt->fx_list_box = NULL;
12909 mt->nb_label = NULL;
12911 mt->poly_state = poly;
12913 if (mt->poly_state ==
POLY_NONE)
return;
12920 while (xxwidth < 1 || xxheight < 1) {
12940 mt->init_event = NULL;
12941 if (!block || block->ordered) {
12951 track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
"layer_number"));
12953 offset_end = block->offset_start + (weed_timecode_t)((
double)(track >= 0) *
TICKS_PER_SECOND_DBL / mt->fps) +
12956 start_anchored = block->start_anchored;
12957 end_anchored = block->end_anchored;
12960 start_anchored = end_anchored =
FALSE;
12961 filenum = mt->file_selected;
12967 LiVESWidget *oeventbox;
12971 if (mt->context_time != -1. && mt->use_context) secs = mt->context_time;
12972 if (is_audio_eventbox(block->eventbox) &&
12973 (oeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(block->eventbox),
12976 block = get_block_from_time(oeventbox, secs, mt);
12983 filenum = mt->file_selected;
12990 filenum = mt->file_selected;
12996 if (mt->insurface) {
12997 thumb =
make_thumb(mt, filenum, width, height, frame_start, LIVES_INTERP_NORMAL,
FALSE);
13035 filenum = mt->file_selected;
13062 if (mt->outsurface) {
13063 thumb =
make_thumb(mt, filenum, width, height, frame_end, LIVES_INTERP_NORMAL,
FALSE);
13074 / mt->fps, out_end_range);
13076 if (!block->start_anchored || !block->end_anchored) {
13126 mt->init_event = NULL;
13136 if (mt->current_rfx) {
13159 get_track_index(mt, tc);
13161 mt->prev_fx_time = 0;
13166 mt->block_tl_move =
TRUE;
13168 mt->block_tl_move =
FALSE;
13175 add_context_label(mt,
_(
"NODES are points where parameters\nhave been set.\nNodes can be deleted."));
13191 mt->init_event = NULL;
13192 if (mt->current_track >= 0) eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, mt->current_track);
13193 else eventbox = (LiVESWidget *)mt->audio_draws->data;
13195 if (!eventbox)
break;
13197 secs = mt->ptr_time;
13198 if (mt->context_time != -1. && mt->use_context) secs = mt->context_time;
13200 block = get_block_from_time(eventbox, secs, mt);
13202 block = get_block_before(eventbox, secs,
FALSE);
13203 if (block) shortcut = block->end_event;
13204 else shortcut = NULL;
13205 }
else shortcut = block->start_event;
13218 set_css_value_direct(mt->fx_list_label, LIVES_WIDGET_STATE_NORMAL,
"",
"padding-top",
"10px");
13219 set_css_value_direct(mt->fx_list_label, LIVES_WIDGET_STATE_NORMAL,
"",
"padding-bottom",
"10px");
13238 for (i = 0; i < num_fx; i++) {
13239 init_event = (weed_plant_t *)init_events[i];
13244 if (num_in_tracks > 0) {
13245 for (j = 0; j < num_in_tracks; j++) {
13246 if (in_tracks[j] == mt->current_track) {
13248 }
else if (num_in_tracks == 2) fromtrack = in_tracks[j];
13254 if (num_out_tracks > 0) {
13255 def_out_track = out_tracks[0];
13256 for (j = 0; j < num_out_tracks; j++) {
13257 if (out_tracks[j] == mt->current_track) {
13265 if (!is_input && !is_output)
continue;
13278 }
else if (!is_output && num_out_tracks > 0) {
13279 if (def_out_track > -1) {
13280 yeventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, def_out_track);
13281 olayer = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(yeventbox),
"layer_number"));
13283 }
else otrackname = (
_(
"audio track"));
13286 }
else if (num_in_tracks == 2 && num_out_tracks > 0) {
13287 if (fromtrack > -1) {
13288 yeventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, fromtrack);
13289 olayer = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(yeventbox),
"layer_number"));
13291 }
else otrackname = (
_(
"audio track"));
13295 txt = lives_strdup(fname);
13298 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(xeventbox),
"init_event", (livespointer)init_event);
13314 if (init_event == mt->selected_init_event) {
13322 lives_signal_sync_connect(LIVES_GUI_OBJECT(xeventbox), LIVES_WIDGET_BUTTON_PRESS_EVENT,
13323 LIVES_GUI_CALLBACK(fx_ebox_pressed), (livespointer)mt);
13348 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->prev_fm_button), LIVES_WIDGET_CLICKED_SIGNAL,
13358 mt->selected_init_event != NULL);
13360 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->fx_ibefore_button), LIVES_WIDGET_CLICKED_SIGNAL,
13369 mt->selected_init_event != NULL);
13371 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->fx_iafter_button), LIVES_WIDGET_CLICKED_SIGNAL,
13375 mt->fx_ibefore_button = mt->fx_iafter_button = NULL;
13386 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->next_fm_button), LIVES_WIDGET_CLICKED_SIGNAL,
13404 set_fxlist_label(mt);
13413 add_context_label(mt, (
_(
"Drag a compositor anywhere\non the timeline\nto apply it to the selected region.")));
13420 add_context_label(mt, (
_(
"Drag a transition anywhere\non the timeline\nto apply it to the selected region.")));
13433 mt->fx_list_scroll = NULL;
13435 if (mt->poly_state ==
POLY_COMP) nins = 1000000;
13436 populate_filter_box(nins, mt, 0);
13446 static void mouse_select_start(LiVESWidget * widget, LiVESXEventButton * event, lives_mt * mt) {
13456 mt->timeline, &mt->sel_x, &mt->sel_y);
13458 mt->region_start = mt->region_end = mt->region_init = timesecs;
13460 mt->region_updating =
TRUE;
13462 mt->region_updating =
FALSE;
13465 mt->tl_eventbox, &mt->sel_x, &mt->sel_y);
13468 if (mt->sel_x < min_x) mt->sel_x = min_x;
13469 if (mt->sel_y < 0.) mt->sel_y = 0.;
13474 mt->tl_selecting =
TRUE;
13478 static void mouse_select_end(LiVESWidget * widget, LiVESXEventButton * event, lives_mt * mt) {
13481 mt->tl_selecting =
FALSE;
13483 mt->timeline, &mt->sel_x, &mt->sel_y);
13490 static void mouse_select_move(LiVESWidget * widget, LiVESXEventMotion * event, lives_mt * mt) {
13491 lives_painter_t *cr;
13493 LiVESWidget *xeventbox;
13494 LiVESWidget *checkbutton;
13497 int start_x, start_y, width, height;
13498 int current_track = mt->current_track;
13500 int rel_x, rel_y, min_x;
13501 int offs_y_start, offs_y_end, xheight;
13510 mt->tl_eventbox, &x, &y);
13513 if (x < min_x) x = min_x;
13514 if (y < 0.) y = 0.;
13519 if (x >= mt->sel_x) {
13520 start_x = mt->sel_x;
13521 width = x - mt->sel_x;
13524 width = mt->sel_x - x;
13526 if (y >= mt->sel_y) {
13527 start_y = mt->sel_y;
13528 height = y - mt->sel_y;
13531 height = mt->sel_y - y;
13534 if (start_x < 0) start_x = 0;
13535 if (start_y < 0) start_y = 0;
13543 for (i = 0; i < mt->num_video_tracks; i++) {
13544 xeventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, i);
13545 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
HIDDEN_KEY)) == 0) {
13547 checkbutton = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"checkbutton");
13549 if (start_y > (rel_y + xheight / 2) || (start_y + height) < (rel_y + xheight / 2)) {
13555 mt->current_track = current_track;
13560 if (giw_led_get_mode(GIW_LED(checkbutton))) {
13561 giw_led_set_mode(GIW_LED(checkbutton),
FALSE);
13562 mt->current_track = current_track;
13570 offs_y_end = xheight;
13572 if (start_y < rel_y + xheight) {
13573 offs_y_start = start_y - rel_y;
13577 if (start_y + height < rel_y + xheight) {
13578 offs_y_end = start_y - rel_y + height;
13594 mt->current_track = current_track;
13599 if (!giw_led_get_mode(GIW_LED(checkbutton))) {
13600 giw_led_set_mode(GIW_LED(checkbutton),
TRUE);
13601 mt->current_track = current_track;
13611 if (widget != mt->timeline_eb) {
13612 mt->region_updating =
TRUE;
13614 mt->region_updating =
FALSE;
13622 LiVESWidget *delete_block;
13623 LiVESWidget *split_here;
13624 LiVESWidget *list_fx_here;
13625 LiVESWidget *selblock;
13629 double block_start_time, block_end_time;
13640 LIVES_GUI_CALLBACK(
selblock_cb), (livespointer)mt);
13642 if (block->ordered) {
13650 if (mt->ptr_time < block_start_time || mt->ptr_time >= block_end_time)
13653 lives_signal_sync_connect(LIVES_GUI_OBJECT(split_here), LIVES_WIDGET_ACTIVATE_SIGNAL,
13663 if (is_audio_eventbox(block->eventbox) && mt->avol_init_event) {
13664 char *avol_fxname = weed_get_string_value(
get_weed_filter(mt->avol_fx), WEED_LEAF_NAME, NULL);
13672 LIVES_GUI_CALLBACK(mt_avol_quick), (livespointer)mt);
13698 LiVESWidget *insert_here, *avol;
13701 boolean has_something =
FALSE;
13702 boolean needs_idlefunc =
FALSE;
13703 boolean did_backup = mt->did_backup;
13707 if (mt->idlefunc > 0) {
13710 needs_idlefunc =
TRUE;
13713 mouse_select_end(NULL, event, mt);
13717 if (mt->file_selected > 0 && ((track < 0 && mainw->files[mt->file_selected]->achans > 0 &&
13732 has_something =
TRUE;
13735 if (mt->audio_draws && (track < 0 || mt->opts.pertrack_audio) && mt->event_list) {
13736 char *avol_fxname = weed_get_string_value(
get_weed_filter(mt->avol_fx), WEED_LEAF_NAME, NULL);
13744 LIVES_GUI_CALLBACK(mt_avol_quick),
13749 has_something =
TRUE;
13752 if (has_something) {
13763 LIVES_GUI_CALLBACK(rdrw_cb),
13767 if (needs_idlefunc || (!did_backup && mt->auto_changed)) {
13773 boolean on_track_release(LiVESWidget * eventbox, LiVESXEventButton * event, livespointer user_data) {
13774 lives_mt *mt = (lives_mt *)user_data;
13775 weed_timecode_t tc, tcpp;
13777 LiVESWidget *xeventbox;
13778 LiVESWidget *oeventbox;
13779 LiVESWidget *xlabelbox;
13780 LiVESWidget *xahbox;
13781 LiVESXWindow *window;
13785 boolean got_track =
FALSE;
13786 boolean needs_idlefunc =
FALSE;
13787 boolean did_backup = mt->did_backup;
13793 int old_track = mt->current_track;
13799 if (mt->idlefunc > 0) {
13802 needs_idlefunc =
TRUE;
13814 mt->display, &win_x, &win_y);
13818 for (list = mt->audio_draws; list; list = list->next, i++) {
13819 xeventbox = (LiVESWidget *)list->data;
13820 oeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"owner");
13821 if (i >= mt->opts.back_audio_tracks &&
13822 !LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(oeventbox),
"expanded")))
continue;
13823 xlabelbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"labelbox");
13824 xahbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"ahbox");
13829 mt->aud_track_selected =
TRUE;
13836 for (list = mt->video_draws; list; list = list->next) {
13837 xeventbox = (LiVESWidget *)list->data;
13838 xlabelbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"labelbox");
13839 xahbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"ahbox");
13842 track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"layer_number"));
13843 mt->aud_track_selected =
FALSE;
13851 mouse_select_end(eventbox, event, mt);
13853 mt->sel_y -= y + 2;
13855 if (mt->hotspot_x != 0 || mt->hotspot_y != 0) {
13856 LiVESXScreen *screen;
13861 mt->display, &screen, &abs_x, &abs_y, NULL);
13863 mt->display, screen, abs_x + mt->hotspot_x, abs_y + mt->hotspot_y - height / 2);
13864 mt->hotspot_x = mt->hotspot_y = 0;
13872 mt->putative_block = get_block_from_time(eventbox, timesecs, mt);
13874 mt->putative_block = NULL;
13875 doubleclick =
FALSE;
13876 goto track_rel_done;
13879 if (got_track && !mt->is_rendering && mt->putative_block && !
LIVES_IS_PLAYING &&
13880 event->button == 1) {
13881 weed_timecode_t start_tc;
13891 (LIVES_WIDGET(lives_list_nth_data(mt->video_draws, 0))));
13894 if ((track != mt->current_track || (tc - start_tc > (tcpp * 3 / 2)) || (start_tc - tc > (tcpp * 3 / 2))) &&
13895 ((old_track < 0 && track < 0) || (old_track >= 0 && track >= 0))) {
13896 move_block(mt, mt->putative_block, timesecs, old_track, track);
13897 mt->putative_block = NULL;
13911 mt->hotspot_x = mt->hotspot_y = 0;
13912 mt->putative_block = NULL;
13917 if (needs_idlefunc || (!did_backup && mt->auto_changed)) {
13926 lives_mt *mt = (lives_mt *)user_data;
13929 mouse_select_start(widget, event, mt);
13937 lives_mt *mt = (lives_mt *)user_data;
13940 mouse_select_end(widget, event, mt);
13948 lives_mt *mt = (lives_mt *)user_data;
13951 mouse_select_start(widget, event, mt);
13959 lives_mt *mt = (lives_mt *)user_data;
13962 mouse_select_end(widget, event, mt);
13969 boolean on_track_click(LiVESWidget * eventbox, LiVESXEventButton * event, livespointer user_data) {
13970 lives_mt *mt = (lives_mt *)user_data;
13984 mt->aud_track_selected = is_audio_eventbox(eventbox);
13993 if (
mainw->
files[mt->render_file]->
achans == 0 || !mt->audio_draws || (mt->opts.back_audio_tracks == 0 ||
13994 eventbox != mt->audio_draws->data))
13995 track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"layer_number"));
13997 block = mt->putative_block = get_block_from_time(eventbox, timesecs, mt);
14001 if (mt->opts.mouse_mode ==
MOUSE_MODE_SELECT && event->type == LIVES_BUTTON_PRESS) {
14002 mouse_select_start(eventbox, event, mt);
14007 doubleclick =
TRUE;
14011 if (event->button == 1) {
14013 mt->fm_edit_event = NULL;
14025 if (event->time != dclick_time) {
14026 show_track_info(mt, eventbox, track, timesecs);
14028 if (!is_audio_eventbox(eventbox))
14036 if (!mt->is_rendering) {
14037 double start_secs, end_secs;
14039 LiVESXScreen *screen;
14049 if (event->button == 1) {
14051 mt->putative_block = NULL;
14054 if (!is_audio_eventbox(eventbox))
14058 width = (width / (mt->tl_max - mt->tl_min) * (
double)ebwidth);
14059 if (width > ebwidth) width = ebwidth;
14060 if (width < 2) width = 2;
14062 mt->hotspot_x = x - (int)((ebwidth * ((
double)start_secs - mt->tl_min) / (mt->tl_max - mt->tl_min)) + .5);
14065 mt->display, &screen, &abs_x, &abs_y, NULL);
14067 mt->display, screen, abs_x - mt->hotspot_x, abs_y - y + height / 2);
14068 if (track >= 0 && !mt->aud_track_selected) {
14083 mt->putative_block = NULL;
14087 mt->current_track = track;
14092 mt->context_time = timesecs;
14095 mt->putative_block = block;
14112 boolean on_track_move(LiVESWidget * widget, LiVESXEventMotion * event, livespointer user_data) {
14114 lives_mt *mt = (lives_mt *)user_data;
14116 if (mt->opts.mouse_mode ==
MOUSE_MODE_SELECT) mouse_select_move(widget, event, mt);
14123 lives_mt *mt = (lives_mt *)user_data;
14125 if (mt->opts.mouse_mode ==
MOUSE_MODE_SELECT) mouse_select_move(widget, event, mt);
14134 if (mt->redraw_block)
return;
14136 if (!mt->is_ready)
return;
14137 if ((xoffset = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"has_line"))) < 0)
return;
14141 if (xoffset < ebwidth) {
14146 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"has_line", LIVES_INT_TO_POINTER(-1));
14151 if (!mt->is_ready)
return;
14157 static void paint_line(lives_mt * mt, LiVESWidget * eventbox,
int offset,
double currtime,
14158 lives_painter_t *cr) {
14159 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"has_line", LIVES_INT_TO_POINTER(offset));
14164 static void paint_lines(lives_mt * mt,
double currtime,
boolean unpaint, lives_painter_t *cr) {
14168 if (!mt->is_ready)
return;
14174 if (currtime < mt->tl_min || currtime > mt->tl_max)
return;
14175 offset = (currtime - mt->tl_min) / (mt->tl_max - mt->tl_min) * (double)ebwidth;
14180 if (offset > off_x && offset < ebwidth + off_x) {
14181 paint_line(mt, mt->timeline_table, offset, currtime, cr);
14186 static void _animate_multitrack(lives_mt * mt) {
14191 int offset, offset_old;
14194 update_timecodes(mt, currtime);
14196 offset = (currtime - mt->tl_min) / (mt->tl_max - mt->tl_min) * (double)ebwidth;
14198 / (mt->tl_max - mt->tl_min) * (double)ebwidth;
14202 if (offset == offset_old)
return;
14204 if (mt->opts.follow_playback) {
14205 if (currtime > (mt->tl_min + ((tl_page = mt->tl_max - mt->tl_min)) * .85) &&
14208 mt->tl_min += tl_page * .85;
14209 mt->tl_max += tl_page * .85;
14214 if ((offset < 0. && offset_old < 0.) || (offset > (
double)ebwidth && offset_old > (
double)ebwidth))
return;
14217 if (mt->redraw_block)
return;
14219 paint_lines(mt, currtime,
TRUE, NULL);
14230 static boolean multitrack_end(LiVESMenuItem * menuitem, livespointer user_data) {
14231 lives_mt *mt = (lives_mt *)user_data;
14238 lives_mt *mt = (lives_mt *)user_data;
14239 if (mt->is_rendering)
return;
14240 multitrack_end(menuitem, user_data);
14245 lives_mt *mt = (lives_mt *)user_data;
14246 if (mt->is_rendering)
return;
14252 lives_mt *mt = (lives_mt *)user_data;
14253 if (mt->is_rendering)
return;
14254 mt->use_context =
TRUE;
14260 lives_mt *mt = (lives_mt *)user_data;
14261 if (mt->is_rendering)
return;
14267 lives_mt *mt = (lives_mt *)user_data;
14268 if (mt->is_rendering)
return;
14274 lives_mt *mt = (lives_mt *)user_data;
14276 if (mt->file_selected != -1) {
14285 lives_mt *mt = (lives_mt *)user_data;
14286 if (mt->is_rendering)
return;
14292 lives_mt *mt = (lives_mt *)user_data;
14293 if (mt->is_rendering)
return;
14294 mt->use_context =
TRUE;
14300 lives_mt *mt = (lives_mt *)user_data;
14301 if (mt->is_rendering)
return;
14302 on_delblock_activate(NULL, user_data);
14307 lives_mt *mt = (lives_mt *)user_data;
14309 mt->putative_block = NULL;
14314 lives_mt *mt = (lives_mt *)user_data;
14316 mt->context_time = -1.;
14323 static void on_move_fx_changed(LiVESMenuItem * menuitem, livespointer user_data) {
14324 lives_mt *mt = (lives_mt *)user_data;
14325 mt->opts.move_effects = !mt->opts.move_effects;
14329 static void select_all_time(LiVESMenuItem * menuitem, livespointer user_data) {
14330 lives_mt *mt = (lives_mt *)user_data;
14331 mt->region_start = 0.;
14337 static void select_from_zero_time(LiVESMenuItem * menuitem, livespointer user_data) {
14338 lives_mt *mt = (lives_mt *)user_data;
14339 if (mt->region_start == 0. && mt->region_end == 0.) mt->region_end = mt->ptr_time;
14340 mt->region_start = 0.;
14345 static void select_to_end_time(LiVESMenuItem * menuitem, livespointer user_data) {
14346 lives_mt *mt = (lives_mt *)user_data;
14347 if (mt->region_start == 0. && mt->region_end == 0.) mt->region_start = mt->ptr_time;
14353 static void select_all_vid(LiVESMenuItem * menuitem, livespointer user_data) {
14354 lives_mt *mt = (lives_mt *)user_data;
14355 LiVESWidget *eventbox, *checkbutton;
14356 LiVESList *vdr = mt->video_draws;
14358 int current_track = mt->current_track;
14367 eventbox = (LiVESWidget *)vdr->data;
14368 checkbutton = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"checkbutton");
14377 if (!giw_led_get_mode(GIW_LED(checkbutton))) giw_led_set_mode(GIW_LED(checkbutton),
TRUE);
14380 mt->current_track = i++;
14385 mt->current_track = current_track;
14389 static void select_no_vid(LiVESMenuItem * menuitem, livespointer user_data) {
14390 lives_mt *mt = (lives_mt *)user_data;
14391 LiVESWidget *eventbox, *checkbutton;
14392 LiVESList *vdr = mt->video_draws;
14394 int current_track = mt->current_track;
14403 eventbox = (LiVESWidget *)vdr->data;
14404 checkbutton = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"checkbutton");
14413 if (giw_led_get_mode(GIW_LED(checkbutton))) giw_led_set_mode(GIW_LED(checkbutton),
FALSE);
14416 mt->current_track = i++;
14421 mt->current_track = current_track;
14425 static void mt_fplay_toggled(LiVESMenuItem * menuitem, livespointer user_data) {
14426 lives_mt *mt = (lives_mt *)user_data;
14427 mt->opts.follow_playback = !mt->opts.follow_playback;
14432 static void mt_render_vid_toggled(LiVESMenuItem * menuitem, livespointer user_data) {
14433 lives_mt *mt = (lives_mt *)user_data;
14434 mt->opts.render_vidp = !mt->opts.render_vidp;
14439 static void mt_render_aud_toggled(LiVESMenuItem * menuitem, livespointer user_data) {
14440 lives_mt *mt = (lives_mt *)user_data;
14441 mt->opts.render_audp = !mt->opts.render_audp;
14447 static void mt_norm_aud_toggled(LiVESMenuItem * menuitem, livespointer user_data) {
14448 lives_mt *mt = (lives_mt *)user_data;
14449 mt->opts.normalise_audp = !mt->opts.normalise_audp;
14453 static void mt_view_audio_toggled(LiVESMenuItem * menuitem, livespointer user_data) {
14454 lives_mt *mt = (lives_mt *)user_data;
14457 if (!mt->opts.show_audio) lives_widget_object_set_data(LIVES_WIDGET_OBJECT(mt->audio_draws->data),
HIDDEN_KEY,
14459 else lives_widget_object_set_data(LIVES_WIDGET_OBJECT(mt->audio_draws->data),
HIDDEN_KEY, LIVES_INT_TO_POINTER(0));
14466 static void mt_ign_ins_sel_toggled(LiVESMenuItem * menuitem, livespointer user_data) {
14467 lives_mt *mt = (lives_mt *)user_data;
14472 static void remove_gaps_inner(LiVESMenuItem * menuitem, livespointer user_data,
boolean only_first) {
14473 lives_mt *mt = (lives_mt *)user_data;
14475 weed_timecode_t offset = 0;
14476 weed_timecode_t tc, new_tc, tc_last, new_tc_last, tc_first, block_tc;
14478 LiVESList *vsel = mt->selected_tracks;
14479 LiVESList *track_sel;
14481 LiVESWidget *eventbox;
14483 track_rect *block = NULL;
14485 boolean did_backup = mt->did_backup;
14486 boolean audio_done =
FALSE;
14487 boolean needs_idlefunc =
FALSE;
14492 if (mt->idlefunc > 0) {
14493 needs_idlefunc =
TRUE;
14504 while (vsel || (mt->current_track == -1 && !audio_done)) {
14506 if (mt->current_track > -1) {
14507 track = LIVES_POINTER_TO_INT(vsel->data);
14508 eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, track);
14511 eventbox = (LiVESWidget *)mt->audio_draws->data;
14521 if (new_tc > tc) tc = new_tc;
14529 if (new_tc_last < tc_last) tc_last = new_tc_last;
14547 while (tc <= tc_last) {
14552 if (new_tc > tc_last)
break;
14556 if (offset > 0) tc =
q_gint64(new_tc - offset, mt->fps);
14563 track_sel = mt->selected_tracks;
14564 mt->selected_tracks = NULL;
14566 if (mt->selected_tracks) lives_list_free(mt->selected_tracks);
14567 mt->selected_tracks = track_sel;
14568 if (only_first && offset == 0) offset = new_tc - tc;
14572 if (mt->current_track > -1) vsel = vsel->next;
14573 else audio_done =
TRUE;
14583 while (tc >= tc_first) {
14588 if (new_tc < tc_first)
break;
14595 if (offset > 0) tc =
q_gint64(new_tc - block_tc + offset, mt->fps);
14596 else tc =
q_gint64(tc - block_tc, mt->fps);
14603 track_sel = mt->selected_tracks;
14604 mt->selected_tracks = NULL;
14606 if (mt->selected_tracks) lives_list_free(mt->selected_tracks);
14607 mt->selected_tracks = track_sel;
14608 if (only_first && offset == 0) offset = tc - new_tc + block_tc;
14612 if (mt->current_track > -1) vsel = vsel->next;
14613 else audio_done =
TRUE;
14618 if (mt->avol_fx != -1 && (!block || !block->next) && mt->audio_draws
14620 apply_avol_filter(mt);
14624 mt->did_backup = did_backup;
14625 if (!did_backup && mt->framedraw && mt->current_rfx && mt->init_event
14629 get_track_index(mt, tc);
14633 mt->did_backup =
FALSE;
14634 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
14644 remove_gaps_inner(menuitem, user_data,
TRUE);
14649 remove_gaps_inner(menuitem, user_data,
FALSE);
14653 static void split_block(lives_mt * mt, track_rect * block, weed_timecode_t tc,
int track,
boolean no_recurse) {
14654 weed_plant_t *
event = block->start_event;
14655 weed_plant_t *start_event = event;
14656 weed_plant_t *old_end_event = block->end_event;
14657 int frame = 0, clip;
14658 LiVESWidget *eventbox;
14659 track_rect *new_block;
14660 weed_timecode_t offset_start;
14661 double seek, new_seek, vel;
14665 if (!block)
return;
14667 mt->no_expose =
TRUE;
14674 eventbox = block->eventbox;
14676 if (!is_audio_eventbox(eventbox)) {
14679 LiVESWidget *aeventbox = LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"atrack"));
14681 track_rect *ablock = get_block_from_time(aeventbox, tc /
TICKS_PER_SECOND_DBL + 1. / mt->fps, mt);
14690 LiVESWidget *oeventbox = LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"owner"));
14691 if (oeventbox) split_block(mt, get_block_from_time(oeventbox, tc /
TICKS_PER_SECOND_DBL - 1. / mt->fps, mt),
14697 event = block->end_event;
14703 if (block->ordered ||
14704 (is_audio_eventbox(eventbox))) offset_start = block->offset_start -
get_event_timecode(start_event)
14708 new_block = add_block_start_point(LIVES_WIDGET(eventbox), tc, clip, offset_start, event, block->ordered);
14709 new_block->end_event = old_end_event;
14711 mt->no_expose =
FALSE;
14713 redraw_eventbox(mt, eventbox);
14714 paint_lines(mt, mt->ptr_time,
TRUE, NULL);
14718 static void insgap_inner(lives_mt * mt,
int tnum,
boolean is_sel,
int passnm) {
14733 track_rect *sblock, *block, *ablock = NULL;
14734 LiVESWidget *eventbox;
14736 weed_plant_t *event, *new_event = NULL, *last_frame_event;
14737 weed_plant_t *init_event;
14738 weed_timecode_t tc, new_tc;
14739 weed_timecode_t start_tc, new_init_tc, init_tc;
14740 double aseek = 0., avel = 0., *audio_seeks;
14743 int clip, *clips, *new_clips;
14744 int64_t frame, *frames, *new_frames;
14745 int xnumclips, numclips, naclips;
14746 int aclip = 0, *audio_clips;
14747 int nintracks, *in_tracks;
14754 if (tnum >= 0) eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, tnum);
14755 else eventbox = (LiVESWidget *)mt->audio_draws->data;
14756 tc =
q_dbl(mt->region_start, mt->fps);
14757 sblock = get_block_from_time(eventbox, mt->region_start, mt);
14760 split_block(mt, sblock, tc, tnum,
FALSE);
14761 sblock = sblock->next;
14763 sblock = get_block_after(eventbox, mt->region_start,
FALSE);
14766 if (!sblock)
return;
14769 while (block->next) block = block->next;
14770 event = block->end_event;
14772 if (tnum >= 0 && mt->opts.pertrack_audio) {
14773 LiVESWidget *aeventbox = LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"atrack"));
14775 ablock = get_block_after(aeventbox, mt->region_start,
FALSE);
14777 while (ablock->next) ablock = ablock->next;
14778 event = ablock->end_event;
14801 clips = weed_get_int_array_counted(new_event,
WEED_LEAF_CLIPS, &numclips);
14802 xnumclips = numclips;
14803 if (numclips < tnum + 1) xnumclips = tnum + 1;
14810 for (i = 0; i < xnumclips; i++) {
14812 new_clips[i] = clip;
14813 new_frames[i] = frame;
14815 if (i < numclips) {
14816 new_clips[i] = clips[i];
14817 new_frames[i] = frames[i];
14825 weed_set_int_array(new_event,
WEED_LEAF_CLIPS, xnumclips, new_clips);
14844 for (i = 0; i < naclips; i += 2) {
14845 if (audio_clips[i] == tnum) {
14846 aclip = audio_clips[i + 1];
14847 aseek = audio_seeks[i];
14848 avel = audio_seeks[i + 1];
14858 if (mt->avol_fx != -1) {
14859 apply_avol_filter(mt);
14864 if (new_event != event) {
14867 if (event == ablock->end_event) ablock->end_event = new_event;
14868 else if (event == ablock->start_event) {
14869 ablock->start_event = new_event;
14873 if (event == block->end_event) block->end_event = new_event;
14874 else if (event == block->start_event) {
14875 block->start_event = new_event;
14876 if (block == sblock) {
14877 if (tnum < 0 || ablock) {
14878 if (ablock) block = ablock;
14879 if (block->prev && block->prev->end_event == event) {
14883 if (mt->avol_fx != -1) {
14884 apply_avol_filter(mt);
14888 redraw_eventbox(mt, eventbox);
14889 paint_lines(mt, mt->ptr_time,
TRUE, NULL);
14892 block = block->prev;
14894 if (ablock && ablock->start_event == new_event) {
14895 ablock = ablock->prev;
14896 if (ablock && event == ablock->end_event) ablock->end_event = new_event;
14903 if (new_event == block->end_event)
event = block->start_event;
14904 else event = block->end_event;
14919 if (init_event == mt->avol_init_event) {
14928 if ((nintracks == 1 && in_tracks[0] != mt->current_track) || (nintracks == 2 && in_tracks[0] != mt->current_track &&
14929 in_tracks[1] != mt->current_track)) {
14934 for (i = 0; i < nintracks; i++) {
14935 slist = mt->selected_tracks;
14938 while (slist && !found) {
14939 if (LIVES_POINTER_TO_INT(slist->data) == in_tracks[i]) found =
TRUE;
14940 slist = slist->next;
14943 if (nintracks != 2 || notmatched > 0)
return;
14957 if (init_tc >= start_tc) {
14965 if (nintracks == 2) {
14967 if (init_tc >= start_tc && init_event != mt->avol_init_event)
14976 if (end_secs > mt->end_secs) {
14984 lives_mt *mt = (lives_mt *)user_data;
14985 LiVESList *slist = mt->selected_tracks;
14986 char *tstart, *tend;
14987 boolean did_backup = mt->did_backup;
14988 boolean needs_idlefunc =
FALSE;
14992 if (mt->idlefunc > 0) {
14993 needs_idlefunc =
TRUE;
15001 track = LIVES_POINTER_TO_INT(slist->data);
15002 insgap_inner(mt, track,
TRUE, 1);
15003 slist = slist->next;
15006 if (mt->opts.move_effects) {
15007 insgap_inner(mt, 0,
TRUE, 2);
15010 mt->did_backup = did_backup;
15013 tstart = time_to_string(
QUANT_TIME(mt->region_start));
15014 tend = time_to_string(
QUANT_TIME(mt->region_end));
15016 d_print(
_(
"Inserted gap in selected tracks from time %s to time %s\n"), tstart, tend);
15022 mt->did_backup =
FALSE;
15023 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
15030 lives_mt *mt = (lives_mt *)user_data;
15032 boolean did_backup = mt->did_backup;
15033 boolean needs_idlefunc =
FALSE;
15035 char *tstart, *tend;
15038 if (mt->idlefunc > 0) {
15039 needs_idlefunc =
TRUE;
15046 insgap_inner(mt, mt->current_track,
FALSE, 1);
15048 if (mt->opts.move_effects) {
15049 insgap_inner(mt, mt->current_track,
FALSE, 2);
15052 mt->did_backup = did_backup;
15055 tstart = time_to_string(
QUANT_TIME(mt->region_start));
15056 tend = time_to_string(
QUANT_TIME(mt->region_end));
15059 d_print(
_(
"Inserted gap in track %s from time %s to time %s\n"), tname, tstart, tend);
15066 mt->did_backup =
FALSE;
15067 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
15074 lives_mt *mt = (lives_mt *)user_data;
15076 mt_undo *last_undo = (
mt_undo *)lives_list_nth_data(mt->undos, lives_list_length(mt->undos) - 1 - mt->undo_offset);
15080 LiVESList *label_list = NULL;
15081 LiVESList *vlist, *llist;
15082 LiVESList *seltracks = NULL;
15083 LiVESList *aparam_view_list;
15085 LiVESWidget *checkbutton, *eventbox, *label;
15087 unsigned char *memblock, *omemblock, *mem_end;
15089 size_t space_avail = (size_t)(
prefs->
mt_undo_buf * 1024 * 1024) - mt->undo_buffer_used;
15090 size_t space_needed;
15098 boolean block_is_selected =
FALSE;
15099 boolean avoid_fx_list =
FALSE;
15108 if (!mt->undo_mem)
return;
15110 if (mt->idlefunc > 0) {
15117 mt->was_undo_redo =
TRUE;
15118 ptr_time = mt->ptr_time;
15120 if (mt->block_selected) block_is_selected =
TRUE;
15123 if (mt->undo_offset == 0) {
15125 if ((space_needed = estimate_space(mt, last_undo->
action) +
sizeof(
mt_undo)) > space_avail) {
15135 new_redo = (
mt_undo *)(mt->undo_mem + mt->undo_buffer_used);
15138 omemblock = memblock = (
unsigned char *)new_redo +
sizeof(
mt_undo);
15140 new_redo->
data_len = memblock - omemblock;
15142 mt->undo_buffer_used += space_needed;
15143 mt->undos = lives_list_append(mt->undos, new_redo);
15147 current_track = mt->current_track;
15148 end_secs = mt->end_secs;
15149 num_tracks = mt->num_video_tracks;
15150 clip_sel = mt->clip_selected;
15152 seltracks = lives_list_copy(mt->selected_tracks);
15154 vlist = mt->video_draws;
15156 eventbox = LIVES_WIDGET(vlist->data);
15157 label = LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"label"));
15159 label_list = lives_list_append(label_list, txt);
15160 vlist = vlist->next;
15163 aparam_view_list = lives_list_copy(mt->opts.aparam_view_list);
15164 avol_fx = mt->avol_fx;
15167 mt->no_expose =
TRUE;
15170 last_undo = (
mt_undo *)lives_list_nth_data(mt->undos, lives_list_length(mt->undos) - 1 - mt->undo_offset);
15171 memblock = (
unsigned char *)(last_undo) +
sizeof(
mt_undo);
15173 mt->event_list = load_event_list_inner(mt, -1,
FALSE, NULL, &memblock, mem_end);
15177 mt->event_list = NULL;
15182 mt->event_list = NULL;
15185 for (i = 0; i < mt->num_video_tracks; i++) {
15188 lives_list_free(mt->video_draws);
15189 mt->video_draws = NULL;
15190 mt->num_video_tracks = 0;
15193 mt->audio_draws = NULL;
15195 mt->fm_edit_event = NULL;
15196 mt->init_event = NULL;
15197 mt->selected_init_event = NULL;
15198 mt->specific_event = NULL;
15199 mt->avol_init_event = NULL;
15203 if (mt->avol_fx == -1) mt->avol_fx = avol_fx;
15204 if (mt->avol_fx != -1) mt->opts.aparam_view_list = lives_list_copy(aparam_view_list);
15205 if (aparam_view_list) lives_list_free(aparam_view_list);
15210 for (i = mt->num_video_tracks; i < num_tracks; i++) {
15214 mt->clip_selected = clip_sel;
15217 vlist = mt->video_draws;
15218 llist = label_list;
15220 eventbox = LIVES_WIDGET(vlist->data);
15221 label = LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"label"));
15225 vlist = vlist->next;
15226 llist = llist->next;
15228 lives_list_free(label_list);
15232 mt->selected_tracks = lives_list_copy(seltracks);
15233 slist = mt->selected_tracks;
15235 eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, LIVES_POINTER_TO_INT(slist->data));
15236 checkbutton = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"checkbutton");
15243 giw_led_set_mode(GIW_LED(checkbutton),
TRUE);
15246 slist = slist->next;
15248 if (seltracks) lives_list_free(seltracks);
15250 mt->current_track = current_track;
15255 mt->no_expose =
FALSE;
15259 if (mt->undo_offset == lives_list_length(mt->undos)) mt_set_undoable(mt,
MT_UNDO_NONE, NULL,
FALSE);
15261 mt_undo *undo = (
mt_undo *)(lives_list_nth_data(mt->undos, lives_list_length(mt->undos) - mt->undo_offset - 1));
15268 utxt = lives_utf8_strdown((tmp = get_undo_text(last_undo->
action, last_undo->
extra)), -1);
15274 if (last_undo->
action <= 1024 && block_is_selected) mt_selblock(LIVES_MENU_ITEM(mt->seldesel_menuitem), (livespointer)mt);
15280 avoid_fx_list =
TRUE;
15299 lives_mt *mt = (lives_mt *)user_data;
15301 mt_undo *last_redo = (
mt_undo *)lives_list_nth_data(mt->undos, lives_list_length(mt->undos) + 1 - mt->undo_offset);
15303 LiVESWidget *checkbutton, *eventbox, *label;
15306 LiVESList *label_list = NULL;
15307 LiVESList *vlist, *llist;
15308 LiVESList *seltracks = NULL;
15309 LiVESList *aparam_view_list;
15311 unsigned char *memblock, *mem_end;
15326 if (!mt->undo_mem)
return;
15328 if (mt->idlefunc > 0) {
15337 mt->was_undo_redo =
TRUE;
15338 ptr_time = mt->ptr_time;
15341 current_track = mt->current_track;
15342 end_secs = mt->end_secs;
15343 num_tracks = mt->num_video_tracks;
15344 clip_sel = mt->clip_selected;
15346 seltracks = lives_list_copy(mt->selected_tracks);
15348 vlist = mt->video_draws;
15350 eventbox = LIVES_WIDGET(vlist->data);
15351 label = LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"label"));
15353 label_list = lives_list_append(label_list, txt);
15354 vlist = vlist->next;
15357 aparam_view_list = lives_list_copy(mt->opts.aparam_view_list);
15358 avol_fx = mt->avol_fx;
15361 mt->no_expose =
TRUE;
15365 memblock = (
unsigned char *)(last_redo) +
sizeof(
mt_undo);
15367 mt->event_list = load_event_list_inner(mt, -1,
FALSE, NULL, &memblock, mem_end);
15370 mt->event_list = NULL;
15375 mt->event_list = NULL;
15378 for (i = 0; i < mt->num_video_tracks; i++) {
15381 lives_list_free(mt->video_draws);
15382 mt->video_draws = NULL;
15383 mt->num_video_tracks = 0;
15386 mt->audio_draws = NULL;
15388 mt->fm_edit_event = NULL;
15389 mt->init_event = NULL;
15390 mt->selected_init_event = NULL;
15391 mt->specific_event = NULL;
15392 mt->avol_init_event = NULL;
15396 if (mt->avol_fx == avol_fx) {
15397 mt->opts.aparam_view_list = lives_list_copy(aparam_view_list);
15399 if (aparam_view_list) lives_list_free(aparam_view_list);
15404 for (i = mt->num_video_tracks; i < num_tracks; i++) {
15408 mt->clip_selected = clip_sel;
15411 vlist = mt->video_draws;
15412 llist = label_list;
15414 eventbox = LIVES_WIDGET(vlist->data);
15415 label = LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"label"));
15419 vlist = vlist->next;
15420 llist = llist->next;
15422 lives_list_free(label_list);
15426 mt->selected_tracks = lives_list_copy(seltracks);
15427 slist = mt->selected_tracks;
15429 eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, LIVES_POINTER_TO_INT(slist->data));
15430 checkbutton = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"checkbutton");
15437 giw_led_set_mode(GIW_LED(checkbutton),
TRUE);
15440 slist = slist->next;
15442 if (seltracks) lives_list_free(seltracks);
15444 mt->current_track = current_track;
15449 mt->no_expose =
FALSE;
15455 mt_undo *redo = (
mt_undo *)(lives_list_nth_data(mt->undos, lives_list_length(mt->undos) - mt->undo_offset));
15458 last_redo = (
mt_undo *)lives_list_nth_data(mt->undos, lives_list_length(mt->undos) - 1 - mt->undo_offset);
15473 utxt = lives_utf8_strdown((tmp = get_undo_text(last_redo->
action, last_redo->
extra)), -1);
15492 lives_mt *mt = (lives_mt *)user_data;
15494 uint32_t bsize = 0;
15496 int num_events = 0;
15501 lives_snprintf(buff, 512,
"\n Event List");
15506 lives_snprintf(buff, 512,
"\n %.3f%s", mt->fps, rfile->
ratio_fps ?
"..." :
"");
15508 lives_snprintf(buff, 512,
"%s",
_(
"\n (variable)"));
15514 lives_snprintf(buff, 512,
"\n %dx%d", rfile->
hsize, rfile->
vsize);
15517 if (mt->event_list) {
15518 bsize = event_list_get_byte_size(mt, mt->event_list,
TRUE, &num_events);
15522 lives_snprintf(buff, 512,
"\n %d", (
frames_t)(mt->fps * time));
15525 lives_snprintf(buff, 512,
_(
"\n %.3f sec"), time);
15529 lives_snprintf(buff, 512,
_(
"\n %d bytes\n%d events"), bsize, num_events);
15544 static void add_effect_inner(lives_mt * mt,
int num_in_tracks,
int *in_tracks,
int num_out_tracks,
int *out_tracks,
15545 weed_plant_t *start_event, weed_plant_t *end_event) {
15546 void **init_events;
15551 double timesecs = mt->ptr_time;
15559 boolean has_params;
15562 mt->track_index = -1;
15563 for (
int i = 0; i < num_in_tracks; i++) {
15564 if (mt->current_track == in_tracks[i]) {
15565 mt->track_index = i;
15622 if (mt->current_fx == mt->avol_fx)
return;
15624 if (mt->avol_fx != -1) {
15625 apply_avol_filter(mt);
15628 if (mt->is_atrans)
return;
15630 get_track_index(mt, tc);
15632 if (mt->track_index > -1) {
15653 weed_timecode_t tc;
15654 weed_plant_t *shortcut = NULL;
15655 weed_timecode_t tl =
q_dbl(1. / fps, fps);
15656 int blank_clip = -1;
15657 int64_t blank_frame = 0;
15662 for (; tc <= end_tc; tc =
q_gint64(tc + tl, fps)) {
15665 weed_set_double_value(event_list, WEED_LEAF_FPS, fps);
15671 lives_mt *mt = (lives_mt *)user_data;
15675 weed_plant_t *start_event;
15676 weed_plant_t *end_event;
15677 weed_plant_t *last_frame_event = NULL;
15681 weed_timecode_t last_frame_tc = 0;
15684 char *tname, *track_desc;
15686 char *tstart, *tend;
15688 boolean did_backup = mt->did_backup;
15689 boolean needs_idlefunc =
FALSE;
15691 int numtracks = lives_list_length(mt->selected_tracks);
15692 int tcount = 0, tlast = -1000000, tsmall = -1, ctrack;
15696 if (mt->idlefunc > 0) {
15697 needs_idlefunc =
TRUE;
15703 while (tcount < numtracks) {
15705 llist = mt->selected_tracks;
15707 ctrack = LIVES_POINTER_TO_INT(llist->data);
15708 if ((tsmall == -1000000 || ctrack < tsmall) && ctrack > tlast) tsmall = ctrack;
15709 llist = llist->next;
15711 tracks[tcount++] = tlast = tsmall;
15715 if (mt->event_list &&
15721 if (menuitem) mt->current_fx = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(menuitem),
"idx"));
15726 add_effect_inner(mt, numtracks, tracks, 1, &tracks[0], start_event, end_event);
15728 if (!menuitem && !mt->is_atrans) {
15730 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
15741 switch (numtracks) {
15756 track_desc = (
_(
"selected tracks"));
15764 d_print(
_(
"Added %s %s to %s from time %s to time %s\n"), tname, filter_name, track_desc, tstart, tend);
15773 mt->did_backup =
FALSE;
15774 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
15780 static boolean mt_add_region_effect_idle(livespointer user_data) {
15788 lives_mt *mt = (lives_mt *)user_data;
15789 weed_plant_t *start_event = mt->block_selected->start_event;
15790 weed_plant_t *end_event = mt->block_selected->end_event;
15794 char *tstart, *tend;
15796 int selected_track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mt->block_selected->eventbox),
15798 boolean did_backup = mt->did_backup;
15799 boolean needs_idlefunc =
FALSE;
15801 if (mt->idlefunc > 0) {
15802 needs_idlefunc =
TRUE;
15807 if (menuitem) mt->current_fx
15808 = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(menuitem),
"idx"));
15811 add_effect_inner(mt, 1, &selected_track, 1, &selected_track, start_event, end_event);
15818 d_print(
_(
"Added effect %s to track %s from time %s to time %s\n"), filter_name,
15819 (tmp =
get_track_name(mt, selected_track, mt->aud_track_selected)),
15828 mt->did_backup =
FALSE;
15829 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
15835 static boolean mt_add_block_effect_idle(livespointer user_data) {
15844 lives_mt *mt = (lives_mt *)user_data;
15850 lives_mt *mt = (lives_mt *)user_data;
15852 weed_timecode_t start_tc, end_tc;
15854 weed_plant_t *deinit_event, *init_event = mt->selected_init_event;
15858 char *fhash, *filter_name;
15859 char *tname, *track_desc;
15861 char *tstart, *tend;
15863 boolean did_backup = mt->did_backup;
15864 boolean needs_idlefunc =
FALSE;
15868 if (!mt->selected_init_event)
return;
15870 if (mt->is_rendering)
return;
15872 if (mt->idlefunc > 0) {
15873 needs_idlefunc =
TRUE;
15890 switch (numtracks) {
15905 track_desc = (
_(
"selected tracks"));
15919 d_print(
_(
"Deleted %s %s from %s from time %s to time %s\n"), tname, filter_name, track_desc, tstart, tend);
15926 mt->selected_init_event = NULL;
15927 mt->current_fx = -1;
15933 mt->did_backup =
FALSE;
15934 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
15944 weed_timecode_t start_tc, end_tc;
15946 LiVESWidget *eventbox;
15951 if (mt->current_track > -1 &&
15952 !mt->aud_track_selected) eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, mt->current_track);
15954 eventbox = (LiVESWidget *)lives_list_nth_data(mt->audio_draws, mt->current_track + mt->opts.back_audio_tracks);
15957 block = get_block_from_time(eventbox, secs, mt);
15962 secs -= 1. / mt->fps;
15967 secs += 1. / mt->fps;
15974 block = get_block_before(eventbox, secs,
TRUE);
15975 if (!block) secs = 0.;
15982 block = get_block_after(eventbox, secs,
FALSE);
15983 if (!block)
return;
15988 if (secs < 0.) secs = 0.;
15990 mt->fm_edit_event = NULL;
15996 lives_mt *mt = (lives_mt *)user_data;
16002 lives_mt *mt = (lives_mt *)user_data;
16008 LiVESList *tl_marks = mt->tl_marks;
16009 double time = -1., marktime = -1.;
16014 if (time > ptr_time)
break;
16015 if (marktime == time)
continue;
16017 tl_marks = tl_marks->next;
16026 lives_mt *mt = (lives_mt *)user_data;
16032 lives_mt *mt = (lives_mt *)user_data;
16038 lives_mt *mt = (lives_mt *)user_data;
16040 LiVESWidget *xeventbox;
16046 if (mt->current_track < 0)
return;
16048 xeventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, mt->current_track);
16050 cname = (
char *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xeventbox),
"track_name");
16056 if (response == LIVES_RESPONSE_CANCEL)
return;
16067 set_track_label(LIVES_EVENT_BOX(xeventbox), mt->current_track);
16072 lives_mt *mt = (lives_mt *)user_data;
16073 mt->current_track = -1;
16079 lives_mt *mt = (lives_mt *)user_data;
16083 boolean had_audio =
FALSE;
16084 boolean post_reset_ba =
FALSE;
16085 boolean post_reset_ca =
FALSE;
16086 boolean retval =
FALSE;
16098 if (mt->idlefunc > 0) {
16105 mt->pr_audio =
TRUE;
16106 had_audio = mt->has_audio_file;
16117 mt->has_audio_file =
TRUE;
16119 mt->pr_audio =
FALSE;
16128 mt->is_rendering =
TRUE;
16137 if (mt->opts.normalise_audp) {
16144 boolean has_backing_audio =
FALSE;
16145 boolean has_channel_audio =
FALSE;
16148 list = mt->audio_draws;
16149 if (mt->opts.back_audio_tracks >= 1) {
16151 for (i = 0; i < mt->opts.back_audio_tracks; list = list->next, i++) {
16154 has_backing_audio =
TRUE;
16159 list = mt->audio_draws;
16160 for (i = mt->opts.back_audio_tracks + 1; --i > 0; list = list->next);
16161 for (; list; list = list->next, i++) {
16165 has_channel_audio =
TRUE;
16172 if (has_backing_audio && !has_channel_audio) {
16177 list = mt->audio_draws;
16178 for (i = 0; i < mt->opts.back_audio_tracks; i++, list = list->next) {
16181 has_backing_audio =
FALSE;
16187 if (has_backing_audio) {
16188 post_reset_ba =
TRUE;
16189 list = mt->audio_draws;
16190 for (i = 0; i < mt->opts.back_audio_tracks; i++, list = list->next) {
16197 if (!has_backing_audio && has_channel_audio) {
16202 list = mt->audio_draws;
16203 for (i = mt->opts.back_audio_tracks + 1; --i > 0; list = list->next);
16207 has_channel_audio =
FALSE;
16212 if (has_channel_audio) {
16213 post_reset_ca =
TRUE;
16214 list = mt->audio_draws;
16215 for (i = 0; i < mt->opts.back_audio_tracks; i++, list = list->next);
16217 for (; list; list = list->next) {
16229 if (mt->pr_audio) {
16230 mt->pr_audio =
FALSE;
16250 mt->is_rendering =
FALSE;
16257 if (post_reset_ba) {
16259 for (i = 0; i < mt->opts.back_audio_tracks; i++) {
16260 if (!
is_empty_track(LIVES_WIDGET_OBJECT(lives_list_nth_data(mt->audio_draws, i)))) {
16267 if (post_reset_ca) {
16269 list = mt->audio_draws;
16270 for (i = 0; i < mt->opts.back_audio_tracks; i++, list = list->next);
16272 for (; list; list = list->next) {
16297 cfile->arate = arate;
16298 cfile->arps = arps;
16299 cfile->asampsize = asampsize;
16301 cfile->achans = achans;
16302 cfile->signed_endian = signed_endian;
16313 if (multitrack_end(menuitem, user_data))
return TRUE;
16328 mt->is_rendering =
FALSE;
16331 if (mt->pr_audio) {
16335 mt->has_audio_file = had_audio;
16359 lives_mt *mt = (lives_mt *)user_data;
16368 int track, weed_timecode_t new_start_tc,
int new_track) {
16392 LiVESList *moved_events = NULL;
16394 weed_plant_t *event, *event_next;
16395 weed_plant_t *init_event, *deinit_event;
16397 weed_timecode_t last_frame_tc = 0, event_tc;
16400 boolean leave_event;
16421 if (event == mt->avol_init_event) {
16422 event = event_next;
16425 if (mt->opts.move_effects && mt->moving_block) {
16436 if (lives_list_index(moved_events, event) == -1) {
16443 for (i = 0; i < num_tracks; i++) {
16445 if (out_tracks[i] == track) out_tracks[i] = new_track;
16452 if (new_start_tc < start_tc) {
16457 deinit_event, mt->fps,
TRUE);
16458 if (event == first_event) first_event = NULL;
16460 }
else if (new_start_tc > start_tc) {
16464 deinit_event, mt->fps,
TRUE);
16466 if (event == first_event) first_event = NULL;
16470 moved_events = lives_list_prepend(moved_events, event);
16475 if (lives_list_index(moved_events, event) == -1 && event != mt->avol_init_event) {
16479 if (in_tracks[0] == track || (nins == 2 && in_tracks[1] == track)) {
16490 if (event == first_event) first_event = NULL;
16496 if (event == first_event) first_event = NULL;
16504 leave_event =
TRUE;
16507 if (mt->opts.move_effects && mt->moving_block) {
16511 if (init_event != mt->avol_init_event &&
16512 (event_tc > last_frame_tc ||
16513 (lives_list_index(moved_events, init_event) == -1 &&
16518 if (event_tc <= last_frame_tc) {
16520 if (in_tracks[0] == track || (nins == 2 && in_tracks[1] == track)) {
16521 leave_event =
FALSE;
16524 }
else leave_event =
FALSE;
16544 event = event_next;
16548 if (moved_events) lives_list_free(moved_events);
16554 lives_mt *mt = (lives_mt *)user_data;
16556 weed_timecode_t tc;
16558 double timesecs = mt->ptr_time;
16560 boolean did_backup = mt->did_backup;
16561 boolean needs_idlefunc =
FALSE;
16563 if (!mt->putative_block)
return;
16565 if (mt->idlefunc > 0) {
16566 needs_idlefunc =
TRUE;
16571 if (mt->context_time != -1. && mt->use_context) {
16572 timesecs = mt->context_time;
16573 mt->context_time = -1.;
16574 mt->use_context =
FALSE;
16581 split_block(mt, mt->putative_block, tc, mt->current_track,
FALSE);
16584 mt->did_backup =
FALSE;
16585 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
16593 lives_mt *mt = (lives_mt *)user_data;
16594 double timesecs = mt->ptr_time;
16595 boolean did_backup = mt->did_backup;
16596 boolean needs_idlefunc =
FALSE;
16597 weed_timecode_t tc;
16598 LiVESWidget *eventbox;
16601 if (mt->idlefunc > 0) {
16602 needs_idlefunc =
TRUE;
16609 if (mt->current_track == -1) eventbox = (LiVESWidget *)mt->audio_draws->data;
16610 else eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, mt->current_track);
16612 block = get_block_from_time(eventbox, timesecs, mt);
16616 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
16622 split_block(mt, block, tc, mt->current_track,
FALSE);
16625 mt->did_backup =
FALSE;
16626 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
16634 lives_mt *mt = (lives_mt *)user_data;
16635 LiVESList *selt = mt->selected_tracks;
16636 LiVESWidget *eventbox;
16639 double timesecs = mt->ptr_time;
16640 boolean did_backup = mt->did_backup;
16641 boolean needs_idlefunc =
FALSE;
16643 if (!mt->selected_tracks)
return;
16645 if (mt->idlefunc > 0) {
16646 needs_idlefunc =
TRUE;
16654 track = LIVES_POINTER_TO_INT(selt->data);
16655 eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, track);
16656 block = get_block_from_time(eventbox, timesecs, mt);
16662 mt->did_backup =
FALSE;
16663 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
16669 static void on_delblock_activate(LiVESMenuItem * menuitem, livespointer user_data) {
16670 lives_mt *mt = (lives_mt *)user_data;
16671 weed_timecode_t start_tc, end_tc;
16672 weed_plant_t *first_event;
16673 weed_plant_t *event, *prevevent;
16675 track_rect *block, *blockprev, *blocknext;
16677 LiVESWidget *eventbox, *aeventbox;
16680 char *tstart, *tend;
16682 boolean done =
FALSE;
16683 boolean did_backup = mt->did_backup;
16684 boolean needs_idlefunc =
FALSE;
16688 if (mt->is_rendering)
return;
16690 if (mt->idlefunc > 0) {
16691 needs_idlefunc =
TRUE;
16696 mt->context_time = -1.;
16701 if (!mt->block_selected) mt->block_selected = mt->putative_block;
16702 block = mt->block_selected;
16703 eventbox = block->eventbox;
16705 if (mt->current_track != -1) track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
16709 if ((aeventbox = LIVES_WIDGET(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"atrack"))) != NULL) {
16710 int current_track = mt->current_track;
16711 mt->current_track = track;
16713 if (mt->block_selected) on_delblock_activate(NULL, user_data);
16714 mt->block_selected = block;
16715 mt->current_track = current_track;
16728 event = block->end_event;
16730 if (mt->current_track != -1 && !is_audio_eventbox(eventbox)) {
16732 while (event && !done) {
16734 if (event == block->start_event) done =
TRUE;
16736 if (!done)
event = prevevent;
16746 if (block->prev && block->start_event == block->prev->end_event) {
16755 if ((blockprev = block->prev) != NULL) blockprev->next = block->next;
16756 else lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks", (livespointer)block->next);
16757 if ((blocknext = block->next) != NULL) blocknext->prev = blockprev;
16759 if (block == mt->block_selected) mt->block_selected = NULL;
16763 if (
cfile->achans > 0 && mt->audio_draws && mt->opts.back_audio_tracks > 0 && eventbox == mt->audio_draws->data &&
16764 LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"expanded"))) {
16765 LiVESWidget *xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"achan0");
16767 xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"achan1");
16776 if (mt->current_track != -1 && !is_audio_eventbox(eventbox)) {
16777 d_print(
_(
"Deleted frames from time %s to time %s on track %s\n"), tstart, tend, tmp);
16779 d_print(
_(
"Deleted audio from time %s to time %s on track %s\n"), tstart, tend, tmp);
16789 double oldr_start = mt->region_start;
16790 double oldr_end = mt->region_end;
16791 LiVESList *tracks_sel = NULL;
16792 if (mt->current_track != -1) {
16793 tracks_sel = lives_list_copy(mt->selected_tracks);
16794 if (mt->selected_tracks) lives_list_free(mt->selected_tracks);
16795 mt->selected_tracks = NULL;
16796 mt->selected_tracks = lives_list_append(mt->selected_tracks, LIVES_INT_TO_POINTER(mt->current_track));
16801 mt->region_end = mt->end_secs;
16803 mt->region_start = 0.;
16808 if (mt->current_track > -1) {
16809 lives_list_free(mt->selected_tracks);
16810 mt->selected_tracks = lives_list_copy(tracks_sel);
16811 if (tracks_sel) lives_list_free(tracks_sel);
16813 mt->region_start = oldr_start;
16814 mt->region_end = oldr_end;
16820 if (!mt->opts.move_effects || !mt->moving_block) {
16822 if (mt->block_selected == block) {
16823 mt->block_selected = NULL;
16831 if ((!mt->moving_block || !
get_first_frame_event(mt->event_list)) && mt->avol_fx != -1 && !blocknext &&
16833 apply_avol_filter(mt);
16836 if (!did_backup && mt->framedraw && mt->current_rfx && mt->init_event &&
16840 get_track_index(mt, tc);
16843 if (!mt->moving_block) {
16844 redraw_eventbox(mt, eventbox);
16845 paint_lines(mt, mt->ptr_time,
TRUE, NULL);
16850 mt->did_backup =
FALSE;
16851 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
16855 if (!mt->moving_block) {
16864 lives_mt *mt = (lives_mt *)user_data;
16872 lives_mt *mt = (lives_mt *)user_data;
16873 LiVESWidget *eventbox;
16874 LiVESWidget *checkbutton;
16880 if (mt->current_track == -1)
return;
16882 eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, mt->current_track);
16883 checkbutton = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"checkbutton");
16889 if (lives_list_index(mt->selected_tracks, LIVES_INT_TO_POINTER(mt->current_track)) == -1)
16890 mt->selected_tracks = lives_list_append(mt->selected_tracks, LIVES_INT_TO_POINTER(mt->current_track));
16893 if (lives_list_index(mt->selected_tracks, LIVES_INT_TO_POINTER(mt->current_track)) != -1)
16894 mt->selected_tracks = lives_list_remove(mt->selected_tracks, LIVES_INT_TO_POINTER(mt->current_track));
16907 if (giw_led_get_mode(GIW_LED(checkbutton)) != mi_state) {
16909 giw_led_set_mode(GIW_LED(checkbutton), mi_state);
16922 if (mt->selected_tracks) {
16927 if (mt->region_start != mt->region_end) {
16934 switch (lives_list_length(mt->selected_tracks)) {
16944 if (!mt->opts.pertrack_audio)
16963 int track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(checkbutton),
"layer_number"));
16964 lives_mt *mt = (lives_mt *)user_data;
16968 mt->current_track = track;
16970 if (track > -1) mt->aud_track_selected =
FALSE;
16971 else mt->aud_track_selected =
TRUE;
17021 #ifdef ENABLE_DVD_GRAB
17024 #ifdef HAVE_LDVGRAB
17041 if (mt->block_selected) {
17053 LiVESWidget *eventbox = NULL;
17055 if (mt->in_sensitise)
return;
17056 mt->in_sensitise =
TRUE;
17067 if (mt->avol_init_event && mt->opts.pertrack_audio &&
mainw->
files[mt->render_file]->
achans > 0)
17091 #ifdef ENABLE_DVD_GRAB
17094 #ifdef HAVE_LDVGRAB
17109 if (mt->selected_init_event) {
17114 if (mt->checkbutton_avel_reverse) {
17117 if (mt->block_selected && (!mt->block_selected->start_anchored ||
17119 (LIVES_TOGGLE_BUTTON(mt->checkbutton_avel_reverse))) {
17127 if (mt->file_selected > -1) {
17136 if (mt->video_draws &&
17137 mt->current_track > -1) eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, mt->current_track);
17138 else if (mt->audio_draws) eventbox = (LiVESWidget *)mt->audio_draws->data;
17145 if (mt->tl_marks) {
17152 if (mt->block_selected) {
17154 if (mt->poly_state ==
POLY_IN_OUT && mt->block_selected->ordered) {
17155 weed_timecode_t offset_end = mt->block_selected->offset_start + (weed_timecode_t)(
TICKS_PER_SECOND_DBL / mt->fps) +
17158 set_in_out_spin_ranges(mt, mt->block_selected->offset_start, offset_end);
17171 if (mt->region_end > mt->region_start && mt->event_list &&
get_first_event(mt->event_list)) {
17172 if (mt->selected_tracks) {
17178 if (mt->selected_tracks && mt->region_end != mt->region_start) {
17179 switch (lives_list_length(mt->selected_tracks)) {
17187 if (!mt->opts.pertrack_audio)
17202 mt->in_sensitise =
FALSE;
17207 LiVESWidget *tmp_img = NULL;
17208 static LiVESWidgetClosure *freeze_closure = NULL;
17210 if (!freeze_closure) freeze_closure = lives_cclosure_new(LIVES_GUI_CALLBACK(
freeze_callback), NULL, NULL);
17213 #if GTK_CHECK_VERSION(2, 6, 0)
17223 lives_signal_sync_connect(LIVES_GUI_OBJECT(mt->playall), LIVES_WIDGET_ACTIVATE_SIGNAL,
17226 lives_signal_sync_connect(LIVES_GUI_OBJECT(
mainw->
m_playbutton), LIVES_WIDGET_CLICKED_SIGNAL,
17229 (LiVESXModifierType)LIVES_CONTROL_MASK,
17230 (LiVESAccelFlags)0, freeze_closure);
17242 freeze_closure = NULL;
17252 lives_mt *mt = (lives_mt *)user_data;
17262 pb_loop_event = mt->pb_loop_event;
17269 if (mt->mt_frame_preview) {
17293 mt->no_frame_update =
FALSE;
17297 if (mt->opts.follow_playback) {
17298 double currtime = mt->ptr_time;
17299 if (currtime > mt->tl_max || currtime < mt->tl_min) {
17305 mt->is_paused =
TRUE;
17306 if ((curtime = mt->ptr_time) > 0.) {
17310 paint_lines(mt, curtime,
TRUE, NULL);
17311 mt->no_frame_update =
FALSE;
17317 if (!mt->is_rendering) {
17319 if (mt->init_event) {
17331 if (mt->ptr_time > 0.) {
17339 if (mt->is_paused) mt->pb_loop_event = pb_loop_event;
17341 paint_lines(mt, mt->ptr_time,
FALSE, NULL);
17346 LiVESWidget *old_context_scroll = mt->context_scroll;
17347 boolean needs_idlefunc =
FALSE;
17350 mt->no_expose_frame =
TRUE;
17351 mt->no_frame_update =
TRUE;
17353 if (mt->idlefunc > 0) {
17356 needs_idlefunc =
TRUE;
17362 if (mt->context_scroll) {
17365 mt->context_scroll = NULL;
17378 if (mt->opts.follow_playback) {
17379 double currtime = mt->ptr_time;
17380 if (currtime > mt->tl_max || currtime < mt->tl_min) {
17381 double page = mt->tl_max - mt->tl_min;
17382 mt->tl_min = currtime - page * .25;
17383 mt->tl_max = currtime + page * .75;
17390 needs_clear =
FALSE;
17393 if (mt->is_rendering) {
17395 boolean had_audio = mt->has_audio_file;
17396 mt->pb_start_event = NULL;
17397 mt->has_audio_file =
TRUE;
17400 mt->has_audio_file = had_audio;
17402 if (mt->event_list) {
17404 set_play_position(mt);
17408 if (mt->playing_sel)
17411 else if (mt->is_paused) mt->pb_loop_event = pb_loop_event;
17422 if (mt->context_scroll)
17425 mt->context_scroll = old_context_scroll;
17426 if (mt->context_scroll)
17434 if (mt->context_scroll)
17440 if (!mt->is_rendering) {
17442 if (needs_idlefunc) mt->idlefunc =
mt_idle_add(mt);
17445 mt->no_expose_frame =
FALSE;
17452 lives_mt *mt = (lives_mt *)user_data;
17454 ptr_time = mt->ptr_time;
17456 if (ptr_time < mt->region_start || ptr_time >= mt->region_end) {
17462 mt->playing_sel =
TRUE;
17467 if (!mt->is_paused) {
17468 mt->playing_sel =
FALSE;
17474 lives_mt *mt = (lives_mt *)user_data;
17481 lives_mt *mt = (lives_mt *)user_data;
17484 double secs = mt->ptr_time;
17486 LiVESWidget *eventbox;
17491 boolean did_backup = mt->did_backup;
17492 boolean needs_idlefunc =
FALSE;
17500 if (mt->idlefunc > 0) {
17501 needs_idlefunc =
TRUE;
17506 if (mt->context_time != -1. && mt->use_context) {
17507 secs = mt->context_time;
17508 mt->context_time = -1.;
17509 mt->use_context =
FALSE;
17512 eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, mt->current_track);
17514 if (mt->opts.ign_ins_sel) {
17520 if (mt->insert_start != -1) {
17522 ins_start = mt->insert_start;
17523 ins_end = mt->insert_end;
17528 weed_plant_t *
event = NULL;
17529 weed_timecode_t tc = 0, tcnow;
17530 weed_timecode_t tclen = ins_end - ins_start;
17532 while (tc <= tclen) {
17540 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
17551 block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"block_last");
17553 if (block && (mt->opts.grav_mode ==
GRAV_MODE_LEFT || (block->next
17555 !(did_backup || mt->moving_block)) {
17556 double oldr_start = mt->region_start;
17557 double oldr_end = mt->region_end;
17558 LiVESList *tracks_sel;
17559 track_rect *selblock = NULL;
17560 if (mt->block_selected != block) selblock = mt->block_selected;
17561 tracks_sel = lives_list_copy(mt->selected_tracks);
17562 if (mt->selected_tracks) lives_list_free(mt->selected_tracks);
17563 mt->selected_tracks = NULL;
17564 mt->selected_tracks = lives_list_append(mt->selected_tracks, LIVES_INT_TO_POINTER(mt->current_track));
17568 else mt->region_start = 0.;
17576 lives_list_free(mt->selected_tracks);
17577 mt->selected_tracks = lives_list_copy(tracks_sel);
17578 if (tracks_sel) lives_list_free(tracks_sel);
17579 mt->region_start = oldr_start;
17580 mt->region_end = oldr_end;
17582 if (selblock) mt->block_selected = selblock;
17586 block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"block_last");
17589 if (mt->avol_fx != -1 && block && !block->next &&
get_first_event(mt->event_list)) {
17590 apply_avol_filter(mt);
17596 mt->did_backup = did_backup;
17598 mt->did_backup =
TRUE;
17602 lives_painter_surface_t *bgimage = (lives_painter_surface_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
17610 if (!did_backup && mt->framedraw && mt->current_rfx && mt->init_event &&
17615 get_track_index(mt, tc);
17624 mt->did_backup =
FALSE;
17625 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
17633 lives_mt *mt = (lives_mt *)user_data;
17636 double secs = mt->ptr_time;
17637 double tstart, tend;
17639 LiVESWidget *eventbox = (LiVESWidget *)mt->audio_draws->data;
17644 boolean did_backup = mt->did_backup;
17645 boolean needs_idlefunc =
FALSE;
17650 char *istart, *iend;
17654 if (mt->current_track != -1 || sfile->
achans == 0)
return FALSE;
17656 if (mt->idlefunc > 0) {
17657 needs_idlefunc =
TRUE;
17662 if (mt->context_time != -1. && mt->use_context) {
17663 secs = mt->context_time;
17664 mt->context_time = -1.;
17665 mt->use_context =
FALSE;
17668 if (sfile->
frames == 0 || mt->opts.ign_ins_sel) {
17675 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
17684 if (mt->insert_start != -1) {
17685 ins_start = mt->insert_start;
17686 ins_end = mt->insert_end;
17694 weed_plant_t *
event = NULL;
17695 weed_timecode_t tc = 0, tcnow;
17696 weed_timecode_t tclen = ins_end - ins_start;
17700 while (tc <= tclen) {
17709 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
17720 block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"block_last");
17724 && !(did_backup || mt->moving_block)) {
17725 double oldr_start = mt->region_start;
17726 double oldr_end = mt->region_end;
17727 LiVESList *tracks_sel;
17728 track_rect *selblock = NULL;
17729 if (mt->block_selected != block) selblock = mt->block_selected;
17730 tracks_sel = lives_list_copy(mt->selected_tracks);
17731 if (mt->selected_tracks) lives_list_free(mt->selected_tracks);
17732 mt->selected_tracks = NULL;
17733 mt->current_track = -1;
17737 else mt->region_start = 0.;
17745 lives_list_free(mt->selected_tracks);
17746 mt->selected_tracks = lives_list_copy(tracks_sel);
17747 if (tracks_sel) lives_list_free(tracks_sel);
17748 mt->region_start = oldr_start;
17749 mt->region_end = oldr_end;
17750 if (selblock) mt->block_selected = selblock;
17753 mt->did_backup = did_backup;
17760 d_print(
_(
"Inserted audio %.4f to %.4f from clip %s into backing audio from time %s to time %s\n"),
17768 lives_painter_surface_t *bgimage = (lives_painter_surface_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
17775 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"expanded"))) {
17776 LiVESWidget *xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"achan0");
17778 xeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"achan1");
17784 block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"block_last");
17787 if (mt->avol_fx != -1 && block && !block->next &&
get_first_event(mt->event_list)) {
17788 apply_avol_filter(mt);
17794 if (!did_backup && mt->framedraw && mt->current_rfx && mt->init_event &&
17798 get_track_index(mt, tc);
17802 mt->did_backup =
FALSE;
17803 if (needs_idlefunc || (!did_backup && mt->auto_changed)) mt->idlefunc =
mt_idle_add(mt);
17810 void insert_frames(
int filenum, weed_timecode_t offset_start, weed_timecode_t offset_end, weed_timecode_t tc,
17811 lives_direction_t direction, LiVESWidget * eventbox, lives_mt * mt, track_rect * in_block) {
17831 weed_timecode_t last_tc = 0, offset_start_tc, start_tc, last_offset;
17832 weed_timecode_t orig_st = offset_start, orig_end = offset_end;
17834 int *clips = NULL, *rep_clips;
17835 int64_t *frames = NULL, *rep_frames;
17836 weed_plant_t *last_frame_event = NULL;
17837 weed_plant_t *event, *shortcut1 = NULL, *shortcut2 = NULL;
17838 track_rect *new_block = NULL;
17840 LiVESWidget *aeventbox = NULL;
17845 boolean isfirst =
TRUE;
17848 int track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"layer_number"));
17857 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"block_last", (livespointer)NULL);
17858 if ((aeventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"atrack")) != NULL)
17859 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(aeventbox),
"block_last", (livespointer)NULL);
17861 last_offset = offset_start_tc =
q_gint64(offset_start, mt->fps);
17862 offset_end =
q_gint64(offset_end, mt->fps);
17871 q_gint64(start_tc - 1. / mt->fps, mt->fps), mt->fps);
17876 if (
cfile->fps != mt->fps && !
cfile->event_list) {
17878 cfile->undo1_dbl = mt->fps;
17885 (offset_start =
q_gint64(last_tc - start_tc + offset_start_tc, mt->fps)) < offset_end)
17887 (offset_start =
q_gint64(last_tc + offset_start_tc - start_tc, mt->fps)) >= offset_end)) {
17889 clips = rep_clips = NULL;
17890 frames = rep_frames = NULL;
17894 clips = weed_get_int_array_counted(event,
WEED_LEAF_CLIPS, &numframes);
17901 if (numframes <= track) {
17906 for (i = 0; i < track; i++) {
17907 if (i < numframes) {
17908 rep_clips[i] = clips[i];
17909 rep_frames[i] = frames[i];
17915 numframes = track + 1;
17918 if (!in_block && new_block) {
17928 rep_frames = frames;
17933 if (rep_clips != clips && rep_clips)
lives_free(rep_clips);
17934 if (rep_frames != frames && rep_frames)
lives_free(rep_frames);
17939 last_offset = offset_start;
17946 rep_clips[track] = filenum;
17947 rep_frames[track] = frame;
17950 if (!mt->event_list) {
17954 mt->event_list =
insert_frame_event_at(mt->event_list, last_tc, numframes, rep_clips, rep_frames, &shortcut1);
17956 if (rep_clips != clips && rep_clips)
lives_free(rep_clips);
17957 if (rep_frames != frames && rep_frames)
lives_free(rep_frames);
17962 new_block = add_block_start_point(eventbox, last_tc, filenum, offset_start, shortcut1,
TRUE);
17964 if (
cfile->achans > 0 && sfile->
achans > 0 && mt->opts.insert_audio) {
17967 aseek = ((double)frame - 1.) / sfile->
fps;
17970 add_block_start_point(aeventbox, last_tc, filenum, offset_start, shortcut1,
TRUE);
17972 weed_plant_t *nframe;
17976 nframe = shortcut1;
17990 last_tc =
q_gint64(last_tc, mt->fps);
17992 if (last_tc < TICKS_PER_SECOND_DBL / mt->fps) {
17996 last_tc =
q_gint64(last_tc, mt->fps);
18006 if (in_block) lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"block_last", (livespointer)in_block);
18007 add_block_end_point(eventbox, shortcut1);
18009 if (
cfile->achans > 0 && sfile->
achans > 0 && mt->opts.insert_audio && mt->opts.pertrack_audio) {
18013 }
else shortcut1 = shortcut2;
18015 add_block_end_point(aeventbox, shortcut1);
18017 }
else if (in_block) {
18018 in_block->offset_start = last_offset;
18019 in_block->start_event = shortcut1;
18020 if (
cfile->achans > 0 && sfile->
achans > 0 && mt->opts.insert_audio && mt->opts.pertrack_audio) {
18024 }
else shortcut1 = shortcut2;
18029 mt->last_direction = direction;
18031 if (mt->event_list) {
18032 weed_set_double_value(mt->event_list, WEED_LEAF_FPS,
mainw->
files[render_file]->
fps);
18036 char *tmp, *tmp1, *istart, *iend;
18038 istart = time_to_string(
QUANT_TICKS((orig_st + start_tc)));
18039 iend = time_to_string(
QUANT_TICKS((orig_end + start_tc)));
18041 d_print(
_(
"Inserted frames %d to %d from clip %s into track %s from time %s to time %s\n"),
18051 if (end_secs > mt->end_secs) {
18059 void insert_audio(
int filenum, weed_timecode_t offset_start, weed_timecode_t offset_end, weed_timecode_t tc,
18061 lives_mt * mt, track_rect * in_block) {
18064 weed_timecode_t start_tc =
q_gint64(tc, mt->fps);
18065 weed_timecode_t end_tc =
q_gint64(start_tc + offset_end - offset_start, mt->fps);
18066 weed_plant_t *last_frame_event;
18068 weed_plant_t *shortcut = NULL;
18069 weed_plant_t *frame_event;
18073 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(eventbox),
"block_last", (livespointer)NULL);
18076 weed_timecode_t tmp_tc = offset_end;
18077 offset_end = offset_start;
18078 offset_start = tmp_tc;
18082 if ((block = get_block_from_time((LiVESWidget *)mt->audio_draws->data, start_tc /
TICKS_PER_SECOND_DBL, mt)) != NULL &&
18090 if (block) shortcut = block->end_event;
18101 offset_start = offset_start - offset_end + offset_end * mt->insert_avel;
18104 add_block_start_point((LiVESWidget *)mt->audio_draws->data, start_tc, filenum, offset_start, frame_event,
TRUE);
18110 add_block_end_point((LiVESWidget *)mt->audio_draws->data, frame_event);
18111 }
else add_block_end_point((LiVESWidget *)mt->audio_draws->data, block->start_event);
18114 if (end_secs > mt->end_secs) {
18123 lives_mt *mt = (lives_mt *)user_data;
18124 LiVESWidget *elist_dialog;
18138 lives_mt *mt = (lives_mt *)user_data;
18139 LiVESWidget *elist_dialog;
18160 lives_painter_t *cr;
18167 if (mt->region_start == mt->region_end) {
18183 if (mt->region_start < mt->region_end) {
18184 start = mt->region_start;
18185 end = mt->region_end;
18187 start = mt->region_end;
18188 end = mt->region_start;
18191 if (mt->region_start == mt->region_end) {
18223 static EXPOSE_FN_DECL(expose_timeline_reg_event, timeline, user_data) {
18224 lives_mt *mt = (lives_mt *)user_data;
18225 LiVESList *tl_marks = mt->tl_marks;
18232 if (mt->no_expose)
return TRUE;
18233 if (event && event->count > 0)
return FALSE;
18242 time = strtod((
char *)tl_marks->data, NULL);
18244 offset = (time - mt->tl_min) / (mt->tl_max - mt->tl_min) * (double)ebwidth;
18250 tl_marks = tl_marks->next;
18255 paint_lines(mt, mt->ptr_time,
FALSE, NULL);
18262 static void draw_soundwave(LiVESWidget * ebox, lives_painter_surface_t *surf,
int chnum, lives_mt * mt) {
18263 weed_plant_t *event;
18264 weed_timecode_t tc;
18268 LiVESWidget *eventbox = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(ebox),
"owner");
18270 track_rect *block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks");
18274 double offset_startd, offset_endd;
18275 double tl_span = mt->tl_max - mt->tl_min;
18280 int offset_start, offset_end;
18283 int track = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"layer_number"));
18291 event = block->start_event;
18295 if (offset_startd > mt->tl_max) {
18300 offset_start = (int)((offset_startd - mt->tl_min) / tl_span * width + .5);
18301 if (offset_start < 0) offset_start = 0;
18304 if (offset_endd < mt->tl_min) {
18305 block = block->next;
18308 if (offset_endd > mt->tl_max) offset_endd = mt->tl_max;
18309 offset_end = (offset_endd - mt->tl_min) / tl_span * width;
18328 if (fnum != aofile) {
18330 if (afd != -1) close(afd);
18337 for (
int i = offset_start; i <= offset_end; i++) {
18338 secs = (double)i / (
double)width * tl_span + mt->tl_min;
18339 secs -= offset_startd;
18340 secs = secs * vel + seek;
18354 block = block->next;
18369 static EXPOSE_FN_DECL(mt_expose_audtrack_event, ebox, user_data) {
18370 lives_mt *mt = (lives_mt *)user_data;
18372 lives_painter_surface_t *bgimage;
18374 int startx, starty, width, height;
18378 if (mt->no_expose)
return TRUE;
18381 if (event->count > 0) {
18384 startx =
event->area.x;
18385 starty =
event->area.y;
18386 width =
event->area.width;
18387 height =
event->area.height;
18389 startx = starty = 0;
18394 if (width == 0)
return FALSE;
18396 hidden = (int)LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(ebox),
HIDDEN_KEY));
18403 #if !GTK_CHECK_VERSION(3, 22, 0)
18407 bgimage = (lives_painter_surface_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(ebox),
"bgimg");
18409 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(ebox),
"drawn"))) {
18438 channum = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(ebox),
"channel"));
18441 draw_soundwave(ebox, bgimage, channum, mt);
18442 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(ebox),
"drawn", LIVES_INT_TO_POINTER(
TRUE));
18444 }
else if (bgimage) {
18449 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(ebox),
"bgimg", bgimage);
18461 lives_mt *mt = (lives_mt *)user_data;
18471 if (!mt->region_updating) {
18472 if (mt->tl_mouse) {
18473 mt->fm_edit_event = NULL;
18479 if (!mt->sel_locked) {
18480 if (pos > mt->region_init) {
18481 mt->region_start = mt->region_init;
18482 mt->region_end = pos;
18484 mt->region_start = pos;
18485 mt->region_end = mt->region_init;
18492 if (mt->opts.mouse_mode ==
MOUSE_MODE_SELECT && mt->tl_selecting && event) mouse_select_move(widget, event, mt);
18501 int numclips, layer;
18504 if (!event || !sel)
return FALSE;
18506 clips = weed_get_int_array_counted(event,
WEED_LEAF_CLIPS, &numclips);
18508 if (!numclips)
return FALSE;
18513 layer = LIVES_POINTER_TO_INT(sel->data);
18514 if (layer >= numclips || clips[layer] < 1 || frames[layer] < 1) {
18529 weed_plant_t *event;
18530 weed_timecode_t tc;
18532 if (!mt->selected_tracks || !mt->event_list) {
18533 mt->region_start = mt->region_end = 0.;
18540 while (
all_present(event, mt->selected_tracks)) {
18550 while (event && !
all_present(event, mt->selected_tracks)) {
18554 if (!event) mt->region_start = 0.;
18560 while (
all_present(event, mt->selected_tracks)) {
18570 while (event && !
all_present(event, mt->selected_tracks)) {
18574 if (!event) mt->region_end = 0.;
18585 if (mt->region_start == mt->region_end || mt->did_backup)
return;
18587 msg =
lives_strdup_printf(
_(
"Time region %.3f to %.3f\nselected.\n"), mt->region_start, mt->region_end);
18590 if (!mt->selected_tracks) {
18591 msg =
lives_strdup_printf(
_(
"select one or more tracks\nto create a region.\n"), lives_list_length(mt->selected_tracks));
18593 int llen = lives_list_length(mt->selected_tracks);
18608 add_context_label(mt, (
_(
"\n\nEffects are applied in order from top to bottom.\n")));
18617 add_context_label(mt, (
_(
"You can select an effect,\nthen use the INSERT BEFORE")));
18624 lives_mt *mt = (lives_mt *)user_data;
18626 double pos = mt->region_end;
18634 mt->tl_mouse =
FALSE;
18636 if (eventbox != mt->timeline_reg || mt->sel_locked) {
18640 if (event) mt->region_updating =
FALSE;
18642 if (mt->region_start == mt->region_end && eventbox == mt->timeline_reg) {
18643 mt->region_start = mt->region_end = 0;
18655 no_time_selected(mt);
18658 if ((mt->region_end != mt->region_start) && eventbox == mt->timeline_reg) {
18660 if (mt->region_end < mt->region_start) {
18661 mt->region_start -= mt->region_end;
18662 mt->region_end += mt->region_start;
18663 mt->region_start = mt->region_end - mt->region_start;
18665 if (mt->region_end > mt->region_start && mt->event_list &&
get_first_event(mt->event_list)) {
18666 if (mt->selected_tracks) {
18687 if (eventbox != mt->timeline_reg)
mt_tl_move(mt, pos);
18694 if (mt->init_event && mt->poly_state ==
POLY_PARAMS)
18702 pos = mt->ptr_time;
18708 if (mt->opts.mouse_mode ==
MOUSE_MODE_SELECT && event) mouse_select_end(eventbox, event, mt);
18710 if (mt->selected_tracks && mt->region_end != mt->region_start) {
18712 switch (lives_list_length(mt->selected_tracks)) {
18718 if (!mt->opts.pertrack_audio)
18740 lives_mt *mt = (lives_mt *)user_data;
18742 LiVESXModifierType modmask;
18743 LiVESXDevice *device;
18756 if (widget == mt->timeline_reg && !mt->sel_locked) {
18757 mt->region_start = mt->region_end = mt->region_init = pos;
18759 mt->region_updating =
TRUE;
18765 if (event->button == 1) {
18766 if (widget == mt->timeline_eb) {
18767 mt->fm_edit_event = NULL;
18769 mt->tl_mouse =
TRUE;
18772 if (widget == mt->timeline) {
18773 mt->fm_edit_event = NULL;
18777 if (mt->opts.mouse_mode ==
MOUSE_MODE_SELECT) mouse_select_start(widget, event, mt);
18784 weed_plant_t *
get_prev_fm(lives_mt * mt,
int current_track, weed_plant_t *event) {
18785 weed_plant_t *event2, *event3, *eventx;
18787 if (!event)
return NULL;
18791 if (!eventx)
return NULL;
18799 if (!event2)
return NULL;
18804 event = event2 = event3;
18814 if (!event2)
return NULL;
18823 if (!event3)
break;
18827 if (!event2)
break;
18838 weed_plant_t *
get_next_fm(lives_mt * mt,
int current_track, weed_plant_t *event) {
18839 weed_plant_t *event2, *event3;
18841 if (!event)
return NULL;
18844 if (!event3)
return NULL;
18850 if (!event)
return NULL;
18861 static void add_mark_at(lives_mt * mt,
double time) {
18862 lives_painter_t *cr;
18868 mt->tl_marks = lives_list_append(mt->tl_marks, tstring);
18883 boolean mt_mark_callback(LiVESAccelGroup * group, LiVESWidgetObject * obj, uint32_t keyval, LiVESXModifierType mod,
18884 livespointer user_data) {
18885 lives_mt *mt = (lives_mt *)user_data;
18890 cur_time = mt->ptr_time;
18892 add_mark_at(mt, cur_time);
18898 livespointer user_data) {
18899 lives_mt *mt = (lives_mt *)user_data;
18901 mt->opts.overlay_timecode = !mt->opts.overlay_timecode;
18908 lives_mt *mt = (lives_mt *)user_data;
18921 lives_mt *mt = (lives_mt *)user_data;
18934 lives_mt *mt = (lives_mt *)user_data;
18935 weed_timecode_t tc;
18936 double secs = mt->ptr_time;
18938 weed_plant_t *event;
18942 event =
get_prev_fm(mt, mt->current_track, event);
18951 lives_mt *mt = (lives_mt *)user_data;
18952 weed_timecode_t tc;
18953 weed_plant_t *event;
18954 double secs = mt->ptr_time;
18959 event =
get_next_fm(mt, mt->current_track, event);
18967 static weed_timecode_t get_prev_node_tc(lives_mt * mt, weed_timecode_t tc) {
18969 weed_timecode_t prev_tc = -1;
18970 weed_plant_t *event;
18971 weed_timecode_t ev_tc;
18973 if (!pchain)
return tc;
18975 for (
int i = 0; i < num_params; i++) {
18976 event = (weed_plant_t *)pchain[i];
18978 if (ev_tc > prev_tc) prev_tc = ev_tc;
18986 static weed_timecode_t get_next_node_tc(lives_mt * mt, weed_timecode_t tc) {
18988 weed_timecode_t next_tc = -1;
18989 weed_plant_t *event;
18990 weed_timecode_t ev_tc;
18992 if (!pchain)
return tc;
18994 for (
int i = 0; i < num_params; i++) {
18995 event = (weed_plant_t *)pchain[i];
18999 if (next_tc == -1 || ev_tc < next_tc) next_tc = ev_tc;
19006 static boolean is_node_tc(lives_mt * mt, weed_timecode_t tc) {
19008 weed_plant_t *event;
19009 weed_timecode_t ev_tc;
19011 for (
int i = 0; i < num_params; i++) {
19012 event = (weed_plant_t *)pchain[i];
19025 lives_mt *mt = (lives_mt *)user_data;
19028 weed_timecode_t tc =
q_gint64(otc, mt->fps);
19029 weed_timecode_t pn_tc, nn_tc;
19031 boolean auto_prev = mt->opts.fx_auto_preview;
19035 if (!mt->block_tl_move) {
19037 mt->block_node_spin =
TRUE;
19038 if (mt->current_track >= 0 && (mt->opts.fx_auto_preview ||
mainw->
play_window))
19039 mt->no_frame_update =
TRUE;
19041 mt->no_frame_update =
FALSE;
19042 mt->block_node_spin =
FALSE;
19045 if (mt->prev_fx_time == 0. || tc == init_tc) {
19053 get_track_index(mt, tc);
19055 mt->opts.fx_auto_preview =
FALSE;
19056 mt->current_rfx->needs_reinit =
FALSE;
19060 if (mt->current_rfx->needs_reinit) {
19061 mt->current_rfx->needs_reinit =
FALSE;
19065 mt->opts.fx_auto_preview = auto_prev;
19068 pn_tc = get_prev_node_tc(mt, tc);
19069 nn_tc = get_next_node_tc(mt, tc);
19077 if (is_node_tc(mt, tc)) {
19084 if (mt->current_track >= 0) {
19092 static boolean check_can_resetp(lives_mt * mt) {
19094 boolean can_reset =
FALSE;
19102 if (mt->init_event) {
19104 int *in_tracks = weed_get_int_array_counted(mt->init_event,
WEED_LEAF_IN_TRACKS, &num_in_tracks);
19106 for (i = 0; i < num_in_tracks; i++) {
19107 if (in_tracks[i] == mt->current_track) {
19108 mt->track_index = i;
19115 for (i = 0; i < nparams; i++) {
19120 if (!weed_leaf_elements_equate(in_params[i], WEED_LEAF_VALUE, def_params[i], WEED_LEAF_VALUE, mt->track_index)) {
19125 if (!weed_leaf_elements_equate(in_params[i], WEED_LEAF_VALUE, def_params[i], WEED_LEAF_VALUE, -1)) {
19132 for (i = 0; i < ninpar; i++) {
19133 weed_plant_free(def_params[i]);
19141 lives_mt *mt = (lives_mt *)user_data;
19143 boolean can_apply =
FALSE;
19144 boolean aprev = mt->opts.fx_auto_preview;
19152 if (mt->init_event) {
19154 int *in_tracks = weed_get_int_array_counted(mt->init_event,
WEED_LEAF_IN_TRACKS, &num_in_tracks);
19155 if (num_in_tracks > 0) {
19156 for (i = 0; i < num_in_tracks; i++) {
19157 if (in_tracks[i] == mt->current_track) {
19158 mt->track_index = i;
19166 for (i = 0; i < nparams; i++) {
19171 if (!weed_leaf_elements_equate(in_params[i], WEED_LEAF_VALUE, def_params[i], WEED_LEAF_VALUE, mt->track_index)) {
19172 weed_leaf_dup_nth(in_params[i], def_params[i], WEED_LEAF_VALUE, mt->track_index);
19174 mt->current_rfx->params[i].changed =
TRUE;
19177 if (!weed_leaf_elements_equate(in_params[i], WEED_LEAF_VALUE, def_params[i], WEED_LEAF_VALUE, -1)) {
19178 weed_leaf_dup(in_params[i], def_params[i], WEED_LEAF_VALUE);
19179 mt->current_rfx->params[i].changed =
TRUE;
19183 weed_plant_free(def_params[i]);
19188 mt->opts.fx_auto_preview =
FALSE;
19190 mt->current_rfx->needs_reinit =
FALSE;
19194 if (mt->current_rfx->needs_reinit) {
19196 mt->current_rfx->needs_reinit =
FALSE;
19199 mt->opts.fx_auto_preview = aprev;
19208 lives_mt *mt = (lives_mt *)user_data;
19213 weed_timecode_t next_tc = get_next_node_tc(mt, tc);
19222 lives_mt *mt = (lives_mt *)user_data;
19227 weed_timecode_t prev_tc = get_prev_node_tc(mt, tc);
19236 lives_mt *mt = (lives_mt *)user_data;
19240 weed_plant_t **in_params = weed_get_plantptr_array((weed_plant_t *)mt->current_rfx->source, WEED_LEAF_IN_PARAMETERS, &
error);
19242 weed_plant_t *event;
19243 weed_plant_t *prev_pchange, *next_pchange;
19245 weed_timecode_t ev_tc;
19255 if (mt->idlefunc > 0) {
19262 for (i = 0; i < num_params; i++) {
19263 event = (weed_plant_t *)pchain[i];
19270 if (event != pchain[i]) {
19276 weed_plant_t *param = in_params[i];
19280 }
else weed_leaf_copy(event, WEED_LEAF_VALUE, paramtmpl, WEED_LEAF_DEFAULT);
19291 if (mt->current_fx == mt->avol_fx && mt->avol_init_event && mt->opts.aparam_view_list) {
19292 LiVESList *slist = mt->audio_draws;
19295 slist = slist->next;
19301 d_print(
_(
"Removed parameter values for effect %s at time %s\n"), filter_name, mt->timestring);
19303 mt->block_tl_move =
TRUE;
19305 mt->block_tl_move =
FALSE;
19307 if (mt->current_track >= 0) {
19313 if (!mt->auto_changed) mt->auto_changed =
TRUE;
19317 mt->changed =
TRUE;
19326 if (mt->fm_edit_event == old_event) {
19328 mt->fm_edit_event = new_event;
19330 if (mt->init_event == old_event) {
19332 mt->init_event = new_event;
19334 if (mt->selected_init_event == old_event) {
19336 mt->selected_init_event = new_event;
19338 if (mt->avol_init_event == old_event) {
19340 mt->avol_init_event = new_event;
19342 if (mt->specific_event == old_event) {
19344 mt->specific_event = new_event;
19349 static void combine_ign(weed_plant_t *xnew, weed_plant_t *xold) {
19350 int num, numo, *nign, *oign, i;
19353 oign = weed_get_boolean_array_counted(xold, WEED_LEAF_IGNORE, &numo);
19355 nign = weed_get_boolean_array_counted(xnew, WEED_LEAF_IGNORE, &num);
19356 for (i = 0; i < num; i++)
if (i >= numo || oign[i] == WEED_FALSE) nign[i] = WEED_FALSE;
19357 weed_set_boolean_array(xnew, WEED_LEAF_IGNORE, num, nign);
19363 static void add_to_pchain(weed_plant_t *event_list, weed_plant_t *init_event, weed_plant_t *pchange,
int index,
19364 weed_timecode_t tc) {
19365 weed_plant_t *
event = (weed_plant_t *)pchain[index];
19366 weed_plant_t *last_event = NULL;
19370 last_event = event;
19379 if (event == pchain[index]) weed_leaf_delete(pchange, WEED_LEAF_IGNORE);
19380 if (weed_plant_has_leaf(pchange, WEED_LEAF_IGNORE)) combine_ign(pchange, event);
19391 void **in_params = weed_get_voidptr_array_counted(init_event, WEED_LEAF_IN_PARAMETERS, &numin);
19392 in_params[index] = pchain[index] = (
void *)pchange;
19393 weed_set_voidptr_array(init_event, WEED_LEAF_IN_PARAMETERS, numin, in_params);
19402 static boolean norecurse =
FALSE;
19403 if (norecurse)
return;
19407 if (mt->opts.fx_auto_preview) {
19412 if (mt->apply_fx_button) {
19413 int nparams = mt->current_rfx->num_params;
19416 for (
int i = 0; i < nparams; i++) {
19417 if (mt->current_rfx->params[i].changed) {
19431 lives_mt *mt = (lives_mt *)user_data;
19433 weed_plant_t *inst = (weed_plant_t *)mt->current_rfx->source;
19434 weed_plant_t *param, *pchange, *at_event;
19443 char *tname, *track_desc;
19445 boolean has_multi =
FALSE;
19446 boolean was_changed =
FALSE;
19447 boolean needs_idlefunc =
FALSE;
19448 boolean did_backup = mt->did_backup;
19455 LiVESWidget *textwidget = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(
mainw->
textwidget_focus),
19459 if (mt->framedraw) {
19465 if (mt->idlefunc > 0) {
19466 needs_idlefunc =
TRUE;
19475 if (!mt->current_rfx->params[i].changed)
continue;
19476 pchange = weed_plant_new(WEED_PLANT_EVENT);
19477 weed_set_int_value(pchange, WEED_LEAF_EVENT_TYPE, WEED_EVENT_TYPE_PARAM_CHANGE);
19478 weed_set_int64_value(pchange, WEED_LEAF_TIMECODE, tc);
19483 if (weed_plant_has_leaf(param, WEED_LEAF_IGNORE)) {
19486 int *ign = weed_get_boolean_array_counted(param, WEED_LEAF_IGNORE, &num_vals);
19487 weed_set_boolean_array(pchange, WEED_LEAF_IGNORE, num_vals, ign);
19488 for (j = 0; j < num_vals; j++) {
19489 if (ign[j] == WEED_FALSE) {
19490 was_changed =
TRUE;
19491 ign[j] = WEED_TRUE;
19495 weed_set_boolean_array(param, WEED_LEAF_IGNORE, num_vals, ign);
19498 }
else was_changed =
TRUE;
19500 weed_leaf_copy(pchange, WEED_LEAF_VALUE, param, WEED_LEAF_VALUE);
19508 add_to_pchain(mt->event_list, mt->init_event, pchange, i, tc);
19514 if (!was_changed) {
19515 if (needs_idlefunc || (!did_backup && mt->auto_changed))
19524 nparams = mt->current_rfx->num_params;
19525 for (i = 0; i < nparams; i++) mt->current_rfx->params[i].changed =
FALSE;
19527 switch (numtracks) {
19545 }
else track_desc = (
_(
"selected tracks"));
19549 if (mt->current_fx == mt->avol_fx) {
19551 tname = (
_(
"audio"));
19554 d_print(
_(
"Set parameter values for %s %s on %s at time %s\n"), tname, filter_name, track_desc, mt->timestring);
19561 if (mt->current_fx == mt->avol_fx && mt->avol_init_event && mt->opts.aparam_view_list) {
19562 LiVESList *slist = mt->audio_draws;
19565 slist = slist->next;
19569 if (mt->current_track >= 0) {
19573 if (!mt->auto_changed) mt->auto_changed =
TRUE;
19577 mt->changed =
TRUE;
19581 static int free_tt_key;
19582 static int elist_errors;
19598 LiVESList *lmap = NULL;
19600 uint64_t unique_id;
19613 boolean err =
FALSE;
19615 if (!lives_file_test(lmap_name, LIVES_FILE_TEST_EXISTS)) {
19659 lmap_entry->
handle = handle;
19661 lmap_entry->
name = name;
19662 lmap_entry->
list = NULL;
19673 for (i = 0; i < nm; i++) {
19687 lmap_entry->
list = lives_list_append(lmap_entry->
list, lives_strdup(
string));
19688 array = lives_strsplit(
string,
"|", -1);
19691 lives_strfreev(array);
19695 lmap = lives_list_append(lmap, lmap_entry);
19707 }
while (retval == LIVES_RESPONSE_RETRY);
19743 LiVESList *map, *map_next;
19746 char *map_name = NULL, *ldir = NULL;
19753 boolean written =
FALSE;
19755 boolean write_to_file =
TRUE;
19766 if (!file) write_to_file =
FALSE;
19772 else ldir = lives_strdup(dir);
19795 map_next = map->next;
19797 char **array = lives_strsplit((
char *)map->data,
"|", -1);
19798 if ((file && !strcmp(array[0], file)) || (!file && !dir &&
19799 !lives_file_test(array[0], LIVES_FILE_TEST_EXISTS))) {
19805 lives_strfreev(array);
19811 if (file && ((lmap && lmap[i] != 0) || (lmap_audio && lmap_audio[i] != 0.))) {
19812 if (lmap) max_frame = lmap[i];
19813 else max_frame = 0;
19814 if (lmap_audio) max_atime = lmap_audio[i];
19815 else max_atime = 0.;
19832 len = lives_list_length(map);
19836 len = strlen(
string);
19853 }
while (retval == LIVES_RESPONSE_RETRY);
19855 if (write_to_file && retval != LIVES_RESPONSE_CANCEL) {
19859 if (size <= 0 || !written) {
19870 if (write_to_file) {
19877 void add_markers(lives_mt * mt, weed_plant_t *event_list,
boolean add_block_ids) {
19889 LiVESList *track_blocks = NULL;
19890 LiVESList *tlist = mt->video_draws;
19893 weed_timecode_t tc;
19894 LiVESWidget *eventbox;
19895 weed_plant_t *event;
19899 eventbox = (LiVESWidget *)tlist->data;
19900 block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks");
19901 track_blocks = lives_list_append(track_blocks, (livespointer)block);
19902 tlist = tlist->next;
19910 blist = track_blocks;
19913 block = (track_rect *)blist->data;
19922 if (mt->audio_draws && lives_list_length(mt->audio_draws) >= track + mt->opts.back_audio_tracks) {
19925 LIVES_INT_TO_POINTER(-track - mt->opts.back_audio_tracks - 1));
19928 if (!block->ordered) {
19931 if (event == block->end_event) blist->data = block->next;
19934 blist = blist->next;
19940 if (track_blocks) lives_list_free(track_blocks);
19950 boolean needs_idlefunc =
FALSE;
19952 if (mt && mt->idlefunc > 0) {
19955 needs_idlefunc =
TRUE;
19964 if (response == LIVES_RESPONSE_CANCEL) {
19967 if (needs_idlefunc) {
19983 if (!mt->auto_changed) mt->auto_changed =
TRUE;
19999 lives_mt *mt = (lives_mt *)user_data;
20005 double *layout_map_audio;
20007 LiVESWidget *ar_checkbutton;
20010 weed_plant_t *event_list;
20020 boolean retval =
TRUE;
20022 boolean needs_idlefunc =
FALSE;
20023 boolean did_backup;
20032 did_backup = mt->did_backup;
20034 event_list = mt->event_list;
20035 layout_name = mt->layout_name;
20040 layout_map_audio = update_layout_map_audio(event_list);
20062 if (mt && mt->idlefunc > 0) {
20065 needs_idlefunc =
TRUE;
20075 if (needs_idlefunc) {
20084 if ((needs_idlefunc || (!did_backup && mt->auto_changed))) {
20100 lives_signal_sync_connect(LIVES_GUI_OBJECT(ar_checkbutton), LIVES_WIDGET_TOGGLED_SIGNAL,
20106 if (!(*layout_name)) esave_file =
choose_file(esave_dir, NULL, filt, LIVES_FILE_CHOOSER_ACTION_SAVE, NULL, hbox);
20107 else esave_file =
choose_file(esave_dir, layout_name, filt, LIVES_FILE_CHOOSER_ACTION_SAVE, NULL, hbox);
20114 esave_dir =
get_dir(esave_file);
20134 if (needs_idlefunc || (!did_backup && mt->auto_changed)) {
20143 lives_snprintf(xlayout_name,
PATH_MAX,
"%s", esave_file);
20162 if (!retval || fd < 0) {
20164 if (retval2 == LIVES_RESPONSE_CANCEL) {
20166 if (needs_idlefunc) {
20178 }
while (retval2 == LIVES_RESPONSE_RETRY);
20180 if (retval2 != LIVES_RESPONSE_CANCEL) {
20182 d_print(
_(
"Saved layout to %s\n"), esave_file);
20188 if (mt) mt->changed =
FALSE;
20208 mt->auto_changed =
FALSE;
20218 static char *rec_error_add(
char *ebuf,
char *msg,
int num, weed_timecode_t tc) {
20227 if (tc == -1) xnew = lives_strdup(msg);
20232 tmp = lives_strconcat(ebuf, xnew, NULL);
20234 #ifndef SILENT_EVENT_LIST_LOAD
20235 lives_printerr(
"Rec error: %s", xnew);
20244 static int get_next_tt_key(
ttable * trans_table) {
20247 if (trans_table[i].in == 0)
return i;
20255 if (normal && trans_table[i].in == in)
return trans_table[i].
out;
20258 if (!normal && (uint64_t)trans_table[i].out == in)
return (
void *)trans_table[i].
in;
20259 if (!trans_table[i].out)
return NULL;
20265 static void **remove_nulls_from_filter_map(
void **init_events,
int *num_events) {
20269 int num_nulls = 0, i, j = 0;
20270 void **new_init_events;
20272 if (*num_events == 1)
return init_events;
20274 for (i = 0; i < *num_events; i++)
if (!init_events[i]) num_nulls++;
20275 if (num_nulls == 0)
return init_events;
20277 *num_events -= num_nulls;
20279 if (*num_events == 0) new_init_events = NULL;
20281 else new_init_events = (
void **)
lives_malloc((*num_events) *
sizeof(
void *));
20283 for (i = 0; i < *num_events + num_nulls; i++)
if (init_events[i]) new_init_events[j++] = init_events[i];
20287 if (*num_events == 0) *num_events = 1;
20289 return new_init_events;
20294 weed_plant_t *ito,
int track,
boolean after) {
20297 void **events_before = NULL;
20298 void **events_after = NULL;
20299 int num_before = 0, j1;
20300 int num_after = 0, j2;
20302 void **init_events, **new_init_events;
20305 while (event != deinit_event) {
20311 if (!events_before && !events_after) {
20313 for (i = 0; i < num_inits; i++) {
20314 if (init_events[i] == ifrom)
continue;
20317 if (init_events[i] == ito) {
20318 num_before = j - 1 + after;
20322 num_after = j - after;
20323 if (num_before > 0) events_before = (
void **)
lives_malloc(num_before *
sizeof(
void *));
20324 if (num_after > 0) events_after = (
void **)
lives_malloc(num_after *
sizeof(
void *));
20326 for (i = 0; i < num_inits; i++) {
20328 if (init_events[i] == ifrom)
continue;
20329 if (j1 < num_before) {
20330 events_before[j1] = init_events[i];
20333 events_after[j2] = init_events[i];
20340 for (i = 0; i < num_inits; i++) {
20341 if (init_events[i] == ifrom)
continue;
20343 if (!got_after &&
init_event_in_list(events_after, num_after, (weed_plant_t *)init_events[i])) got_after =
TRUE;
20344 if (got_after &&
init_event_in_list(events_before, num_before, (weed_plant_t *)init_events[i])) {
20346 if (events_before)
lives_free(events_before);
20351 new_init_events = (
void **)
lives_malloc(num_inits *
sizeof(
void *));
20354 for (i = 0; i < num_inits; i++) {
20355 if (init_events[i] == ifrom)
continue;
20356 if ((
init_event_in_list(events_before, num_before, (weed_plant_t *)init_events[i]) ||
20359 new_init_events[j] = init_events[i];
20363 new_init_events[j] = ifrom;
20368 new_init_events[j] = init_events[i];
20372 if (j < num_inits) new_init_events[j] = ifrom;
20379 if (events_before)
lives_free(events_before);
20387 int i1, i2, num_events1, num_events2;
20388 void **inits1, **inits2;
20410 if (!inits1 && !inits2)
return TRUE;
20414 for (i1 = 0; i1 < num_events1; i1++) {
20435 if (i2 >= num_events2) {
20444 if (i2 < num_events2) {
20453 if (inits1[i1] != inits2[i2]) {
20462 if (i2 < num_events2) {
20467 for (; i2 < num_events2; i2++) {
20488 static char *filter_map_check(
ttable * trans_table, weed_plant_t *filter_map, weed_timecode_t deinit_tc,
20489 weed_timecode_t fm_tc,
char *ebuf) {
20490 int num_init_events;
20491 void **copy_events, **pinit_events;
20493 uint64_t *init_events;
20500 if (num_init_events == 1 && weed_get_int64_value(filter_map,
WEED_LEAF_INIT_EVENTS, NULL) == 0)
return ebuf;
20503 if (num_init_events == 1 && !weed_get_voidptr_value(filter_map,
WEED_LEAF_INIT_EVENTS, NULL))
return ebuf;
20505 init_events = (uint64_t *)
lives_malloc(num_init_events *
sizeof(uint64_t));
20506 for (i = 0; i < num_init_events; i++) init_events[i] = (uint64_t)pinit_events[i];
20510 copy_events = (
void **)
lives_malloc(num_init_events *
sizeof(weed_plant_t *));
20511 for (i = 0; i < num_init_events; i++) {
20514 copy_events[i] = NULL;
20515 ebuf = rec_error_add(ebuf,
"Filter_map points to invalid filter_init", -1, fm_tc);
20518 if (num_init_events > 1) copy_events = remove_nulls_from_filter_map(copy_events, &num_init_events);
20526 static char *add_filter_deinits(weed_plant_t *event_list,
ttable * trans_table,
void ***pchains,
20527 weed_timecode_t tc,
char *ebuf) {
20529 int i, j, num_params;
20532 weed_plant_t *init_event, *event;
20533 void **in_pchanges;
20536 if (!trans_table[i].out)
continue;
20537 if (trans_table[i].in != 0) {
20543 if ((num_params = weed_leaf_num_elements(init_event, WEED_LEAF_IN_PARAMETERS)) > 0) {
20544 in_pchanges = (
void **)
lives_malloc(num_params *
sizeof(
void *));
20545 for (j = 0; j < num_params; j++) {
20547 in_pchanges[j] = (weed_plant_t *)pchains[i][j];
20548 else in_pchanges[j] = NULL;
20550 weed_set_voidptr_array(event, WEED_LEAF_IN_PARAMETERS, num_params, in_pchanges);
20556 ebuf = rec_error_add(ebuf,
"Added missing filter_deinit", -1, tc);
20563 static char *add_null_filter_map(weed_plant_t *event_list, weed_plant_t *last_fm, weed_timecode_t tc,
char *ebuf) {
20573 ebuf = rec_error_add(ebuf,
"Added missing empty filter_map", -1, tc);
20578 static weed_plant_t *duplicate_frame_at(weed_plant_t *event_list, weed_plant_t *src_frame, weed_timecode_t tc) {
20584 clips = weed_get_int_array_counted(src_frame,
WEED_LEAF_CLIPS, &numframes);
20585 if (!numframes)
return src_frame;
20597 static LiVESList *atrack_list;
20599 static void add_atrack_to_list(
int track,
int clip) {
20601 LiVESList *alist = atrack_list;
20606 entry = (
char *)alist->data;
20607 array = lives_strsplit(entry,
"|", -1);
20608 if (atoi(array[0]) == track) {
20611 lives_strfreev(array);
20614 lives_strfreev(array);
20615 alist = alist->next;
20621 static void remove_atrack_from_list(
int track) {
20623 LiVESList *alist = atrack_list, *alist_next;
20628 alist_next = alist->next;
20629 entry = (
char *)alist->data;
20630 array = lives_strsplit(entry,
"|", -1);
20631 if (atoi(array[0]) == track) {
20632 atrack_list = lives_list_remove(atrack_list, entry);
20633 lives_strfreev(array);
20637 lives_strfreev(array);
20638 alist = alist_next;
20643 static char *add_missing_atrack_closers(weed_plant_t *event_list,
double fps,
char *ebuf) {
20644 LiVESList *alist = atrack_list;
20652 weed_plant_t *last_frame;
20654 weed_timecode_t tc;
20656 if (!atrack_list)
return ebuf;
20658 num_atracks = lives_list_length(atrack_list) * 2;
20667 weed_plant_t *shortcut = last_frame;
20672 entry = (
char *)alist->data;
20673 array = lives_strsplit(entry,
"|", -1);
20674 aclips[i] = atoi(array[0]);
20675 aclips[i + 1] = atoi(array[1]);
20677 aseeks[i + 1] = 0.;
20678 lives_strfreev(array);
20679 if (aclips[i] >= 0) ebuf = rec_error_add(ebuf,
"Added missing audio closure", aclips[i], tc);
20680 else ebuf = rec_error_add(ebuf,
"Added missing audio closure to backing track", -aclips[i], tc);
20682 alist = alist->next;
20697 static int64_t *get_int64_array_convert(weed_plant_t *plant,
const char *key) {
20698 if (weed_leaf_seed_type(plant, key) == WEED_SEED_INT) {
20700 int *ivals = weed_get_int_array_counted(plant, key, &nvals);
20701 if (!nvals)
return NULL;
20703 for (
int i = 0; i < nvals; i++) i64vals[i] = (int64_t)ivals[i];
20705 weed_leaf_delete(plant, key);
20706 weed_set_int64_array(plant, key, nvals, i64vals);
20709 return weed_get_int64_array(plant, key, NULL);
20722 weed_plant_t **ptmpls;
20723 weed_plant_t **ctmpls;
20726 weed_plant_t *shortcut = NULL;
20727 weed_plant_t *last_frame_event;
20728 weed_plant_t *last_filter_map = NULL;
20729 weed_plant_t *filter = NULL;
20730 weed_plant_t *last_event;
20732 weed_timecode_t tc = 0, last_tc = 0;
20733 weed_timecode_t last_frame_tc = -1;
20734 weed_timecode_t last_deinit_tc = -1;
20735 weed_timecode_t last_filter_map_tc = -1;
20736 weed_timecode_t cur_tc = 0;
20738 char *ebuf = lives_strdup(
"");
20741 char *bit1 = lives_strdup(
""), *bit2 = NULL, *bit3 = lives_strdup(
"."), *msg;
20742 int64_t *frame_index, *new_frame_index;
20744 int *clip_index, *aclip_index, *new_aclip_index;
20745 int *new_clip_index;
20747 int i, idx, filter_idx, j;
20749 int num_ctmpls, num_inct, num_outct;
20751 int num_init_events;
20753 int num_tracks, num_atracks;
20754 int last_valid_frame;
20757 int api_version = 100;
20760 boolean check_filter_map =
FALSE;
20761 boolean was_deleted =
FALSE;
20763 boolean missing_clips =
FALSE, missing_frames =
FALSE;
20764 boolean has_event_type;
20767 void **new_init_events;
20768 void **in_pchanges;
20772 double *aseek_index, *new_aseek_index;
20776 uint64_t *init_events;
20780 if (weed_plant_has_leaf(event_list, WEED_LEAF_FPS)) fps = weed_get_double_value(event_list, WEED_LEAF_FPS, NULL);
20784 if (mt) mt->layout_prompt =
FALSE;
20787 trans_table[i].
in = 0;
20788 trans_table[i].
out = NULL;
20793 atrack_list = NULL;
20796 was_deleted =
FALSE;
20798 if (!weed_plant_has_leaf(event, WEED_LEAF_TIMECODE)) {
20799 ebuf = rec_error_add(ebuf,
"Event has no timecode", weed_get_plant_type(event), -1);
20801 event = event_next;
20807 weed_set_int64_value(event, WEED_LEAF_TIMECODE, tc);
20813 if (weed_get_plant_type(event) != WEED_PLANT_EVENT) {
20814 ebuf = rec_error_add(ebuf,
"Invalid plant type", weed_get_plant_type(event), tc);
20816 event = event_next;
20819 if (tc < last_tc) {
20820 break_me(
"oo event in event_list_rectify");
20821 ebuf = rec_error_add(ebuf,
"Out of order event", -1, tc);
20823 event = event_next;
20826 has_event_type =
TRUE;
20827 if (!weed_plant_has_leaf(event, WEED_LEAF_EVENT_TYPE)) {
20828 has_event_type =
FALSE;
20829 if (api_version < 122) {
20831 weed_leaf_copy(event, WEED_LEAF_EVENT_TYPE, event,
WEED_LEAF_HINT);
20833 has_event_type =
TRUE;
20837 if (!has_event_type) {
20838 ebuf = rec_error_add(ebuf,
"Event has no event_type", weed_get_plant_type(event), tc);
20840 event = event_next;
20846 switch (event_type) {
20847 case WEED_EVENT_TYPE_FILTER_INIT:
20848 #ifdef DEBUG_TTABLE
20849 g_print(
"\n\ngot filter init %p\n", event);
20853 ebuf = rec_error_add(ebuf,
"Filter_init missing event_id", -1, tc);
20861 ebuf = rec_error_add(ebuf,
"Filter_init missing filter", -1, tc);
20863 was_deleted =
TRUE;
20868 if (weed_plant_has_leaf(filter, WEED_LEAF_IN_CHANNEL_TEMPLATES)) {
20870 ebuf = rec_error_add(ebuf,
"Filter_init missing filter", -1, tc);
20872 was_deleted =
TRUE;
20874 num_ctmpls = weed_leaf_num_elements(filter, WEED_LEAF_IN_CHANNEL_TEMPLATES);
20876 if (num_ctmpls != num_inct) {
20877 ebuf = rec_error_add(ebuf,
"Filter_init has invalid in_count", -1, tc);
20879 was_deleted =
TRUE;
20882 ctmpls = weed_get_plantptr_array(filter, WEED_LEAF_IN_CHANNEL_TEMPLATES, NULL);
20883 for (i = 0; i < num_ctmpls; i++) {
20886 ebuf = rec_error_add(ebuf,
"Filter_init disables a non-optional in channel", i, tc);
20888 was_deleted =
TRUE;
20890 if (thisct > 1 && (!weed_plant_has_leaf(ctmpls[i], WEED_LEAF_MAX_REPEATS) ||
20891 (weed_get_int_value(ctmpls[i], WEED_LEAF_MAX_REPEATS, NULL) > 0 &&
20892 weed_get_int_value(ctmpls[i], WEED_LEAF_MAX_REPEATS, NULL) < thisct))) {
20893 ebuf = rec_error_add(ebuf,
"Filter_init has too many repeats of in channel", i, tc);
20895 was_deleted =
TRUE;
20903 if (!was_deleted) {
20904 num_ctmpls = weed_leaf_num_elements(filter, WEED_LEAF_OUT_CHANNEL_TEMPLATES);
20906 if (num_ctmpls != num_outct) {
20907 ebuf = rec_error_add(ebuf,
"Filter_init has invalid out_count", -1, tc);
20909 was_deleted =
TRUE;
20912 ctmpls = weed_get_plantptr_array(filter, WEED_LEAF_OUT_CHANNEL_TEMPLATES, NULL);
20913 for (i = 0; i < num_ctmpls; i++) {
20916 ebuf = rec_error_add(ebuf,
"Filter_init disables a non-optional out channel", i, tc);
20918 was_deleted =
TRUE;
20920 if (thisct > 1 && (!weed_plant_has_leaf(ctmpls[i], WEED_LEAF_MAX_REPEATS) ||
20921 (weed_get_int_value(ctmpls[i], WEED_LEAF_MAX_REPEATS, NULL) > 0 &&
20922 weed_get_int_value(ctmpls[i], WEED_LEAF_MAX_REPEATS, NULL) < thisct))) {
20923 ebuf = rec_error_add(ebuf,
"Filter_init has too many repeats of out channel", i, tc);
20925 was_deleted =
TRUE;
20930 for (i = 0; i < ntracks; i++) {
20933 if (mt && !mt->opts.pertrack_audio) {
20935 mt->opts.pertrack_audio =
TRUE;
20936 }
else force_pertrack_audio =
TRUE;
20939 if (trax[i] == -1) {
20941 if (mt && mt->opts.back_audio_tracks == 0) {
20942 mt->opts.back_audio_tracks = 1;
20943 ebuf = rec_error_add(ebuf,
"Adding backing audio", -1, tc);
20944 }
else force_backing_tracks = 1;
20950 for (i = 0; i < ntracks; i++) {
20953 if (mt && !mt->opts.pertrack_audio) {
20955 mt->opts.pertrack_audio =
TRUE;
20956 }
else force_pertrack_audio =
TRUE;
20958 if (trax[i] == -1) {
20960 if (mt && mt->opts.back_audio_tracks == 0) {
20961 mt->opts.back_audio_tracks = 1;
20962 }
else force_backing_tracks = 1;
20970 if (mt && mt->avol_fx == -1) {
20974 if (LIVES_POINTER_TO_INT(clist->data) == filter_idx) {
20975 mt->avol_fx = filter_idx;
20976 mt->avol_init_event = event;
20979 clist = clist->next;
20987 lives_printerr(
"Layout contains unknown filter %s\n", filter_hash);
20988 ebuf = rec_error_add(ebuf,
"Layout contains unknown filter", -1, tc);
20990 was_deleted =
TRUE;
20991 if (mt) mt->layout_prompt =
TRUE;
20994 if (!was_deleted) {
20996 if (host_tag == -1) {
21008 event_id = (uint64_t)((weed_plant_t *)weed_get_voidptr_value(event,
WEED_LEAF_EVENT_ID, NULL));
21011 trans_table[idx].
out = event;
21012 #ifdef DEBUG_TTABLE
21013 g_print(
"adding lookup %"PRIu64" -> %p\n", event_id, event);
21017 if (weed_plant_has_leaf(event, WEED_LEAF_IN_PARAMETERS)) {
21018 num_params = weed_leaf_num_elements(event, WEED_LEAF_IN_PARAMETERS);
21019 pchains[idx] = (
void **)
lives_malloc((num_params + 1) *
sizeof(
void *));
21020 in_pchanges = (
void **)
lives_malloc(num_params *
sizeof(
void *));
21021 for (i = 0; i < num_params; i++) {
21022 pchains[idx][i] = event;
21023 in_pchanges[i] = NULL;
21025 pchains[idx][i] = NULL;
21027 weed_leaf_delete(event, WEED_LEAF_IN_PARAMETERS);
21028 weed_set_voidptr_array(event, WEED_LEAF_IN_PARAMETERS, num_params, in_pchanges);
21035 case WEED_EVENT_TYPE_FILTER_DEINIT:
21039 ebuf = rec_error_add(ebuf,
"Filter_deinit missing init_event", -1, tc);
21041 was_deleted =
TRUE;
21046 event_id = (uint64_t)((weed_plant_t *)weed_get_voidptr_value(event,
WEED_LEAF_INIT_EVENT, NULL));
21048 #ifdef DEBUG_TTABLE
21049 g_print(
"looking for %"PRIu64" in ttable\n", event_id);
21054 ebuf = rec_error_add(ebuf,
"Filter_deinit has invalid init_event", -1, tc);
21056 was_deleted =
TRUE;
21061 host_tag_s = weed_get_string_value((weed_plant_t *)init_event,
WEED_LEAF_HOST_TAG, NULL);
21062 host_tag = atoi(host_tag_s);
21065 if (idx < free_tt_key) free_tt_key = idx;
21068 check_filter_map =
TRUE;
21069 last_deinit_tc = tc;
21071 filter_hash = weed_get_string_value((weed_plant_t *)init_event,
WEED_LEAF_FILTER, NULL);
21073 if ((num_params = weed_leaf_num_elements((weed_plant_t *)init_event, WEED_LEAF_IN_PARAMETERS)) > 0) {
21074 in_pchanges = (
void **)
lives_malloc(num_params *
sizeof(
void *));
21075 for (i = 0; i < num_params; i++) {
21077 in_pchanges[i] = (weed_plant_t *)pchains[idx][i];
21078 else in_pchanges[i] = NULL;
21080 weed_leaf_delete(event, WEED_LEAF_IN_PARAMETERS);
21081 weed_set_voidptr_array(event, WEED_LEAF_IN_PARAMETERS, num_params, in_pchanges);
21090 case WEED_EVENT_TYPE_FILTER_MAP:
21098 init_events = (uint64_t *)
lives_malloc(num_init_events *
sizeof(uint64_t));
21099 for (i = 0; i < num_init_events; i++) init_events[i] = (uint64_t)pinit_events[i];
21103 new_init_events = (
void **)
lives_malloc(num_init_events *
sizeof(
void *));
21104 for (i = 0; i < num_init_events; i++) {
21105 event_id = (uint64_t)init_events[i];
21106 if (event_id != 0) {
21108 #ifdef DEBUG_TTABLE
21109 g_print(
"looking for %"PRIu64" in ttable, got %p\n", event_id, init_event);
21112 ebuf = rec_error_add(ebuf,
"Filter_map has invalid init_event", -1, tc);
21113 new_init_events[i] = NULL;
21114 }
else new_init_events[i] = init_event;
21115 }
else new_init_events[i] = NULL;
21117 new_init_events = remove_nulls_from_filter_map(new_init_events, &num_init_events);
21125 for (i = 0; i < num_init_events; i++) {
21137 if (last_filter_map) {
21141 was_deleted =
TRUE;
21146 was_deleted =
TRUE;
21148 if (!was_deleted) last_filter_map = event;
21151 case WEED_EVENT_TYPE_PARAM_CHANGE:
21153 ebuf = rec_error_add(ebuf,
"Param_change has no index", -1, tc);
21155 was_deleted =
TRUE;
21157 if (!weed_plant_has_leaf(event, WEED_LEAF_VALUE)) {
21158 ebuf = rec_error_add(ebuf,
"Param_change has no value", -1, tc);
21160 was_deleted =
TRUE;
21163 ebuf = rec_error_add(ebuf,
"Param_change has no init_event", -1, tc);
21165 was_deleted =
TRUE;
21170 event_id = (uint64_t)((weed_plant_t *)weed_get_voidptr_value(event,
WEED_LEAF_INIT_EVENT, NULL));
21172 #ifdef DEBUG_TTABLE
21173 g_print(
"pc looking for %"PRIu64" in ttable %d\n", event_id,
error);
21177 ebuf = rec_error_add(ebuf,
"Param_change has invalid init_event", -1, tc);
21179 was_deleted =
TRUE;
21181 filter_hash = weed_get_string_value((weed_plant_t *)init_event,
WEED_LEAF_FILTER, NULL);
21186 pnum >= (num_params = weed_leaf_num_elements((weed_plant_t *)init_event, WEED_LEAF_IN_PARAMETERS))) {
21187 ebuf = rec_error_add(ebuf,
"Param_change has invalid index", pnum, tc);
21189 was_deleted =
TRUE;
21191 ptmpls = weed_get_plantptr_array(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES, NULL);
21192 if (!weed_plant_has_leaf(event, WEED_LEAF_VALUE)) {
21193 ebuf = rec_error_add(ebuf,
"Param_change has no value with index", pnum, tc);
21195 was_deleted =
TRUE;
21197 if (weed_leaf_seed_type(event, WEED_LEAF_VALUE) != weed_leaf_seed_type(ptmpls[pnum], WEED_LEAF_DEFAULT)) {
21198 ebuf = rec_error_add(ebuf,
"Param_change has invalid seed type with index", pnum, tc);
21200 was_deleted =
TRUE;
21203 host_tag_s = weed_get_string_value((weed_plant_t *)init_event,
WEED_LEAF_HOST_TAG, NULL);
21204 host_tag = atoi(host_tag_s);
21208 if (pchains[idx][pnum] == init_event) {
21209 if (weed_leaf_seed_type((weed_plant_t *)init_event, WEED_LEAF_IN_PARAMETERS) == WEED_SEED_INT64) {
21211 uint64_t *orig_pchanges = (uint64_t *)weed_get_int64_array((weed_plant_t *)init_event,
21212 WEED_LEAF_IN_PARAMETERS, NULL);
21214 uint64_t *pin_pchanges = (uint64_t *)
lives_malloc(num_params *
sizeof(uint64_t));
21216 for (i = 0; i < num_params; i++) {
21217 if (orig_pchanges[i] == 0 && i == pnum) pin_pchanges[i] = (uint64_t)event;
21218 else pin_pchanges[i] = (uint64_t)orig_pchanges[i];
21221 weed_leaf_delete((weed_plant_t *)init_event, WEED_LEAF_IN_PARAMETERS);
21222 weed_set_int64_array((weed_plant_t *)init_event, WEED_LEAF_IN_PARAMETERS, num_params,
21223 (int64_t *)pin_pchanges);
21228 void **orig_pchanges = weed_get_voidptr_array((weed_plant_t *)init_event,
21229 WEED_LEAF_IN_PARAMETERS, NULL);
21230 void **pin_pchanges = (
void **)
lives_malloc(num_params *
sizeof(
void *));
21232 for (i = 0; i < num_params; i++) {
21233 if (!orig_pchanges[i] && i == pnum) pin_pchanges[i] = (
void *)event;
21234 else pin_pchanges[i] = (
void *)orig_pchanges[i];
21236 weed_leaf_delete((weed_plant_t *)init_event, WEED_LEAF_IN_PARAMETERS);
21237 weed_set_voidptr_array((weed_plant_t *)init_event, WEED_LEAF_IN_PARAMETERS, num_params, pin_pchanges);
21254 pchains[idx][pnum] = event;
21264 case WEED_EVENT_TYPE_FRAME:
21265 if (tc == last_frame_tc) {
21266 ebuf = rec_error_add(ebuf,
"Duplicate frame event", -1, tc);
21268 was_deleted =
TRUE;
21273 ebuf = rec_error_add(ebuf,
"Frame event missing clips at", -1, tc);
21276 last_frame_tc = tc;
21278 clip_index = weed_get_int_array_counted(event,
WEED_LEAF_CLIPS, &num_tracks);
21282 new_frame_index = (int64_t *)
lives_malloc(num_tracks * 8);
21283 last_valid_frame = 0;
21285 #ifdef DEBUG_MISSING_CLIPS
21286 g_print(
"pt zzz %d\n", num_tracks);
21288 for (i = 0; i < num_tracks; i++) {
21289 if (clip_index[i] > 0 && (clip_index[i] >
MAX_FILES || renumbered_clips[clip_index[i]] < 1 ||
21290 !
mainw->
files[renumbered_clips[clip_index[i]]])) {
21293 new_clip_index[i] = -1;
21294 new_frame_index[i] = 0;
21295 ebuf = rec_error_add(ebuf,
"Invalid clip number", clip_index[i], tc);
21297 #ifdef DEBUG_MISSING_CLIPS
21298 g_print(
"found invalid clip number %d on track %d, renumbered_clips=%d\n", clip_index[i], i,
21299 renumbered_clips[clip_index[i]]);
21301 missing_clips =
TRUE;
21304 if (clip_index[i] > 0 && frame_index[i] > 0) {
21305 int rclip = renumbered_clips[clip_index[i]];
21306 if (lfps[rclip] != 0.) {
21309 }
else new_frame_index[i] = frame_index[i];
21312 ebuf = rec_error_add(ebuf,
"Invalid frame number", new_frame_index[i], tc);
21313 new_clip_index[i] = -1;
21314 new_frame_index[i] = 0;
21315 missing_frames =
TRUE;
21321 else new_clip_index[i] = clip_index[i];
21322 new_frame_index[i] = frame_index[i];
21323 last_valid_frame = i + 1;
21326 new_clip_index[i] = clip_index[i];
21327 new_frame_index[i] = frame_index[i];
21328 last_valid_frame = i + 1;
21333 if (last_valid_frame == 0) {
21338 *new_clip_index = -1;
21339 *new_frame_index = 0;
21341 weed_set_int_array(event,
WEED_LEAF_CLIPS, num_tracks, new_clip_index);
21342 weed_set_int64_array(event,
WEED_LEAF_FRAMES, num_tracks, new_frame_index);
21344 if (last_valid_frame < num_tracks) {
21348 frame_index = (int64_t *)
lives_malloc(last_valid_frame * 8);
21349 for (i = 0; i < last_valid_frame; i++) {
21350 clip_index[i] = new_clip_index[i];
21351 frame_index[i] = new_frame_index[i];
21353 num_tracks = last_valid_frame;
21357 weed_set_int_array(event,
WEED_LEAF_CLIPS, num_tracks, new_clip_index);
21358 weed_set_int64_array(event,
WEED_LEAF_FRAMES, num_tracks, new_frame_index);
21370 if ((num_atracks & 1) != 0) {
21371 ebuf = rec_error_add(ebuf,
"Invalid number of audio_clips", -1, tc);
21377 ebuf = rec_error_add(ebuf,
"Invalid number of audio_seeks", -1, tc);
21386 for (i = 0; i < num_atracks; i += 2) {
21387 if (aclip_index[i + 1] > 0) {
21388 if ((aclip_index[i + 1] >
MAX_FILES || renumbered_clips[aclip_index[i + 1]] < 1 ||
21389 !
mainw->
files[renumbered_clips[aclip_index[i + 1]]]) && aseek_index[i + 1] != 0.) {
21391 ebuf = rec_error_add(ebuf,
"Invalid audio clip number", aclip_index[i + 1], tc);
21392 missing_clips =
TRUE;
21394 new_aclip_index[j] = aclip_index[i];
21395 new_aclip_index[j + 1] = aclip_index[i + 1];
21396 new_aseek_index[j] = aseek_index[i];
21397 new_aseek_index[j + 1] = aseek_index[i + 1];
21398 if (aseek_index[j + 1] != 0.) add_atrack_to_list(aclip_index[i], aclip_index[i + 1]);
21399 else remove_atrack_from_list(aclip_index[i]);
21403 if (aclip_index[i] > -1) {
21404 if (mt && !mt->opts.pertrack_audio) {
21405 mt->opts.pertrack_audio =
TRUE;
21408 ebuf = rec_error_add(ebuf,
"Adding pertrack audio", -1, tc);
21409 }
else force_pertrack_audio =
TRUE;
21412 if (aclip_index[i] == -1) {
21413 if (mt && mt->opts.back_audio_tracks == 0) {
21414 mt->opts.back_audio_tracks = 1;
21415 ebuf = rec_error_add(ebuf,
"Adding backing audio", -1, tc);
21416 }
else force_backing_tracks = 1;
21436 case WEED_EVENT_TYPE_MARKER:
21439 ebuf = rec_error_add(ebuf,
"Unknown marker type", -1, tc);
21441 was_deleted =
TRUE;
21446 ebuf = rec_error_add(ebuf,
"Unknown marker type", marker_type, tc);
21448 was_deleted =
TRUE;
21451 ebuf = rec_error_add(ebuf,
"Block start marker has no tracks", -1, tc);
21453 was_deleted =
TRUE;
21458 ebuf = rec_error_add(ebuf,
"Invalid event_type", event_type, tc);
21460 was_deleted =
TRUE;
21462 if (!was_deleted && check_filter_map && last_filter_map
21465 ebuf = filter_map_check(trans_table, last_filter_map, last_deinit_tc, tc, ebuf);
21466 check_filter_map =
FALSE;
21468 event = event_next;
21470 if (!was_deleted && fps != 0.) {
21471 while (cur_tc < last_frame_tc) {
21475 shortcut = duplicate_frame_at(event_list, shortcut, cur_tc);
21476 ebuf = rec_error_add(ebuf,
"Duplicated frame at", -1, cur_tc);
21479 ebuf = rec_error_add(ebuf,
"Inserted missing blank frame", -1, cur_tc);
21495 ebuf = add_filter_deinits(event_list, trans_table, pchains, last_tc, ebuf);
21498 if (last_filter_map) ebuf = add_null_filter_map(event_list, last_filter_map, last_tc, ebuf);
21506 ebuf = rec_error_add(ebuf,
"Removed final blank frames", -1, last_tc);
21513 last_frame_tc = last_filter_map_tc = -1;
21514 last_frame_event = NULL;
21522 switch (event_type) {
21523 case WEED_EVENT_TYPE_FILTER_INIT:
21525 if (weed_plant_has_leaf(event, WEED_LEAF_IN_PARAMETERS)) {
21526 uint64_t *pin_params;
21528 num_params = weed_leaf_num_elements(event, WEED_LEAF_IN_PARAMETERS);
21530 if (weed_leaf_seed_type(event, WEED_LEAF_IN_PARAMETERS) == WEED_SEED_INT64) {
21531 pin_params = (uint64_t *)weed_get_int64_array(event, WEED_LEAF_IN_PARAMETERS, NULL);
21532 nin_params = (
void **)
lives_malloc(num_params *
sizeof(
void *));
21533 for (i = 0; i < num_params; i++) {
21534 nin_params[i] = (
void *)pin_params[i];
21537 weed_leaf_delete(event, WEED_LEAF_IN_PARAMETERS);
21538 weed_set_voidptr_array(event, WEED_LEAF_IN_PARAMETERS, num_params, nin_params);
21553 if (mt && event != mt->avol_init_event) {
21557 case WEED_EVENT_TYPE_PARAM_CHANGE:
21560 case WEED_EVENT_TYPE_FILTER_DEINIT:
21565 case WEED_EVENT_TYPE_FILTER_MAP:
21566 if (last_filter_map_tc == tc) {
21568 ebuf = rec_error_add(ebuf,
"Duplicate filter maps", -1, tc);
21571 last_filter_map_tc = tc;
21572 last_filter_map = event;
21574 case WEED_EVENT_TYPE_FRAME:
21575 last_frame_tc = tc;
21576 last_filter_map_tc = -1;
21577 last_frame_event = event;
21581 if (last_frame_event)
event = last_frame_event;
21583 }
else event = event_next;
21586 ebuf = add_missing_atrack_closers(event_list, fps, ebuf);
21588 if (missing_clips && missing_frames) {
21589 bit2 = (
_(
"clips and frames"));
21591 if (missing_clips) {
21592 bit2 = (
_(
"clips"));
21593 }
else if (missing_frames) {
21594 bit2 = (
_(
"frames"));
21601 if (mt && mt->auto_reloading) {
21604 bit1 = (
_(
"\nAuto reload layout.\n"));
21607 msg =
lives_strdup_printf(
_(
"%s\nSome %s are missing from the layout%s\nTherefore it could not be loaded properly.\n"),
21612 if (mt) mt->layout_prompt =
TRUE;
21625 LiVESWidget *ar_checkbutton;
21627 boolean needs_idlefunc =
FALSE;
21628 boolean did_backup = mt->did_backup;
21634 char *startdir = NULL;
21637 LIVES_ERROR(
"Loading event list for unknown set");
21650 startdir = lives_strdup(eload_dir);
21654 if (allow_auto_reload) {
21656 lives_signal_sync_connect(LIVES_GUI_OBJECT(ar_checkbutton), LIVES_WIDGET_TOGGLED_SIGNAL,
21661 if (mt->idlefunc > 0) {
21664 needs_idlefunc =
TRUE;
21669 eload_file =
choose_file(startdir, NULL, filt, LIVES_FILE_CHOOSER_ACTION_OPEN, NULL, hbox);
21683 if (needs_idlefunc || (!did_backup && mt->auto_changed))
21697 weed_plant_t *event_list = NULL;
21702 boolean free_eload_file =
TRUE;
21704 boolean retval =
TRUE;
21705 boolean needs_idlefunc =
FALSE;
21707 int num_events = 0;
21713 old_avol_fx = mt->avol_fx;
21714 if (mt->idlefunc > 0) {
21717 needs_idlefunc =
TRUE;
21724 if (needs_idlefunc) mt->idlefunc =
mt_idle_add(mt);
21727 }
else free_eload_file =
FALSE;
21733 else eload_name = (
_(
"auto backup"));
21740 if (needs_idlefunc) mt->idlefunc =
mt_idle_add(mt);
21753 mt->event_list = NULL;
21758 d_print(
_(
"Loading layout from %s..."), eload_name);
21766 if ((event_list = load_event_list_inner(mt, fd, mt != NULL, &num_events, NULL, NULL)) == NULL) {
21769 if (
THREADVAR(read_failed) == fd + 1) {
21775 if (mt && retval != LIVES_RESPONSE_RETRY) {
21778 if (needs_idlefunc) mt->idlefunc =
mt_idle_add(mt);
21785 renumber_from_backup_layout_numbering(NULL);
21796 }
while (retval == LIVES_RESPONSE_RETRY);
21802 d_print(
_(
"Got %d events...processing..."), num_events);
21807 cfile->progress_start = 1;
21808 cfile->progress_end = num_events;
21818 rerenumber_clips(eload_file, NULL);
21820 renumber_from_backup_layout_numbering(mt);
21823 mt->avol_init_event = NULL;
21837 d_print(
_(
"%d errors detected.\n"), elist_errors);
21838 if (!mt->auto_reloading) {
21851 if (fd < 0 || !retval) {
21855 }
while (retval2 == LIVES_RESPONSE_RETRY);
21860 mt->layout_prompt =
FALSE;
21868 if (mt->avol_fx != old_avol_fx && mt->opts.aparam_view_list) {
21870 lives_list_free(mt->opts.aparam_view_list);
21871 mt->opts.aparam_view_list = NULL;
21876 lives_snprintf(mt->layout_name,
PATH_MAX,
"%s", eload_file);
21880 if (mt->layout_set_properties) msg = mt_set_vals_string();
21901 set_audio_filter_channel_values(mt);
21904 if (mt->opts.back_audio_tracks > 0) {
21908 if (free_eload_file)
lives_free(eload_file);
21914 return (event_list);
21920 weed_plant_t *event_next;
21931 event = event_next;
21939 if (mt->idlefunc > 0) {
21959 mt->event_list = NULL;
21972 lives_mt *mt = (lives_mt *)user_data;
21977 boolean rev_resp =
FALSE;
21979 if (mt->idlefunc > 0) {
21984 if (*mt->layout_name) {
22000 if (resp == 2 && rev_resp) {
22005 }
while (resp == 2 && rev_resp);
22010 if (resp == LIVES_RESPONSE_CANCEL) {
22015 if (resp == 2 && !rev_resp) {
22019 if (!
do_yesno_dialog(
"\nLayout will be deleted from the disk.\nAre you sure ?\n")) {
22032 _(
"The current layout has changes which have not been saved.\nAre you sure you wish to wipe it ?\n"),
22047 lives_mt *mt = (lives_mt *)user_data;
22048 weed_plant_t *new_event_list;
22053 if (mt->idlefunc > 0) {
22062 if (!new_event_list) {
22069 mt->event_list = NULL;
22071 mt->undo_buffer_used = 0;
22072 mt->undo_offset = 0;
22073 lives_list_free(mt->undos);
22078 for (i = 0; i < mt->num_video_tracks; i++) {
22081 lives_list_free(mt->video_draws);
22082 mt->video_draws = NULL;
22083 mt->num_video_tracks = 0;
22088 mt->audio_draws = NULL;
22090 if (mt->audio_vols) lives_list_free(mt->audio_vols);
22091 mt->audio_vols = NULL;
22093 mt->event_list = new_event_list;
22095 if (mt->selected_tracks) lives_list_free(mt->selected_tracks);
22096 mt->selected_tracks = NULL;
22100 if (!mt->ignore_load_vals) set_audio_mixer_vols(mt, mt->event_list);
22132 weed_plant_t *event_list;
22134 boolean retval =
TRUE;
22136 char *changefrom = NULL;
22139 if (old_set_name) {
22141 chlen = strlen(changefrom);
22145 if (old_set_name) {
22151 if ((event_list = load_event_list_inner(NULL, fd,
FALSE, NULL, NULL, NULL)) != NULL) {
22165 if (fd < 0 || !retval) {
22169 }
while (retval2 == LIVES_RESPONSE_RETRY);
22177 }
while (retval2 == LIVES_RESPONSE_RETRY);
22180 if (old_set_name && !
lives_strncmp((
char *)map->data, changefrom, chlen)) {
22183 if (lives_file_test(tmp, LIVES_FILE_TEST_EXISTS)) {
22187 prefs->
workdir, new_set_name, old_set_name, (
char *)map->data + chlen);
22188 lives_mv((
const char *)map->data, tmp);
22203 if ((old_set_name && !
lives_strncmp((
char *)map->data, changefrom, chlen)) ||
22204 (!old_set_name && (strstr((
char *)map->data, new_set_name) == NULL))) {
22206 char **array = lives_strsplit((
char *)map->data,
"|", -1);
22207 size_t origlen = strlen(array[0]);
22209 if (lives_file_test(tmp2, LIVES_FILE_TEST_EXISTS)) {
22211 prefs->
workdir, new_set_name, old_set_name, array[0] + chlen);
22215 lives_strfreev(array);
22228 if ((old_set_name && !
lives_strncmp((
char *)map->data, changefrom, chlen)) ||
22229 (!old_set_name && (strstr((
char *)map->data, new_set_name) == NULL))) {
22232 if (lives_file_test(tmp, LIVES_FILE_TEST_EXISTS)) {
22235 prefs->
workdir, new_set_name, old_set_name, (
char *)map->data + chlen);
22254 int resampled_frame;
22260 if (start <= resampled_frame && (end == 0 || end >= resampled_frame))
22265 array = lives_strsplit((
char *)lmap->data,
"|", -1);
22266 if (atoi(array[2]) != 0) {
22267 orig_fps = strtod(array[3], NULL);
22269 if (array[2] == 0) resampled_frame = 0;
22270 if (start <= resampled_frame && (end == 0 || end >= resampled_frame))
22273 lives_strfreev(array);
22295 (etime == 0. || etime <= mainw->files[clipno]->stored_layout_audio))
22301 array = lives_strsplit((
char *)lmap->data,
"|", -1);
22302 max_time = strtod(array[4], NULL);
22303 if (max_time > 0. && stime <= max_time && (etime == 0. || etime <= mainw->files[clipno]->stored_layout_audio)) {
22306 lives_strfreev(array);
22315 lives_mt *mt = (lives_mt *)user_data;
22331 LiVESWidget *dialog;
22332 lives_mt *mt = (lives_mt *)user_data;
22341 lives_mt *mt = (lives_mt *)user_data;
22342 mt->ignore_load_vals = !mt->ignore_load_vals;
22346 static void mt_ac_audio_toggled(LiVESMenuItem * menuitem, livespointer user_data) {
22347 lives_mt *mt = (lives_mt *)user_data;
22348 mt->opts.autocross_audio = !mt->opts.autocross_audio;
22353 lives_mt *mt = (lives_mt *)user_data;
22380 xachans = xarate = xasamps = 0;
22384 if (response == LIVES_RESPONSE_CANCEL) {
22392 if (xachans == 0 && mt->audio_draws) {
22393 LiVESList *slist = mt->audio_draws;
22395 if (lives_widget_object_get_data(LIVES_WIDGET_OBJECT(slist->data),
"blocks")) {
22403 slist = slist->next;
22440 mt->user_arate = xarate;
22441 mt->user_achans = xachans;
22442 mt->user_asamps = xasamps;
22443 mt->user_signed_endian = xse;
22459 mt->audio_draws = NULL;
22463 if (mt->audio_vols) lives_list_free(mt->audio_vols);
22464 mt->audio_vols = NULL;
22471 if (mt->current_track >= 0) {
22475 mt->auto_changed =
TRUE;
22477 mt->changed =
TRUE;
22481 static uint32_t event_list_get_byte_size(lives_mt * mt, weed_plant_t *event_list,
boolean nxprev,
int *num_events) {
22489 int tot_events = 0;
22500 leaves = weed_plant_list_leaves(event, NULL);
22502 for (i = 0; leaves[i]; i++) {
22507 tot += 4 * 3 + strlen(leaves[i]);
22508 ne = weed_leaf_num_elements(event, leaves[i]);
22509 st = weed_leaf_seed_type(event, leaves[i]);
22511 for (j = 0; j < ne; j++) tot += 4 + (st > 64 ? 8 : weed_leaf_element_size(event, leaves[i], j));
22518 event = event_list;
22519 leaves = weed_plant_list_leaves(event, NULL);
22521 for (i = 0; leaves[i]; i++) {
22522 tot += 4 * 3 + strlen(leaves[i]);
22523 ne = weed_leaf_num_elements(event, leaves[i]);
22524 st = weed_leaf_seed_type(event, leaves[i]);
22526 for (j = 0; j < ne; j++) tot += 4 + (st > 64 ? 8 : weed_leaf_element_size(event, leaves[i], j));
22531 if (num_events) *num_events = tot_events;
22537 lives_amixer_t *amixer = mt->amixer;
22546 for (
int i = 0; i < amixer->nchans; i++) {
22549 val = giw_vslider_get_value(GIW_VSLIDER(amixer->ch_sliders[i]));
22566 if (mt->audio_vols_back) lives_list_free(mt->audio_vols_back);
22571 static void on_amixer_reset_clicked(LiVESButton * button, lives_mt * mt) {
22572 lives_amixer_t *amixer = mt->amixer;
22582 for (i = 0; i < amixer->nchans; i++) {
22583 float val = (float)LIVES_POINTER_TO_INT(lives_list_nth_data(mt->audio_vols_back, i)) /
LIVES_AVOL_SCALE;
22589 giw_vslider_set_value(GIW_VSLIDER(amixer->ch_sliders[i]), val);
22605 static void after_amixer_gang_toggled(LiVESToggleButton * toggle, lives_amixer_t *amixer) {
22611 lives_amixer_t *amixer = mt->amixer;
22612 int layer = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(adj),
"layer"));
22620 GiwVSlider *slider = GIW_VSLIDER(amixer->ch_sliders[layer]);
22621 val = giw_vslider_get_value(slider);
22625 LiVESRange *range = LIVES_RANGE(amixer->ch_sliders[layer]);
22634 for (i = mt->opts.back_audio_tracks; i < amixer->nchans; i++) {
22638 giw_vslider_set_value(GIW_VSLIDER(amixer->ch_sliders[i]), val);
22649 if (inv && mt->opts.back_audio_tracks > 0) {
22653 giw_vslider_set_value(GIW_VSLIDER(amixer->ch_sliders[0]), 1. - val < 0. ? 0. : 1. - val);
22666 for (i = 1; i < amixer->nchans; i++) {
22670 giw_vslider_set_value(GIW_VSLIDER(amixer->ch_sliders[i]), 1. - val < 0. ? 0. : 1. - val);
22672 amixer->ch_slider_fns[i]);
22678 amixer->ch_slider_fns[i]);
22686 if (!mt->is_rendering) {
22698 LiVESWidgetObject *adj;
22699 LiVESWidget *spinbutton;
22700 LiVESWidget *label;
22702 lives_amixer_t *amixer = mt->amixer;
22705 i += mt->opts.back_audio_tracks;
22711 amixer->ch_sliders[i] = giw_vslider_new(LIVES_ADJUSTMENT(adj));
22712 giw_vslider_set_legends_digits(GIW_VSLIDER(amixer->ch_sliders[i]), 1);
22713 giw_vslider_set_major_ticks_number(GIW_VSLIDER(amixer->ch_sliders[i]), 5);
22714 giw_vslider_set_minor_ticks_number(GIW_VSLIDER(amixer->ch_sliders[i]), 4);
22728 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(amixer->ch_sliders[i]),
"adj", adj);
22729 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(adj),
"layer", LIVES_INT_TO_POINTER(i));
22731 amixer->ch_slider_fns[i] = lives_signal_sync_connect_after(LIVES_GUI_OBJECT(adj), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
22742 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(amixer->ch_sliders[i]),
"label", label);
22749 gtk_spin_button_set_adjustment(LIVES_SPIN_BUTTON(spinbutton), LIVES_ADJUSTMENT(adj));
22758 lives_mt *mt = (lives_mt *)user_data;
22759 LiVESWidget *amixerw;
22760 LiVESWidget *top_vbox;
22762 LiVESWidget *vbox2;
22764 LiVESWidget *hbuttonbox;
22765 LiVESWidget *scrolledwindow;
22766 LiVESWidget *label;
22767 LiVESWidget *filler;
22768 LiVESWidget *eventbox;
22769 LiVESWidget *close_button;
22770 LiVESWidget *reset_button;
22773 lives_amixer_t *amixer;
22775 int nachans = lives_list_length(mt->audio_draws);
22782 if (nachans == 0)
return;
22789 mt->audio_vols_back = lives_list_copy(mt->audio_vols);
22791 amixer = mt->amixer = (lives_amixer_t *)
lives_malloc(
sizeof(lives_amixer_t));
22792 amixer->nchans = 0;
22794 amixer->ch_sliders = (LiVESWidget **)
lives_malloc(nachans *
sizeof(LiVESWidget *));
22829 LIVES_RESPONSE_RESET);
22834 LIVES_RESPONSE_OK);
22842 LIVES_KEY_m, LIVES_CONTROL_MASK,
22843 (LiVESAccelFlags)0);
22847 if (mt->opts.back_audio_tracks > 0) {
22863 #if GTK_CHECK_VERSION(3, 0, 0)
22864 lives_signal_sync_connect(LIVES_GUI_OBJECT(amixer->inv_checkbutton), LIVES_WIDGET_EXPOSE_EVENT,
22871 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(amixer->inv_checkbutton), LIVES_WIDGET_TOGGLED_SIGNAL,
22879 if (mt->opts.back_audio_tracks > 0 && mt->opts.pertrack_audio) {
22888 lives_signal_sync_connect(LIVES_GUI_OBJECT(eventbox), LIVES_WIDGET_BUTTON_PRESS_EVENT,
22890 amixer->inv_checkbutton);
22906 #if GTK_CHECK_VERSION(3, 0, 0)
22907 lives_signal_sync_connect(LIVES_GUI_OBJECT(amixer->gang_checkbutton), LIVES_WIDGET_EXPOSE_EVENT,
22915 if (mt->opts.pertrack_audio) {
22923 lives_signal_sync_connect(LIVES_GUI_OBJECT(eventbox), LIVES_WIDGET_BUTTON_PRESS_EVENT,
22925 amixer->gang_checkbutton);
22942 for (
register int i = 0; i < nachans - mt->opts.back_audio_tracks; i++) {
22947 lives_signal_sync_connect(LIVES_GUI_OBJECT(close_button), LIVES_WIDGET_CLICKED_SIGNAL,
22951 lives_signal_sync_connect(LIVES_GUI_OBJECT(reset_button), LIVES_WIDGET_CLICKED_SIGNAL,
22952 LIVES_GUI_CALLBACK(on_amixer_reset_clicked),
22956 LIVES_KEY_Escape, (LiVESXModifierType)0, (LiVESAccelFlags)0);
22958 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(amixer->gang_checkbutton), LIVES_WIDGET_TOGGLED_SIGNAL,
22959 LIVES_GUI_CALLBACK(after_amixer_gang_toggled),
22960 (livespointer)amixer);
22961 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(amixer->gang_checkbutton), LIVES_WIDGET_TOGGLED_SIGNAL,
22966 after_amixer_gang_toggled(LIVES_TOGGLE_BUTTON(amixer->gang_checkbutton), amixer);
22970 on_amixer_reset_clicked(NULL, mt);
22982 LiVESWidget *eventbox = NULL;
22985 eventbox = (LiVESWidget *)lives_list_nth_data(mt->video_draws, ntrack);
22987 eventbox = (LiVESWidget *)lives_list_nth_data(mt->audio_draws, 1 - ntrack);
22994 static track_rect *get_nth_block_for_track(lives_mt * mt,
int itrack,
int iblock) {
22998 if (!eventbox)
return NULL;
22999 block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks");
23001 if (count == iblock)
return block;
23002 block = block->next;
23016 if (!mt || uid == 0l)
return NULL;
23018 list = mt->video_draws;
23021 block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(list->data),
"blocks");
23023 if (block->uid == uid)
return block;
23024 block = block->next;
23028 list = mt->audio_draws;
23031 block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(list->data),
"blocks");
23033 if (block->uid == uid)
return block;
23034 block = block->next;
23043 if (ntrack >= 0 && mt->video_draws && ntrack < lives_list_length(mt->video_draws))
return TRUE;
23049 if (ntrack <= 0 && mt->audio_draws && ntrack >= -(lives_list_length(mt->audio_draws)))
return TRUE;
23055 int track = mt->current_track;
23056 track_rect *lastblock;
23058 if (!eventbox)
return 0l;
23059 lastblock = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"block_last");
23060 if (!lastblock)
return 0l;
23061 return lastblock->uid;
23067 track_rect *block, *lastblock;
23069 if (!eventbox)
return -1;
23070 lastblock = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"block_last");
23071 if (!lastblock)
return -1;
23072 block = (track_rect *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(eventbox),
"blocks");
23074 if (block == lastblock)
break;
23075 block = block->next;
23085 track_rect *block = get_nth_block_for_track(mt, ntrack, iblock);
23086 if (!block)
return -1;
23093 track_rect *block = get_nth_block_for_track(mt, ntrack, iblock);
23094 if (!block)
return -1;
23101 if (!mt)
return NULL;
23103 return get_block_from_time(ebox, time, mt);
23109 if (!block)
return -1;
23122 track_rect *oblock = NULL;
23123 weed_timecode_t sttc, endtc = 0;
23125 weed_plant_t **ptmpls;
23126 weed_plant_t **oparams;
23128 weed_plant_t *stevent, *enevent;
23129 weed_plant_t *filter;
23131 weed_plant_t *old_mt_init = mt->init_event;
23135 double region_start = mt->region_start;
23136 double region_end = mt->region_end;
23138 boolean did_backup =
FALSE;
23140 int nvids = lives_list_length(mt->video_draws);
23141 int current_fx = mt->current_fx;
23150 if (!block)
return;
23156 if (tparam == -1)
return;
23159 ptm = ptmpls[tparam];
23170 slist = lives_list_copy(mt->selected_tracks);
23172 if (mt->selected_tracks) {
23173 lives_list_free(mt->selected_tracks);
23174 mt->selected_tracks = NULL;
23177 for (i = 0; i < nvids; i++) {
23178 if (i == track)
continue;
23179 oblock = get_block_from_time((LiVESWidget *)lives_list_nth_data(mt->video_draws, i),
23186 }
else oblock = NULL;
23190 mt->is_atrans =
TRUE;
23193 mt->selected_tracks = lives_list_append(mt->selected_tracks, LIVES_INT_TO_POINTER(track));
23194 mt->selected_tracks = lives_list_append(mt->selected_tracks, LIVES_INT_TO_POINTER(i));
23202 oparams = (weed_plant_t **)weed_get_voidptr_array_counted(mt->init_event, WEED_LEAF_IN_PARAMETERS, &nparams);
23204 for (i = 0; i < nparams; i++) {
23205 if (weed_get_int_value(oparams[i],
WEED_LEAF_INDEX, NULL) == tparam)
break;
23208 stevent = oparams[i];
23210 enevent = weed_plant_new(WEED_PLANT_EVENT);
23211 weed_set_int_value(enevent, WEED_LEAF_EVENT_TYPE, WEED_EVENT_TYPE_PARAM_CHANGE);
23212 weed_set_int64_value(enevent, WEED_LEAF_TIMECODE, endtc);
23222 if (param_type == WEED_PARAM_INTEGER) {
23223 int min = weed_get_int_value(ptm, WEED_LEAF_MIN, NULL);
23224 int max = weed_get_int_value(ptm, WEED_LEAF_MAX, NULL);
23225 weed_set_int_value(stevent, WEED_LEAF_VALUE, i < track ? min : max);
23226 weed_set_int_value(enevent, WEED_LEAF_VALUE, i < track ? max : min);
23228 double min = weed_get_double_value(ptm, WEED_LEAF_MIN, NULL);
23229 double max = weed_get_double_value(ptm, WEED_LEAF_MAX, NULL);
23230 weed_set_double_value(stevent, WEED_LEAF_VALUE, i < track ? min : max);
23231 weed_set_double_value(enevent, WEED_LEAF_VALUE, i < track ? max : min);
23243 if (mt->selected_tracks) {
23244 lives_list_free(mt->selected_tracks);
23245 mt->selected_tracks = NULL;
23248 for (i = 0; i < nvids; i++) {
23249 if (i == track)
continue;
23250 oblock = get_block_from_time((LiVESWidget *)lives_list_nth_data(mt->video_draws, i),
23261 mt->selected_tracks = lives_list_append(mt->selected_tracks, LIVES_INT_TO_POINTER(track));
23262 mt->selected_tracks = lives_list_append(mt->selected_tracks, LIVES_INT_TO_POINTER(i));
23270 oparams = (weed_plant_t **)weed_get_voidptr_array_counted(mt->init_event, WEED_LEAF_IN_PARAMETERS, &nparams);
23272 for (i = 0; i < nparams; i++) {
23273 if (weed_get_int_value(oparams[i],
WEED_LEAF_INDEX, NULL) == tparam)
break;
23276 stevent = oparams[i];
23278 enevent = weed_plant_new(WEED_PLANT_EVENT);
23279 weed_set_int_value(enevent, WEED_LEAF_EVENT_TYPE, WEED_EVENT_TYPE_PARAM_CHANGE);
23290 if (param_type == WEED_PARAM_INTEGER) {
23291 int min = weed_get_int_value(ptm, WEED_LEAF_MIN, NULL);
23292 int max = weed_get_int_value(ptm, WEED_LEAF_MAX, NULL);
23293 weed_set_int_value(stevent, WEED_LEAF_VALUE, i < track ? max : min);
23294 weed_set_int_value(enevent, WEED_LEAF_VALUE, i < track ? min : max);
23296 double min = weed_get_double_value(ptm, WEED_LEAF_MIN, NULL);
23297 double max = weed_get_double_value(ptm, WEED_LEAF_MAX, NULL);
23298 weed_set_double_value(stevent, WEED_LEAF_VALUE, i < track ? max : min);
23299 weed_set_double_value(enevent, WEED_LEAF_VALUE, i < track ? min : max);
23307 if (mt->init_event && mt->opts.autocross_audio)
23310 mt->is_atrans =
FALSE;
23311 mt->region_start = region_start;
23312 mt->region_end = region_end;
23313 lives_list_free(mt->selected_tracks);
23314 mt->selected_tracks = lives_list_copy(slist);
23315 if (slist) lives_list_free(slist);
23316 mt->current_fx = current_fx;
23317 mt->init_event = old_mt_init;
23321 mt->changed = mt->auto_changed =
TRUE;
23322 mt->did_backup = did_backup;