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