1 // events.h
2 // LiVES
3 // (c) G. Finch 2005 - 2016 <salsaman@gmail.com>
4 // released under the GNU GPL 3 or later
5 // see file ../COPYING or www.gnu.org for licensing details
6 
7 // functions/structs for event_lists and events
8 
9 #ifndef HAS_LIVES_EVENTS_H
10 #define HAS_LIVES_EVENTS_H
11 
12 /// for backwards compat.
13 #define WEED_LEAF_HINT "hint"
14 
15 /// parts of this may eventually become libweed-events
16 
17 // event_list
18 #define WEED_LEAF_WEED_EVENT_API_VERSION "weed_event_api_version"
19 #define WEED_LEAF_AUDIO_SIGNED "audio_signed"
20 #define WEED_LEAF_AUDIO_ENDIAN "audio_endian"
21 #define WEED_LEAF_AUDIO_SAMPLE_SIZE "audio_sample_size"
22 #define WEED_LEAF_AUDIO_VOLUME_TRACKS "audio_volume_tracks"
23 #define WEED_LEAF_AUDIO_VOLUME_VALUES "audio_volume_values"
24 #define WEED_LEAF_TRACK_LABEL_TRACKS "track_label_tracks"
25 #define WEED_LEAF_TRACK_LABEL_VALUES "track_label_values"
26 
27 #define WEED_LEAF_AUTHOR "author"
28 #define WEED_LEAF_TITLE "title"
29 #define WEED_LEAF_COMMENTS "comments"
30 
31 #define WEED_LEAF_LIVES_CREATED_VERSION "created_version"
32 #define WEED_LEAF_LIVES_EDITED_VERSION "edited_version"
33 
34 #define WEED_LEAF_CREATED_DATE "host_created_date"
35 #define WEED_LEAF_EDITED_DATE "host_edited_date"
36 
37 // frame event
38 #define WEED_LEAF_FRAMES "frames"
39 #define WEED_LEAF_CLIPS "clips"
40 #define WEED_LEAF_AUDIO_CLIPS "audio_clips"
41 #define WEED_LEAF_AUDIO_SEEKS "audio_seeks"
42 
43 // init_event
44 #define WEED_LEAF_FILTER "filter"
45 #define WEED_LEAF_IN_COUNT "in_count"
46 #define WEED_LEAF_OUT_COUNT "out_count"
47 #define WEED_LEAF_IN_TRACKS "in_tracks"
48 #define WEED_LEAF_OUT_TRACKS "out_tracks"
49 #define WEED_LEAF_EVENT_ID "event_id"
50 
51 // deinit
52 #define WEED_LEAF_INIT_EVENT "init_event"
53 
54 // filter map
55 #define WEED_LEAF_INIT_EVENTS "init_events"
56 
57 // param change
58 #define WEED_LEAF_INDEX "index"
59 
60 // internal
61 // event_list
62 #define WEED_LEAF_NEXT "next"
63 #define WEED_LEAF_PREVIOUS "previous"
64 #define WEED_LEAF_FIRST "first"
65 #define WEED_LEAF_LAST "last"
66 #define WEED_LEAF_NEEDS_SET "needs_set" // oops, should have been host_needs_set
67 #define WEED_LEAF_GAMMA_ENABLED "host_gamma_enabled"
68 #define WEED_LEAF_TC_ADJUSTMENT "tc_adj_val"
69 
70 // param change
71 #define WEED_LEAF_NEXT_CHANGE  "next_change"
72 #define WEED_LEAF_PREV_CHANGE  "prev_change"
73 #define WEED_LEAF_IS_DEF_VALUE "host_is_def_value"
74 
75 // init_event
76 #define WEED_LEAF_DEINIT_EVENT "deinit_event"
77 
78 // marker
79 #define WEED_LEAF_LIVES_TYPE "lives_type"
80 #define WEED_LEAF_TRACKS "tracks"
81 #define WEED_LEAF_TCDELTA "tc_delta"
82 
83 // misc
84 #define WEED_LEAF_PTRSIZE "ptrsize" ///< deprecated
85 
86 #define WEED_LEAF_HOST_AUDIO_TRANSITION "host_audio_transition"
87 
88 #define WEED_LEAF_HOST_TAG_COPY "host_tag_copy"
89 
90 #define WEED_LEAF_OVERLAY_TEXT "overlay_text"
91 
92 #define LIVES_TRACK_ANY -1000000
93 
94 #define AUD_DIFF_MIN 0.05  ///< ignore audio seek differences < than this (seconds)
95 #define AUD_DIFF_REVADJ 8. ///< allow longer seek differences when audio plauback direction reverses (multiplying factor)
96 
97 typedef weed_plant_t weed_event_t;
98 
99 /// various return conditions from rendering (multitrack or after recording)
100 typedef enum {
101   LIVES_RENDER_ERROR_NONE = 0,
102   LIVES_RENDER_READY,
103   LIVES_RENDER_PROCESSING,
104   LIVES_RENDER_EFFECTS_PAUSED,
105   LIVES_RENDER_COMPLETE,
106   LIVES_RENDER_WARNING,
107   LIVES_RENDER_WARNING_READ_FRAME,
108   LIVES_RENDER_ERROR,
109   LIVES_RENDER_ERROR_READ_AUDIO,
110   LIVES_RENDER_ERROR_WRITE_AUDIO,
111   LIVES_RENDER_ERROR_WRITE_FRAME,
112 } lives_render_error_t;
113 
114 weed_event_t *append_frame_event(weed_event_t *event_list, ticks_t tc, int numframes,
115                                  int *clips, int64_t *frames) WARN_UNUSED;
116 weed_event_t *append_filter_init_event(weed_event_t *event_list, ticks_t tc,
117                                        int filter_idx, int num_in_tracks, int key, weed_plant_t *inst) WARN_UNUSED;
118 weed_event_t *append_filter_deinit_event(weed_event_t *event_list, ticks_t tc,
119     void *init_event, void **pchain) WARN_UNUSED;
120 weed_event_t *append_filter_map_event(weed_event_t *event_list, ticks_t tc, void **init_events) WARN_UNUSED;
121 weed_event_t *append_param_change_event(weed_event_t *event_list, ticks_t tc, int pnum,
122                                         weed_plant_t *param, void *init_event, void **pchain) WARN_UNUSED;
123 weed_event_t *append_marker_event(weed_event_t *event_list, ticks_t tc, int marker_type) WARN_UNUSED;
124 
125 /** will either insert or replace */
126 weed_event_t *insert_frame_event_at(weed_event_t *event_list, ticks_t tc, int numframes,
127                                     int *clips, int64_t *frames, weed_event_t **shortcut) WARN_UNUSED;
128 void insert_audio_event_at(weed_event_t *event, int track, int clipnum, double time, double vel);
129 void remove_audio_for_track(weed_event_t *event, int track);
130 weed_event_t *insert_blank_frame_event_at(weed_event_t *event_list, ticks_t tc,
131     weed_event_t **shortcut) WARN_UNUSED;
132 
133 void remove_frame_from_event(weed_event_t *event_list, weed_event_t *event, int track);
134 void remove_end_blank_frames(weed_event_t *event_list, boolean remove_filter_inits);
135 void remove_filter_from_event_list(weed_event_t *event_list, weed_event_t *init_event);
136 
137 weed_event_t *process_events(weed_event_t *next_event, boolean process_audio, ticks_t curr_tc);  ///< RT playback
138 void event_list_close_start_gap(weed_event_t *event_list);
139 void event_list_add_track(weed_event_t *event_list, int layer);
140 void add_track_to_avol_init(weed_plant_t *filter, weed_event_t *event, int nbtracks, boolean behind);
141 void event_list_free(weed_event_t *event_list);
142 
143 void event_list_add_end_events(weed_event_t *event_list, boolean is_final);
144 
145 
146 /// lib-ish stuff
147 weed_event_t *lives_event_list_new(weed_event_t *elist, const char *cdate);
148 int weed_event_get_type(weed_event_t *event);
149 weed_timecode_t weed_event_set_timecode(weed_event_t *, weed_timecode_t tc);
150 weed_timecode_t weed_event_get_timecode(weed_event_t *);
151 
152 int weed_frame_event_get_tracks(weed_event_t *event,  int **clips, int64_t **frames); // returns ntracks
153 int weed_frame_event_get_audio_tracks(weed_event_t *event,  int **aclips, double **aseeks); // returns natracks
154 
155 /// replace events in event_list with events in new_event_list
156 void event_list_replace_events(weed_event_t *event_list, weed_event_t *new_event_list);
157 
158 /// called during quantisation
159 weed_event_t *event_copy_and_insert(weed_event_t *in_event, weed_timecode_t tc, weed_event_t *event_list,
160                                     weed_event_t **ret_event);
161 void reset_ttable(void);
162 
163 /// if all_events is FALSE we only count FRAME events
164 int count_events(weed_event_t *event_list, boolean all_events, ticks_t start_tc, ticks_t end_tc);
165 
166 frames_t count_resampled_events(weed_event_t *event_list, double fps);
167 
168 boolean backup_recording(char **esave_file, char **asave_file);
169 
170 boolean event_list_to_block(weed_event_t *event_list, int num_events);
171 double event_list_get_end_secs(weed_event_t *event_list);
172 double event_list_get_start_secs(weed_event_t *event_list);
173 ticks_t event_list_get_end_tc(weed_event_t *event_list);
174 ticks_t event_list_get_start_tc(weed_event_t *event_list);
175 
176 weed_event_t *get_last_frame_event(weed_event_t *event_list);
177 weed_event_t *get_first_frame_event(weed_event_t *event_list);
178 
179 weed_event_t *get_next_frame_event(weed_event_t *event);
180 weed_event_t *get_prev_frame_event(weed_event_t *event);
181 
182 weed_event_t *get_next_audio_frame_event(weed_event_t *event);
183 weed_event_t *get_prev_audio_frame_event(weed_event_t *event);
184 
185 weed_event_t *get_frame_event_at(weed_event_t *event_list, ticks_t tc, weed_event_t *shortcut, boolean exact);
186 weed_event_t *get_frame_event_at_or_before(weed_event_t *event_list, ticks_t tc, weed_event_t *shortcut);
187 
188 weed_event_t *get_audio_block_start(weed_event_t *event_list, int track, ticks_t tc, boolean seek_back);
189 
190 boolean filter_map_after_frame(weed_event_t *fmap);
191 boolean init_event_is_relevant(weed_event_t *init_event, int ctrack);
192 
193 // definitions in events.c
194 weed_event_t *get_first_event(weed_event_t *event_list);
195 weed_event_t *get_last_event(weed_event_t *event_list);
196 weed_event_t *get_prev_event(weed_event_t *event);
197 weed_event_t *get_next_event(weed_event_t *event);
198 
199 //////////////////////////////////////////////////////////
200 
201 ticks_t get_event_timecode(weed_event_t *);
202 int get_event_type(weed_event_t *);
203 boolean is_blank_frame(weed_event_t *, boolean count_audio);
204 boolean has_audio_frame(weed_event_t *event_list);
205 int get_frame_event_clip(weed_event_t *, int layer);
206 frames_t get_frame_event_frame(weed_event_t *, int layer);
207 boolean frame_event_has_frame_for_track(weed_event_t *event, int track);
208 double *get_track_visibility_at_tc(weed_event_t *event_list, int ntracks, int n_back_tracks,
209                                    ticks_t tc, weed_event_t **shortcut, boolean bleedthru);
210 void get_active_track_list(int *clip_index, int num_tracks, weed_plant_t *filter_map);
211 
212 //////////////////////////////////////////////////////////
213 ///// render details //////////
214 
215 typedef struct {
216   int width;
217   int height;
218   double fps;
219   boolean ratio_fps;
220   LiVESWidget *dialog;
221   LiVESWidget *okbutton;
222   LiVESWidget *usecur_button;
223   LiVESWidget *clipname_entry;
224   LiVESWidget *encoder_combo;
225   LiVESWidget *ofmt_combo;
226   LiVESWidget *acodec_combo;
227   LiVESWidget *acodec_entry;
228   LiVESWidget *spinbutton_width;
229   LiVESWidget *spinbutton_height;
230   LiVESWidget *spinbutton_fps;
231   LiVESWidget *pertrack_checkbutton;
232   LiVESWidget *backaudio_checkbutton;
233   LiVESWidget *always_checkbutton;
234   LiVESWidget *always_hbox;
235   LiVESWidget *debug;
236   LiVESWidget *norm_after;
237   LiVESWidget *afade_in;
238   LiVESWidget *afade_out;
239   LiVESWidget *vfade_in;
240   LiVESWidget *vfade_out;
241   LiVESWidget *vfade_col;
242   ulong encoder_name_fn;
243   ulong encoder_ofmt_fn;
244   boolean enc_changed;
245   char *encoder_name;
246   boolean suggestion_followed;
247 
248   boolean is_encoding;
249 
250   int arate;
251   int achans;
252   int asamps;
253   int aendian;
254 } render_details;
255 
256 render_details *rdet;
257 
258 ////////////////////////////////////////////////////////
259 //// UI stuff ///////
260 
261 LiVESWidget *events_rec_dialog(void);
262 boolean deal_with_render_choice(boolean add_deinit);
263 
264 #define RENDER_CHOICE_NONE 0
265 #define RENDER_CHOICE_DISCARD 1
266 #define RENDER_CHOICE_PREVIEW 2
267 #define RENDER_CHOICE_SAME_CLIP 3
268 #define RENDER_CHOICE_NEW_CLIP 4
269 #define RENDER_CHOICE_MULTITRACK 5
270 #define RENDER_CHOICE_EVENT_LIST 6
271 #define RENDER_CHOICE_TRANSCODE 7
272 
273 LiVESWidget *create_event_list_dialog(weed_plant_t *event_list, ticks_t start_tc, ticks_t end_tc);
274 render_details *create_render_details(int type);
275 
276 LiVESWidget *add_video_options(LiVESWidget **spwidth, int defwidth, LiVESWidget **spheight, int defheight,
277                                LiVESWidget **spfps, double deffps, LiVESWidget **spframes, int defframes,
278                                boolean add_aspect, LiVESWidget *extra);
279 
280 LiVESWidget *add_audio_options(LiVESWidget **cbbackaudio, LiVESWidget **cbpertrack);
281 
282 ////////////////////////////////////////////////////////////////
283 /// rendering
284 
285 boolean render_to_clip(boolean new_clip, boolean transcode);
286 boolean start_render_effect_events(weed_plant_t *event_list, boolean render_vid, boolean render_aud);
287 
288 lives_render_error_t render_events(boolean reset, boolean rend_video, boolean rend_audio);
289 lives_render_error_t render_events_cb(boolean dummy);
290 
291 // effect insertion/updating
292 void insert_filter_init_event_at(weed_plant_t *event_list, weed_plant_t *at_event, weed_plant_t *event);
293 void **filter_init_add_pchanges(weed_plant_t *event_list, weed_plant_t *filter, weed_plant_t *init_event, int ntracks,
294                                 int leave);
295 void insert_filter_deinit_event_at(weed_plant_t *event_list, weed_plant_t *at_event, weed_plant_t *event);
296 boolean insert_filter_map_event_at(weed_plant_t *event_list, weed_plant_t *at_event, weed_plant_t *event,
297                                    boolean before_frames);
298 weed_plant_t *get_filter_map_before(weed_plant_t *event, int ctrack, weed_plant_t *stop_event);
299 weed_plant_t *get_filter_map_after(weed_plant_t *event, int ctrack);
300 void **get_init_events_before(weed_plant_t *event, weed_plant_t *init_event, boolean add);
301 void update_filter_maps(weed_plant_t *event, weed_plant_t *end_event, weed_plant_t *init_event);
302 void insert_param_change_event_at(weed_plant_t *event_list, weed_plant_t *at_event, weed_plant_t *event);
303 weed_plant_t *insert_marker_event_at(weed_plant_t *event_list, weed_plant_t *at_event, int marker_type, livespointer data);
304 
305 void add_init_event_to_filter_map(weed_plant_t *fmap, weed_plant_t *event, void **hints);
306 boolean init_event_in_list(void **init_events, int num_inits, weed_plant_t *event);
307 boolean filter_init_has_owner(weed_plant_t *init_event, int track);
308 boolean init_event_is_process_last(weed_plant_t *event);
309 
310 // effect deletion/moving
311 boolean move_event_right(weed_plant_t *event_list, weed_plant_t *event, boolean can_stay, double fps);
312 boolean move_event_left(weed_plant_t *event_list, weed_plant_t *event, boolean can_stay, double fps);
313 
314 void move_filter_init_event(weed_plant_t *event_list, ticks_t new_tc, weed_plant_t *init_event, double fps);
315 void move_filter_deinit_event(weed_plant_t *event_list, ticks_t new_tc, weed_plant_t *deinit_event,
316                               double fps, boolean rescale_pchanges);
317 
318 // event deletion
319 void unlink_event(weed_plant_t *event_list, weed_plant_t *event);
320 void delete_event(weed_plant_t *event_list, weed_plant_t *event);
321 
322 // event replacement
323 void replace_event(weed_plant_t *event_list, weed_plant_t *at_event, weed_plant_t *event);
324 
325 // event insertion
326 boolean insert_event_before(weed_plant_t *at_event, weed_plant_t *event);
327 boolean insert_event_after(weed_plant_t *at_event, weed_plant_t *event);
328 
329 // param changes
330 void ** *get_event_pchains(void);
331 ticks_t get_next_paramchange(void **pchange_next, ticks_t end_tc);
332 ticks_t get_prev_paramchange(void **pchange_next, ticks_t start_tc);
333 boolean is_init_pchange(weed_plant_t *init_event, weed_plant_t *pchange_event);
334 void free_pchains(int key);
335 
336 // audio
337 /// returns clip number for track (track==-1 is backing audio)
338 int get_audio_frame_clip(weed_plant_t *event, int track);
339 
340 /// returns velocity for track (track==-1 is backing audio)
341 double get_audio_frame_vel(weed_plant_t *event, int track);
342 
343 /// returns velocity for track (track==-1 is backing audio)
344 double get_audio_frame_seek(weed_plant_t *event, int track);
345 
346 // playback
347 
348 void backup_host_tags(weed_plant_t *event_list, ticks_t curr_tc);
349 void restore_host_tags(weed_plant_t *event_list, ticks_t curr_tc);
350 
351 boolean has_frame_event_at(weed_plant_t *event_list, ticks_t tc, weed_plant_t **shortcut);
352 
353 #define EVENT_MARKER_BLOCK_START 1
354 #define EVENT_MARKER_BLOCK_UNORDERED 512
355 #define EVENT_MARKER_RECORD_START 1024
356 #define EVENT_MARKER_RECORD_END 1025
357 
358 #define WEED_PLANT_IS_EVENT(plant) ((plant != NULL && weed_get_plant_type(plant) == WEED_PLANT_EVENT) ? 1 : 0)
359 #define WEED_PLANT_IS_EVENT_LIST(plant) ((plant != NULL && weed_get_plant_type(plant) == WEED_PLANT_EVENT_LIST) ? 1 : 0)
360 
361 #define WEED_EVENT_IS_FRAME(event) (get_event_type(event) == WEED_EVENT_TYPE_FRAME ? 1 : 0)
362 #define WEED_EVENT_IS_AUDIO_FRAME(event) ((get_event_type(event) == WEED_EVENT_TYPE_FRAME \
363 					   && weed_plant_has_leaf(event, WEED_LEAF_AUDIO_CLIPS)) ? 1 : 0)
364 #define WEED_EVENT_IS_FILTER_INIT(event) (get_event_type(event) == WEED_EVENT_TYPE_FILTER_INIT ? 1 : 0)
365 #define WEED_EVENT_IS_FILTER_DEINIT(event) (get_event_type(event) == WEED_EVENT_TYPE_FILTER_DEINIT ? 1 : 0)
366 #define WEED_EVENT_IS_FILTER_MAP(event) (get_event_type(event) == WEED_EVENT_TYPE_FILTER_MAP ? 1 : 0)
367 #define WEED_EVENT_IS_PARAM_CHANGE(event) (get_event_type(event) == WEED_EVENT_TYPE_PARAM_CHANGE ? 1 : 0)
368 #define WEED_EVENT_IS_MARKER(event) (get_event_type(event) == WEED_EVENT_TYPE_MARKER ? 1 : 0)
369 
370 #endif // HAS_LIVES_EVENTS_H
371