1 // multitrack.h
2 // LiVES
3 // (c) G. Finch 2005 - 2017 <salsaman+lives@gmail.com>
4 // released under the GNU GPL 3 or later
5 // see file ../COPYING for licensing details
6 
7 // multitrack window
8 
9 #ifndef HAS_LIVES_MULTITRACK_H
10 #define HAS_LIVES_MULTITRACK_H
11 
12 ////////////////////// GUI constants ///////////////////////
13 
14 #define CLIP_THUMB_WIDTH ((int)(72.*widget_opts.scale))
15 #define CLIP_THUMB_HEIGHT ((int)(72.*widget_opts.scale))
16 
17 #define CLIP_LABEL_LENGTH ((int)(20.*widget_opts.scale))
18 
19 #define BLOCK_THUMB_WIDTH ((int)(40.*widget_opts.scale))
20 
21 #define MT_PLAY_WIDTH_SMALL ((int)(320.*widget_opts.scale))
22 #define MT_PLAY_HEIGHT_SMALL ((int)(216.*widget_opts.scale))
23 
24 #define MT_PLAY_WIDTH_EXP ((int)(432.*widget_opts.scale))
25 #define MT_PLAY_HEIGHT_EXP ((int)(324.*widget_opts.scale))
26 
27 #define MT_CTX_WIDTH ((int)(320.*widget_opts.scale))
28 #define MT_CTX_HEIGHT ((int)(220.*widget_opts.scale))
29 
30 #define FX_BLOCK_WIDTH ((int)(80.*widget_opts.scale))
31 #define FX_BLOCK_HEIGHT ((int)(20.*widget_opts.scale))
32 
33 #define MT_TRACK_HEIGHT ((int)(35.*widget_opts.scale))
34 
35 #define TIMECODE_LENGTH 14 ///< length of timecode text entry, must be > 12
36 
37 #define TIMELINE_TABLE_COLUMNS 40
38 
39 #define MENUBAR_MIN 1024
40 
41 #define PEB_WRATIO 3. ///< preview eventbox width ratio (fraction of screen width)
42 #define PEB_HRATIO 3. ///< preview eventbox height ratio (fraction of screen height)
43 
44 #define AMIXER_WRATIO 2. / 3. ///< audio mixer width ratio (fraction of screen width)
45 #define AMIXER_HRATIO 2. / 3. ///< audio mixer height ratio (fraction of screen height)
46 
47 ////////////////////////////////////////////////////////////////////////////////
48 
49 #define MT_INOUT_TIME 10000 ///< min milliseconds to save autobackup when changing in / out spins
50 
51 #define BLOCK_DRAW_SIMPLE 1
52 #define BLOCK_DRAW_THUMB 2
53 #define BLOCK_DRAW_TYPE BLOCK_DRAW_THUMB
54 
55 #define SELBLOCK_ALPHA 0.6
56 
57 #define DEF_TIME 120 ///< default seconds when there is no event_list
58 
59 #define DEF_AUTOTRANS "simple_blend|chroma blend|salsaman"
60 
61 typedef struct _mt lives_mt;
62 
63 typedef struct _track_rect track_rect;
64 
65 typedef struct _mt_opts mt_opts;
66 
67 typedef struct _lives_amixer_t lives_amixer_t;
68 
69 typedef enum {
70   MOUSE_MODE_MOVE,
71   MOUSE_MODE_SELECT,
72   MOUSE_MODE_COPY
73 } lives_mt_mouse_mode_t;
74 
75 typedef enum {
76   INSERT_MODE_NORMAL,  ///< the default (only insert if it fits)
77 
78   // not implemented yet
79   INSERT_MODE_OVERWRITE, ///< overwite existing blocks
80   INSERT_MODE_FLEX, ///< stretch first gap to fit block
81   INSERT_MODE_FILL, ///< insert enough to fill gap (from selection start or end depending on gravity)
82 } lives_mt_insert_mode_t;
83 
84 typedef enum {
85   GRAV_MODE_NORMAL,
86   GRAV_MODE_LEFT,
87   GRAV_MODE_RIGHT
88 } lives_mt_grav_mode_t;
89 
90 typedef enum {
91   // undo actions
92   /// no event_list
93   MT_UNDO_NONE = 0,
94   MT_UNDO_INSERT_BLOCK = 1,
95   MT_UNDO_INSERT_AUDIO_BLOCK = 2,
96 
97   // minimal event_list
98   MT_UNDO_APPLY_FILTER = 512,
99   MT_UNDO_DELETE_FILTER = 513,
100   MT_UNDO_SPLIT = 514,
101   MT_UNDO_SPLIT_MULTI = 515,
102   MT_UNDO_FILTER_MAP_CHANGE = 516,
103 
104   // full backups of event_list
105   MT_UNDO_DELETE_BLOCK = 1024,
106   MT_UNDO_MOVE_BLOCK = 1025,
107   MT_UNDO_REMOVE_GAPS = 1026,
108   MT_UNDO_DELETE_AUDIO_BLOCK = 1027,
109   MT_UNDO_MOVE_AUDIO_BLOCK = 1028,
110   MT_UNDO_INSERT_GAP = 1029
111 } lives_mt_undo_t;
112 
113 typedef enum {
114   NB_ERROR_SEL,
115   NB_ERROR_NOEFFECT,
116   NB_ERROR_NOTRANS,
117   NB_ERROR_NOCOMP,
118   NB_ERROR_NOCLIP
119 } lives_mt_nb_error_t;
120 
121 typedef enum {
122   POLY_NONE = 0,
123   POLY_CLIPS,
124   POLY_IN_OUT,
125   POLY_FX_STACK,
126   POLY_PARAMS,
127   POLY_EFFECTS,
128   POLY_TRANS,
129   POLY_COMP
130 } lives_mt_poly_state_t;
131 
132 typedef enum {
133   MT_LAST_FX_NONE = 0,
134   MT_LAST_FX_BLOCK,
135   MT_LAST_FX_REGION
136 } lives_mt_last_fx_type_t;
137 
138 typedef enum {
139   FX_ORD_NONE = 0,
140   FX_ORD_BEFORE,
141   FX_ORD_AFTER
142 } lives_mt_fx_order_t;
143 
144 typedef enum {
145   // block state
146   BLOCK_UNSELECTED = 0,
147   BLOCK_SELECTED
148 } lives_mt_block_state_t;
149 
150 struct _mt_opts {
151   boolean set; ///< have we set opts (in mainw) ?
152   boolean move_effects; ///< should we move effects attached to a block ?
153   boolean fx_auto_preview;
154   boolean snap_over; ///< snap to overlap
155   lives_mt_grav_mode_t grav_mode;
156   lives_mt_mouse_mode_t mouse_mode;
157   lives_mt_insert_mode_t insert_mode;
158   boolean show_audio;
159   boolean ign_ins_sel;
160   boolean follow_playback;
161   boolean insert_audio;  ///< do we insert audio with video ?
162   boolean pertrack_audio; ///< do we want pertrack audio ?
163   boolean audio_bleedthru; ///< should we allow all audio to bleed thru ?
164   boolean gang_audio; ///< gang layer audio volume levels
165   boolean autocross_audio; ///< crossfade audio with autotransitions
166   int back_audio_tracks; ///< number of backing audio tracks (currently 0 or 1)
167   boolean render_vidp; ///< render video
168   boolean render_audp; ///< render audio
169   boolean normalise_audp; ///< normalise audio
170   boolean overlay_timecode;
171   boolean show_info;
172   int hpaned_pos;
173   int vpaned_pos;
174   double ptr_time;
175   LiVESList *aparam_view_list;
176 };
177 
178 struct _mt {
179   // widgets
180   LiVESWidget *menubar;
181   LiVESWidget *top_vbox;
182   LiVESWidget *top_vpaned;
183   LiVESWidget *xtravbox;
184   LiVESWidget *hbox;
185   LiVESWidget *play_blank;
186   LiVESWidget *poly_box;
187   LiVESWidget *clip_scroll;
188   LiVESWidget *clip_inner_box;
189   LiVESWidget *in_out_box;
190   LiVESWidget *in_hbox;
191   LiVESWidget *out_hbox;
192   LiVESWidget *in_frame;
193   LiVESWidget *out_frame;
194   LiVESWidget *in_image;
195   LiVESWidget *out_image;
196   LiVESWidget *scrolledwindow;
197   LiVESWidget *context_box;
198   LiVESWidget *context_scroll;
199   LiVESWidget *sep_image;
200   LiVESWidget *timeline_table_header;
201   LiVESWidget *tl_eventbox;
202   LiVESWidget *timeline_table;
203   LiVESWidget *timeline;
204   LiVESWidget *timeline_eb;
205   LiVESWidget *timeline_reg;
206   LiVESWidget *infobar;
207   LiVESWidget *stop;
208   LiVESWidget *rewind;
209   LiVESWidget *sepwin;
210   LiVESWidget *mute_audio;
211   LiVESWidget *loop_continue;
212   LiVESWidget *insert;
213   LiVESWidget *audio_insert;
214   LiVESWidget *delblock;
215   LiVESWidget *clipedit;
216   LiVESWidget *vpaned;
217   LiVESWidget *hpaned;
218   LiVESWidget *scrollbar;
219   LiVESWidget *playall;
220   LiVESWidget *playsel;
221   LiVESWidget *jumpnext;
222   LiVESWidget *jumpback;
223   LiVESWidget *mark_jumpnext;
224   LiVESWidget *mark_jumpback;
225   LiVESWidget *render;
226   LiVESWidget *prerender_aud;
227   LiVESWidget *message_box;
228   LiVESWidget *msg_area;
229   LiVESWidget *msg_scrollbar;
230   LiVESAdjustment *msg_adj;
231   LiVESWidget *fx_block;
232   LiVESWidget *fx_blockv;
233   LiVESWidget *fx_blocka;
234   LiVESWidget *fx_delete;
235   LiVESWidget *fx_edit;
236   LiVESWidget *fx_region;
237   LiVESWidget *fx_region_v;
238   LiVESWidget *fx_region_a;
239   LiVESWidget *fx_region_2av;
240   LiVESWidget *fx_region_2v;
241   LiVESWidget *fx_region_2a;
242   LiVESWidget *fx_region_3;
243   LiVESWidget *atrans_menuitem;
244   LiVESWidget *submenu_atransfx;
245   LiVESWidget *move_fx;
246   LiVESWidget *mm_menuitem;
247   LiVESWidget *mm_move;
248   LiVESWidget *mm_select;
249   LiVESWidget *ins_menuitem;
250   LiVESWidget *ins_normal;
251   LiVESWidget *grav_menuitem;
252   LiVESWidget *grav_label;
253   LiVESWidget *grav_normal;
254   LiVESWidget *grav_left;
255   LiVESWidget *grav_right;
256   LiVESWidget *select_track;
257   LiVESWidget *seldesel_menuitem;
258   LiVESWidget *view_events;
259   LiVESWidget *view_clips;
260   LiVESWidget *view_in_out;
261   LiVESWidget *view_effects;
262   LiVESWidget *show_quota;
263   LiVESWidget *avel_box;
264   LiVESWidget *checkbutton_avel_reverse;
265   LiVESWidget *spinbutton_avel;
266   LiVESWidget *avel_scale;
267   LiVESWidget *spinbutton_in;
268   LiVESWidget *spinbutton_out;
269   LiVESWidget *checkbutton_start_anchored;
270   LiVESWidget *checkbutton_end_anchored;
271   LiVESWidget *timecode;
272   LiVESWidget *spinbutton_start;
273   LiVESWidget *spinbutton_end;
274   LiVESWidget *tl_hbox;
275   LiVESWidget *fx_base_box;
276   LiVESWidget *fx_contents_box;
277   LiVESWidget *fx_box;
278   LiVESWidget *fx_label;
279   LiVESWidget *param_inner_box;
280   LiVESWidget *param_box;
281   LiVESWidget *next_node_button;
282   LiVESWidget *prev_node_button;
283   LiVESWidget *del_node_button;
284   LiVESWidget *resetp_button;
285   LiVESWidget *node_spinbutton;
286   LiVESWidget *node_scale;
287   LiVESWidget *sel_label;
288   LiVESWidget *l_sel_arrow;
289   LiVESWidget *r_sel_arrow;
290   LiVESWidget *save_event_list; ///< menuitem
291   LiVESWidget *load_event_list; ///< menuitem
292   LiVESWidget *clear_event_list; ///< menuitem
293   LiVESWidget *tc_to_rs;
294   LiVESWidget *tc_to_re;
295   LiVESWidget *rs_to_tc;
296   LiVESWidget *re_to_tc;
297   LiVESWidget *undo;
298   LiVESWidget *redo;
299   LiVESWidget *ac_audio_check;
300   LiVESWidget *remove_gaps;
301   LiVESWidget *remove_first_gaps;
302   LiVESWidget *split_sel;
303   LiVESWidget *ins_gap_sel;
304   LiVESWidget *ins_gap_cur;
305   LiVESWidget *last_filter_map;
306   LiVESWidget *next_filter_map;
307   LiVESWidget *fx_list_box;
308   LiVESWidget *fx_list_label;
309   LiVESWidget *fx_list_scroll;
310   LiVESWidget *fx_list_vbox;
311   LiVESWidget *next_fm_button;
312   LiVESWidget *prev_fm_button;
313   LiVESWidget *fx_ibefore_button;
314   LiVESWidget *fx_iafter_button;
315   LiVESWidget *rename_track;
316   LiVESWidget *cback_audio;
317   LiVESWidget *aload_subs;
318   LiVESWidget *load_vals;
319   LiVESWidget *change_vals;
320   LiVESWidget *aparam_separator;
321   LiVESWidget *aparam_menuitem;
322   LiVESWidget *aparam_submenu;
323   LiVESWidget *render_sep;
324   LiVESWidget *render_vid;
325   LiVESWidget *render_aud;
326   LiVESWidget *normalise_aud;
327   LiVESWidget *view_audio;
328   LiVESWidget *clear_marks;
329   LiVESWidget *fd_frame;
330   LiVESWidget *apply_fx_button;
331   LiVESToolItem *eview_button;
332   LiVESWidget *eview_label;
333   LiVESWidget *follow_play;
334   LiVESWidget *change_max_disp;
335   LiVESWidget *add_vid_behind;
336   LiVESWidget *add_vid_front;
337   LiVESWidget *show_info;
338   LiVESWidget *quit;
339   LiVESWidget *troubleshoot;
340   LiVESWidget *expl_missing;
341   LiVESWidget *show_devopts;
342   LiVESWidget *fx_params_label;
343   LiVESWidget *solo_check;
344   LiVESWidget *amixer_button;
345   LiVESWidget *view_sel_events;
346   LiVESWidget *adjust_start_end;
347   LiVESWidget *context_frame;
348   LiVESWidget *nb;
349   LiVESWidget *nb_label;
350 
351   LiVESWidget *eventbox;
352   LiVESWidget *scroll_label;
353   LiVESWidget *preview_frame;
354   LiVESWidget *preview_eventbox;
355   LiVESWidget *btoolbarx;
356   LiVESWidget *btoolbary;
357   LiVESWidget *bleedthru;
358   LiVESWidget *time_label;
359   LiVESWidget *insa_label;
360   LiVESWidget *overlap_label;
361   LiVESWidget *amix_label;
362   LiVESWidget *tl_label;
363   LiVESWidget *dumlabel1;
364   LiVESWidget *dumlabel2;
365   LiVESWidget *top_eventbox;
366   LiVESWidget *tlx_eventbox;
367   LiVESWidget *tlx_vbox;
368 
369   LiVESWidget *grav_submenu;
370   LiVESWidget *ins_submenu;
371   LiVESWidget *mm_submenu;
372   LiVESWidget *ins_label;
373   LiVESWidget *mm_label;
374 
375   LiVESWidget *nb_label1;
376   LiVESWidget *nb_label2;
377   LiVESWidget *nb_label3;
378   LiVESWidget *nb_label4;
379   LiVESWidget *nb_label5;
380   LiVESWidget *nb_label6;
381   LiVESWidget *nb_label7;
382 
383   LiVESToolItem *sep1;
384   LiVESToolItem *sep2;
385   LiVESToolItem *sep3;
386   LiVESWidget *sep4;
387 
388   LiVESWidget *btoolbar2;
389   LiVESWidget *btoolbar3;
390 
391   LiVESWidget *menu_hbox;
392 
393   LiVESWidget *hseparator;
394   LiVESWidget *hseparator2;
395 
396   LiVESWidget *files_menu;
397   LiVESWidget *edit_menu;
398   LiVESWidget *play_menu;
399   LiVESWidget *effects_menu;
400   LiVESWidget *tracks_menu;
401   LiVESWidget *selection_menu;
402   LiVESWidget *tools_menu;
403   LiVESWidget *render_menu;
404   LiVESWidget *view_menu;
405   LiVESWidget *help_menu;
406 
407   LiVESWidget *open_menu;
408 #ifdef HAVE_WEBM
409   LiVESWidget *open_loc_menu;
410 #endif
411 #ifdef ENABLE_DVD_GRAB
412   LiVESWidget *vcd_dvd_menu;
413 #endif
414 #ifdef HAVE_LDVGRAB
415   LiVESWidget *device_menu;
416 #endif
417   LiVESWidget *recent_menu;
418   LiVESWidget *recent[N_RECENT_FILES];
419 
420   LiVESWidget *time_scrollbar;
421   LiVESWidget *show_layout_errors;
422 
423   LiVESWidget *load_set;
424   LiVESWidget *save_set;
425 
426   LiVESWidget *close;
427 
428   LiVESWidget *clear_ds;
429 
430   LiVESWidget *gens_submenu;
431   LiVESWidget *capture;
432 
433   LiVESWidget *backup;
434 
435   LiVESWidget *insa_checkbutton;
436   LiVESWidget *snapo_checkbutton;
437 
438   LiVESWidgetObject *spinbutton_in_adj;
439   LiVESWidgetObject *spinbutton_out_adj;
440 
441   LiVESWidgetObject *hadjustment;
442   LiVESWidgetObject *node_adj;
443 
444   LiVESList *audio_draws; ///< list of audio boxes, 0 == backing audio, 1 == track 0 audio, etc.
445 
446   LiVESList *audio_vols; ///< layer volume levels (coarse control) - set in mixer
447   LiVESList *audio_vols_back; ///< layer volume levels (coarse control) - reset levels
448 
449   LiVESAccelGroup *accel_group;
450   LiVESList *video_draws; ///< list of video timeline eventboxes, in layer order
451   LiVESWidgetObject *vadjustment;
452 
453   LiVESXDisplay *display;
454 
455   LiVESPixbuf *frame_pixbuf;
456 
457   LiVESList *cb_list;
458 
459   lives_painter_surface_t *insurface, *outsurface;
460 
461   ulong spin_in_func;
462   ulong spin_out_func;
463   ulong spin_avel_func;
464   ulong check_start_func;
465   ulong check_end_func;
466   ulong check_avel_rev_func;
467 
468   ulong mm_move_func;
469   ulong mm_select_func;
470 
471   ulong ins_normal_func;
472 
473   ulong grav_normal_func;
474   ulong grav_left_func;
475   ulong grav_right_func;
476 
477   ulong sepwin_func;
478   ulong mute_audio_func;
479   ulong loop_cont_func;
480 
481   ulong seltrack_func;
482 
483   ulong tc_func;
484 
485   //ulong sw_func;
486 
487   lives_painter_surface_t *pbox_surface;
488 
489   lives_painter_surface_t *tl_ev_surf;
490   lives_painter_surface_t *tl_reg_surf;
491   lives_painter_surface_t *tl_surf;
492 
493   weed_plant_t *event_list;
494 
495   weed_plant_t *init_event;   ///< current editable values
496   weed_plant_t *selected_init_event;  ///< currently selected in list
497   ///////////////////////
498   int num_video_tracks;
499   double end_secs;  ///< max display time of timeline in seconds
500 
501   // timeline min and max display values
502   double tl_min;
503   double tl_max;
504 
505   int clip_selected; ///< clip in clip window
506   int file_selected; ///< actual LiVES file struct number which clip_selected matches
507   int current_track; ///< starts at 0
508 
509   LiVESList *selected_tracks;
510 
511   lives_mt_poly_state_t poly_state;  ///< state of polymorph window
512 
513   int render_file;
514 
515   lives_direction_t last_direction; ///< last direction timeline cursor was moved in
516 
517   track_rect *block_selected; ///< pointer to current selected block, or NULL
518   track_rect *putative_block; ///< putative block to move or copy, or NULL
519 
520   double ptr_time; ///< stored timeline cursor position before playback
521 
522   double tl_fixed_length; ///< length of timeline can be fixed (secs) : TODO
523 
524   double fps; ///< fps of this timeline
525 
526   double region_start; ///< start of time region in seconds (or 0.)
527   double region_end; ///< end of time region in seconds (or 0.)
528   double region_init; ///< point where user pressed the mouse
529   boolean region_updating;
530 
531   boolean is_rendering; ///< TRUE if we are in the process of rendering/pre-rendering to a clip, cf. mainw->is_rendering
532   boolean pr_audio; ///< TRUE if we are in the process of prerendering audio to a clip
533 
534   int current_fx;
535 
536   boolean mt_frame_preview;
537 
538   boolean in_sensitise;
539 
540   boolean sel_locked;
541 
542   lives_rfx_t *current_rfx;
543 
544   char layout_name[PATH_MAX];
545 
546   // cursor warping for mouse move mode
547   double hotspot_x;
548   int hotspot_y;
549 
550   boolean moving_block; ///< moving block flag
551 
552   double pb_start_time; ///< playback start time in seconds. If play is stopped (not paused) we return to here.
553   double pb_unpaused_start_time; ///< playback start time in seconds. If play is stopped (not paused) we return to here.
554 
555   //////////////////////////////
556 
557   int sel_x;
558   int sel_y;
559 
560   ulong mouse_mot1;
561   ulong mouse_mot2;
562 
563   boolean tl_selecting; ///< for mouse select mode
564 
565   /* start and end offset overrides for inserting (used during block move) */
566   ticks_t insert_start;
567   ticks_t insert_end;
568 
569   /// override for avel used during audio insert
570   double insert_avel;
571 
572   LiVESList *undos;
573   size_t undo_buffer_used;
574   uint8_t *undo_mem;
575   off_t undo_offset;
576   boolean did_backup;
577 
578   char undo_text[32];
579   char redo_text[32];
580 
581   boolean undoable;
582   boolean redoable;
583 
584   boolean changed; ///< changed since last saved
585   boolean auto_changed; ///< changed since last auto-saved
586 
587   ticks_t auto_back_time; ///< time when last backup was done (not to be confused with prefs->auto_back)
588 
589   lives_special_framedraw_rect_t *framedraw;
590   int track_index;
591 
592   lives_mt_last_fx_type_t last_fx_type;
593 
594   lives_mt_fx_order_t fx_order;
595 
596   mt_opts opts;
597 
598   boolean auto_reloading;
599 
600   weed_plant_t *fm_edit_event;
601   weed_plant_t *moving_fx;
602 
603   int avol_fx; ///< index of audio volume filter, delegated by user from audio volume candidates
604   weed_plant_t *avol_init_event;
605 
606   ulong spin_start_func;
607   ulong spin_end_func;
608 
609   boolean layout_prompt; ///< on occasion, prompt user if they want to correct layout on disk or not
610   boolean layout_set_properties;
611   boolean ignore_load_vals;
612 
613   double user_fps;
614   int user_width;
615   int user_height;
616   int user_arate;
617   int user_achans;
618   int user_asamps;
619   int user_signed_endian;
620 
621   int exact_preview;
622 
623   int preview_layer;
624 
625   char timestring[TIMECODE_LENGTH];
626 
627   weed_plant_t *solo_inst; ///< instance to view solo in the frame preview
628 
629   LiVESList *tl_marks;
630 
631   weed_plant_t *pb_start_event; ///< FRAME event from which we start playback
632   weed_plant_t *pb_loop_event; ///< FRAME event to loop back to (can be different from pb_start_event if we are paused)
633 
634   weed_plant_t *specific_event; ///< a pointer to some generally interesting event
635 
636   double context_time; ///< this is set when the user right clicks on a track, otherwise -1.
637   boolean use_context;
638 
639   lives_cursor_t cursor_style;
640 
641   boolean is_paused;
642 
643   /* current size of frame inside playback/preview area */
644   int play_width;
645   int play_height;
646 
647   /* /\* current size of playback/preview area *\/ */
648   /* int play_window_width; */
649   /* int play_window_height; */
650 
651   int selected_filter; ///< filter selected in poly window tab
652 
653   int top_track; ///< top (video) track in scrolled window
654 
655   boolean redraw_block; ///< block drawing of playback cursor during track redraws
656 
657   boolean was_undo_redo;
658 
659   boolean no_expose; ///< block timeline expose while we are exiting
660 
661   boolean is_ready;
662 
663   boolean aud_track_selected;
664 
665   boolean has_audio_file;
666 
667   boolean tl_mouse;
668 
669   boolean playing_sel; ///< are we playing just the time selection ?
670 
671   uint32_t idlefunc; ///< autobackup function
672 
673   LiVESList *clip_labels;
674 
675   lives_amixer_t *amixer;
676 
677   double prev_fx_time;
678 
679   boolean block_tl_move; ///< set to TRUE to block moving timeline (prevents loops with the node spinbutton)
680   boolean block_node_spin; ///< set to TRUE to block moving node spinner (prevents loops with the timeline)
681 
682   boolean is_atrans; /// < force some visual changes when applying autotrans
683 
684   boolean no_frame_update;
685   boolean no_expose_frame;
686 
687   char *force_load_name; ///< pointer to a string which contains a filename to be force loaded when load_event_list_activate() is called.
688   ///< Normally NULL except when called from language bindings.
689 };  // lives_mt
690 
691 typedef struct {
692   lives_mt_undo_t action;
693   ticks_t tc;
694   void *extra;
695   size_t data_len; ///< including this mt_undo
696 } mt_undo;
697 
698 struct _lives_amixer_t {
699   LiVESWidget *window;
700   LiVESWidget *main_hbox;
701   LiVESWidget **ch_sliders;
702   LiVESWidget *gang_checkbutton;
703   LiVESWidget *inv_checkbutton;
704   ulong *ch_slider_fns;
705   int nchans;
706   lives_mt *mt;
707 };
708 
709 // reasons for track invisibility (bitmap)
710 #define TRACK_I_HIDDEN_USER (1<<0)
711 #define TRACK_I_HIDDEN_SCROLLED (1<<1)
712 
713 /// track rectangles (blocks), we translate our event_list FRAME events into these, then when exposed, the eventbox draws them
714 /// blocks MUST only contain frames from a single clip. They MAY NOT contain blank frames.
715 ///
716 /// start and end events MUST be FRAME events
717 
718 /// TODO: add scrap_file_offset so we can treat scrapfile like an ordinary clip
719 struct _track_rect {
720   ulong uid;
721 
722   track_rect *next;
723   track_rect *prev;
724   weed_plant_t *start_event;
725   weed_plant_t *end_event;
726 
727   ticks_t offset_start; ///< offset in sourcefile of first frame
728 
729   lives_mt_block_state_t state;
730   boolean start_anchored;
731   boolean end_anchored;
732   boolean ordered; ///< are frames in sequential order ?
733 
734   LiVESWidget
735   *eventbox; ///< pointer to eventbox widget which contains this block; we can use its "layer_number" to get the track/layer number
736 };
737 
738 /* translation table for matching event_id to init_event */
739 typedef struct {
740   uint64_t in;
741   void *out;
742 } ttable;
743 
744 /* clip->layout use mapping, from layout.map lives_clip_t */
745 typedef struct {
746   char *handle;
747   int64_t unique_id;
748   char *name;
749   LiVESList *list;
750 } layout_map;
751 
752 //////////////////////////////////////////////////////////////////
753 
754 // setup functions
755 
756 lives_mt *multitrack(weed_plant_t *, int orig_file, double fps);  ///< create and return lives_mt struct
757 void mt_init_tracks(lives_mt *, boolean set_min_max);   ///< add basic tracks, or set tracks from mt->event_list
758 boolean on_multitrack_activate(LiVESMenuItem *menuitem, weed_plant_t *event_list);  ///< menuitem callback
759 
760 // theming
761 void set_mt_colours(lives_mt *);
762 
763 // delete function
764 boolean multitrack_delete(lives_mt *, boolean save);
765 
766 // morph the poly window
767 void polymorph(lives_mt *, lives_mt_poly_state_t poly);
768 void set_poly_tab(lives_mt *mt, uint32_t tab);
769 
770 // gui related
771 void mt_desensitise(lives_mt *);
772 void mt_sensitise(lives_mt *);
773 void set_mt_play_sizes_cfg(lives_mt *);
774 boolean mt_idle_show_current_frame(livespointer mt);
775 boolean show_in_out_images(livespointer mt);
776 
777 void add_aparam_menuitems(lives_mt *);
778 
779 // external control callbacks
780 void insert_here_cb(LiVESMenuItem *, livespointer mt);
781 void insert_audio_here_cb(LiVESMenuItem *, livespointer mt);
782 void insert_at_ctx_cb(LiVESMenuItem *, livespointer mt);
783 void insert_audio_at_ctx_cb(LiVESMenuItem *, livespointer mt);
784 void multitrack_end_cb(LiVESMenuItem *, livespointer mt);
785 void delete_block_cb(LiVESMenuItem *, livespointer mt);
786 void selblock_cb(LiVESMenuItem *, livespointer mt);
787 void list_fx_here_cb(LiVESMenuItem *, livespointer mt);
788 void edit_start_end_cb(LiVESMenuItem *, livespointer mt);
789 void close_clip_cb(LiVESMenuItem *, livespointer mt);
790 void show_clipinfo_cb(LiVESMenuItem *, livespointer mt);
791 
792 boolean multitrack_insert(LiVESMenuItem *, livespointer mt);
793 track_rect *move_block(lives_mt *, track_rect *block, double timesecs, int old_track, int new_track);
794 
795 void update_grav_mode(lives_mt *);
796 void update_insert_mode(lives_mt *);
797 
798 boolean on_render_activate(LiVESMenuItem *, livespointer mt);
799 
800 void mt_set_autotrans(int idx);
801 
802 // event_list functions
803 weed_plant_t *add_blank_frames_up_to(weed_plant_t *event_list, weed_plant_t *start_event, ticks_t end_tc, double fps);
804 
805 // track functions
806 char *get_track_name(lives_mt *, int track_num, boolean is_audio);
807 void on_cback_audio_activate(LiVESMenuItem *, livespointer mt);
808 LiVESWidget *add_audio_track(lives_mt *, int trackno, boolean behind);
809 int add_video_track_behind(LiVESMenuItem *, livespointer mt);
810 int add_video_track_front(LiVESMenuItem *, livespointer mt);
811 void delete_video_track(lives_mt *, int layer, boolean full);
812 void delete_audio_track(lives_mt *, LiVESWidget *eventbox, boolean full);
813 void delete_audio_tracks(lives_mt *, LiVESList *list, boolean full);
814 void remove_gaps(LiVESMenuItem *, livespointer mt);
815 void remove_first_gaps(LiVESMenuItem *, livespointer mt);
816 void on_insgap_sel_activate(LiVESMenuItem *, livespointer mt);
817 void on_insgap_cur_activate(LiVESMenuItem *, livespointer mt);
818 void on_split_activate(LiVESMenuItem *, livespointer mt);
819 void scroll_tracks(lives_mt *, int top_track, boolean set_value);
820 boolean track_arrow_pressed(LiVESWidget *ahbox, LiVESXEventButton *, livespointer mt);
821 void track_select(lives_mt *);  ///< must call after setting mt->current_track
822 void mt_selection_lock(LiVESMenuItem *, livespointer user_data); ///< lock the time selection
823 boolean mt_track_is_audio(lives_mt *, int ntrack); ///< return TRUE if ntrack is a valid backing audio track
824 boolean mt_track_is_video(lives_mt *, int ntrack); ///< return TRUE if ntrack is a valid video track
825 
826 void mt_do_autotransition(lives_mt *, track_rect *block); ///< call this on a block to apply autotransition on it
827 
828 void set_track_label_string(lives_mt *mt, int track, const char *label);
829 
830 LiVESWidget *get_eventbox_for_track(lives_mt *mt, int ntrack);
831 void on_rename_track_activate(LiVESMenuItem *menuitem, livespointer mt);
832 
833 // track mouse movement
834 boolean on_track_click(LiVESWidget *eventbox, LiVESXEventButton *, livespointer mt);
835 boolean on_atrack_click(LiVESWidget *eventbox, LiVESXEventButton *, livespointer mt);
836 boolean on_track_header_click(LiVESWidget *eventbox, LiVESXEventButton *, livespointer mt);
837 boolean on_track_between_click(LiVESWidget *eventbox, LiVESXEventButton *, livespointer mt);
838 boolean on_track_release(LiVESWidget *eventbox, LiVESXEventButton *event, livespointer mt);
839 boolean on_atrack_release(LiVESWidget *eventbox, LiVESXEventButton *event, livespointer mt);
840 boolean on_track_header_release(LiVESWidget *eventbox, LiVESXEventButton *, livespointer mt);
841 boolean on_track_between_release(LiVESWidget *eventbox, LiVESXEventButton *, livespointer mt);
842 boolean on_track_move(LiVESWidget *widget, LiVESXEventMotion *event, livespointer mt);
843 boolean on_track_header_move(LiVESWidget *widget, LiVESXEventMotion *event, livespointer mt);
844 
845 void unselect_all(lives_mt *);  ///< unselect all blocks
846 void insert_frames(int filenum, ticks_t offset_start, ticks_t offset_end, ticks_t tc,
847                    lives_direction_t direction, LiVESWidget *eventbox, lives_mt *, track_rect *in_block);
848 void insert_audio(int filenum, ticks_t offset_start, ticks_t offset_end, ticks_t tc,
849                   double avel, lives_direction_t direction, LiVESWidget *eventbox, lives_mt *, track_rect *in_block);
850 void on_seltrack_toggled(LiVESWidget *, livespointer mt);
851 void scroll_track_by_scrollbar(LiVESScrollbar *sbar, livespointer mt);
852 
853 // block functions
854 void in_out_start_changed(LiVESWidget *, livespointer mt);
855 void in_out_end_changed(LiVESWidget *, livespointer mt);
856 void in_anchor_toggled(LiVESToggleButton *, livespointer mt);
857 void out_anchor_toggled(LiVESToggleButton *, livespointer mt);
858 void avel_reverse_toggled(LiVESToggleButton *, livespointer mt);
859 void avel_spin_changed(LiVESSpinButton *, livespointer mt);
860 
861 // block API functions
862 track_rect *find_block_by_uid(lives_mt *mt, ulong uid);
863 ulong mt_get_last_block_uid(lives_mt *mt); ///< get index of last inserted (wallclock time) block for track
864 int mt_get_block_count(lives_mt *, int ntrack); ///< count blocks in track
865 double mt_get_block_sttime(lives_mt *, int ntrack, int iblock); /// get timeline start time of block
866 double mt_get_block_entime(lives_mt *, int ntrack, int iblock); /// get timeline end time of block
867 
868 track_rect *get_block_from_track_and_time(lives_mt *mt, int track, double time);
869 
870 int get_track_for_block(track_rect *block);
871 int get_clip_for_block(track_rect *block);
872 
873 // timeline functions
874 boolean resize_timeline(lives_mt *);
875 void mt_tl_move(lives_mt *, double pos_abs);
876 void set_timeline_end_secs(lives_mt *, double secs);
877 boolean on_timeline_press(LiVESWidget *, LiVESXEventButton *, livespointer mt);
878 boolean on_timeline_release(LiVESWidget *, LiVESXEventButton *, livespointer mt);
879 boolean on_timeline_update(LiVESWidget *, LiVESXEventMotion *, livespointer mt);
880 void draw_region(lives_mt *mt);
881 
882 boolean mt_mark_callback(LiVESAccelGroup *group, LiVESWidgetObject *obj, uint32_t keyval, LiVESXModifierType mod,
883                          livespointer user_data);
884 
885 void mt_show_current_frame(lives_mt *, boolean return_layer);  ///< preview the current frame
886 void mt_clear_timeline(lives_mt *mt);
887 
888 void mt_zoom_in(LiVESMenuItem *, livespointer mt);
889 void mt_zoom_out(LiVESMenuItem *, livespointer mt);
890 
891 // context box text
892 void clear_context(lives_mt *);
893 void add_context_label(lives_mt *, const char *text);
894 void mouse_mode_context(lives_mt *);
895 void do_sel_context(lives_mt *);
896 void do_fx_list_context(lives_mt *, int fxcount);
897 void do_fx_move_context(lives_mt *mt);
898 
899 // playback / animation
900 void multitrack_playall(lives_mt *);
901 void multitrack_play_sel(LiVESMenuItem *, livespointer mt);
902 void animate_multitrack(lives_mt *);
903 void unpaint_line(lives_mt *, LiVESWidget *eventbox);
904 void unpaint_lines(lives_mt *);
905 
906 void mt_prepare_for_playback(lives_mt *);
907 void mt_post_playback(lives_mt *);
908 
909 boolean mt_tcoverlay_callback(LiVESAccelGroup *, LiVESWidgetObject *, uint32_t keyval, LiVESXModifierType mod,
910                               livespointer user_data);
911 
912 // effect node controls
913 void on_next_node_clicked(LiVESWidget *, livespointer mt);
914 void on_prev_node_clicked(LiVESWidget *, livespointer mt);
915 void on_del_node_clicked(LiVESWidget *, livespointer mt);
916 void on_resetp_clicked(LiVESWidget *, livespointer mt);
917 void on_node_spin_value_changed(LiVESSpinButton *, livespointer mt);
918 double mt_get_effect_time(lives_mt *);
919 
920 void on_frame_preview_clicked(LiVESButton *, livespointer mt);
921 void show_preview(lives_mt *, ticks_t tc);
922 
923 boolean add_mt_param_box(lives_mt *);
924 void redraw_mt_param_box(lives_mt *);
925 
926 // filter list controls
927 weed_plant_t *get_prev_fm(lives_mt *, int current_track, weed_plant_t *frame);
928 weed_plant_t *get_next_fm(lives_mt *, int current_track, weed_plant_t *frame);
929 
930 void on_prev_fm_clicked(LiVESWidget *button, livespointer mt);
931 void on_next_fm_clicked(LiVESWidget *button, livespointer mt);
932 void on_fx_insb_clicked(LiVESWidget *button, livespointer mt);
933 void on_fx_insa_clicked(LiVESWidget *button, livespointer mt);
934 
935 // utils
936 boolean event_list_rectify(lives_mt *, weed_plant_t *event_listy);
937 void *find_init_event_in_ttable(ttable *trans_table, uint64_t in, boolean normal);
938 void reset_renumbering(void);
939 boolean make_backup_space(lives_mt *, size_t space_needed);
940 void activate_mt_preview(lives_mt *); ///< sensitize Show Preview and Apply buttons
941 void **mt_get_pchain(void);
942 void event_list_free_undos(lives_mt *);
943 boolean used_in_current_layout(lives_mt *, int file);
944 
945 boolean set_new_set_name(lives_mt *);
946 
947 LiVESPixbuf *make_thumb(lives_mt *mt, int file, int width, int height, int frame, LiVESInterpType interp, boolean noblanks);
948 
949 void free_thumb_cache(int fnum, frames_t fromframe);
950 
951 // event_list utilities
952 boolean compare_filter_maps(weed_plant_t *fm1, weed_plant_t *fm2,
953                             int ctrack); ///< ctrack can be -1 to compare all events, else we cf for ctrack
954 void move_init_in_filter_map(lives_mt *, weed_plant_t *event_list, weed_plant_t *fmap, weed_plant_t *ifrom,
955                              weed_plant_t *ito, int track, boolean after);
956 void update_filter_events(lives_mt *, weed_plant_t *first_event, ticks_t start_tc, ticks_t end_tc,
957                           int track, ticks_t new_start_tc, int new_track);
958 void mt_fixup_events(lives_mt *, weed_plant_t *old_event, weed_plant_t *new_event);
959 
960 // event_list load/save
961 char *get_eload_filename(lives_mt *mt, boolean allow_auto_reload);
962 weed_plant_t *load_event_list(lives_mt *, char *eload_file);
963 boolean on_save_event_list_activate(LiVESMenuItem *, livespointer mt);
964 boolean save_event_list_inner(lives_mt *, int fd, weed_plant_t *event_list, unsigned char **mem);
965 boolean mt_load_recovery_layout(lives_mt *);
966 
967 // layouts and layout maps
968 LiVESList *load_layout_map(void);
969 void add_markers(lives_mt *, weed_plant_t *event_list, boolean add_block_ids);
970 void remove_markers(weed_plant_t *event_list);
971 void save_layout_map(int *lmap, double *lmap_audio, const char *file, const char *dir);
972 
973 void wipe_layout(lives_mt *);
974 
975 void migrate_layouts(const char *old_set_name, const char *new_set_name);
976 
977 LiVESList *layout_frame_is_affected(int clipno, int start, int end, LiVESList *xlays);
978 LiVESList *layout_audio_is_affected(int clipno, double stime, double etime, LiVESList *xlays);
979 
980 boolean check_for_layout_del(lives_mt *, boolean exiting);
981 
982 boolean on_load_event_list_activate(LiVESMenuItem *, livespointer mt);
983 
984 void stored_event_list_free_all(boolean wiped);
985 void stored_event_list_free_undos(void);
986 void remove_current_from_affected_layouts(lives_mt *);
987 
988 // auto backup
989 void maybe_add_mt_idlefunc(void);
990 uint32_t mt_idle_add(lives_mt *);
991 boolean recover_layout(void);
992 void recover_layout_cancelled(boolean is_startup);
993 boolean write_backup_layout_numbering(lives_mt *);
994 boolean mt_auto_backup(livespointer mt);
995 
996 // amixer funcs
997 void amixer_show(LiVESButton *, livespointer mt);
998 void on_amixer_close_clicked(LiVESButton *, lives_mt *mt);
999 LiVESWidget *amixer_add_channel_slider(lives_mt *, int i);
1000 
1001 // misc
1002 void mt_change_disp_tracks_ok(LiVESButton *, livespointer mt);
1003 void mt_swap_play_pause(lives_mt *, boolean put_pause);
1004 char *set_values_from_defs(lives_mt *, boolean from_prefs);
1005 
1006 // clip boxes
1007 void mt_clip_select(lives_mt *, boolean scroll);
1008 void mt_delete_clips(lives_mt *, int file);
1009 void mt_init_clips(lives_mt *, int orig_file, boolean add);
1010 
1011 // key shortcuts
1012 boolean mt_prevclip(LiVESAccelGroup *, LiVESWidgetObject *, uint32_t keyval, LiVESXModifierType mod, livespointer);
1013 boolean mt_nextclip(LiVESAccelGroup *, LiVESWidgetObject *, uint32_t keyval, LiVESXModifierType mod, livespointer);
1014 
1015 typedef enum {
1016   /* default to warn about */
1017   LMAP_ERROR_MISSING_CLIP = 1,
1018   LMAP_ERROR_CLOSE_FILE = 2,
1019   LMAP_ERROR_DELETE_FRAMES = 3,
1020   LMAP_ERROR_DELETE_AUDIO = 4,
1021 
1022   /*non-default*/
1023   LMAP_ERROR_SHIFT_FRAMES = 65,
1024   LMAP_ERROR_ALTER_FRAMES = 66,
1025   LMAP_ERROR_SHIFT_AUDIO = 67,
1026   LMAP_ERROR_ALTER_AUDIO = 68,
1027 
1028   /* info */
1029   LMAP_INFO_SETNAME_CHANGED = 1024
1030 } lives_lmap_error_t;
1031 
1032 typedef struct {
1033   lives_lmap_error_t type;
1034   char *name;
1035   livespointer data;
1036   int clipno, frameno;
1037   double atime;
1038   boolean current;
1039 } lmap_error;
1040 
1041 #define DEF_MT_DISP_TRACKS 5
1042 
1043 // array max: TODO - use dynamic arrays to bypass track limits
1044 #define MAX_TRACKS 65536
1045 #define MAX_VIDEO_TRACKS 65536
1046 #define MAX_AUDIO_TRACKS 65536
1047 
1048 // double -> quantised double
1049 #define QUANT_TIME(dbltime) ((q_gint64(dbltime * TICKS_PER_SECOND_DBL, mt->fps) / TICKS_PER_SECOND_DBL))
1050 
1051 // ticks -> quantised double
1052 #define QUANT_TICKS(ticks) ((q_gint64(ticks, mt->fps) / TICKS_PER_SECOND_DBL))
1053 
1054 #endif
1055