upgrade ffmpeg to 3.4.2, add proxy popup, undo/redo deadlock fix, rework nested edl
[goodguy/history.git] / cinelerra-5.1 / cinelerra / vwindow.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "asset.h"
23 #include "assets.h"
24 #include "bcsignals.h"
25 #include "clip.h"
26 #include "clipedit.h"
27 #include "bchash.h"
28 #include "edl.h"
29 #include "edlsession.h"
30 #include "filesystem.h"
31 #include "filexml.h"
32 #include "indexable.h"
33 #include "language.h"
34 #include "localsession.h"
35 #include "mainclock.h"
36 #include "mainmenu.h"
37 #include "mainsession.h"
38 #include "mwindow.h"
39 #include "mwindowgui.h"
40 #include "playbackengine.h"
41 #include "tracks.h"
42 #include "transportque.h"
43 #include "vplayback.h"
44 #include "vtimebar.h"
45 #include "vtracking.h"
46 #include "vwindow.h"
47 #include "vwindowgui.h"
48
49
50 VWindow::VWindow(MWindow *mwindow)
51  : BC_DialogThread()
52 {
53         this->mwindow = mwindow;
54         gui = 0;
55         playback_engine = 0;
56         playback_cursor = 0;
57         clip_edit = 0;
58         indexable = 0;
59         edl = 0;
60 }
61
62
63 VWindow::~VWindow()
64 {
65         close_window();
66 //printf("VWindow::~VWindow 1\n");
67         delete playback_engine;
68 //printf("VWindow::~VWindow 1\n");
69         delete playback_cursor;
70         delete_source(1, 0);
71         delete clip_edit;
72 //printf("VWindow::~VWindow 2\n");
73 }
74
75 void VWindow::delete_source(int do_main_edl, int update_gui)
76 {
77 //printf("VWindow::delete_source %d %d %p %p\n", __LINE__, gui->get_window_lock(), edl, indexable);
78         if(do_main_edl) mwindow->edl->remove_vwindow_edl(get_edl());
79
80         if(edl)
81         {
82                 edl->Garbage::remove_user();
83 //printf("VWindow::delete_source %d\n", __LINE__);
84                 edl = 0;
85         }
86
87 //      if(mwindow->edl->vwindow_edl && !mwindow->edl->vwindow_edl_shared)
88 //      {
89 //              mwindow->edl->vwindow_edl->Garbage::remove_user();
90 //              mwindow->edl->vwindow_edl = 0;
91 //              mwindow->edl->vwindow_edl_shared = 0;
92 //      }
93
94 //printf("VWindow::delete_source %d\n", __LINE__);
95         if(indexable) indexable->Garbage::remove_user();
96         indexable = 0;
97
98         if(update_gui) gui->change_source(0, _("Viewer"));
99 //printf("VWindow::delete_source %d\n", __LINE__);
100 }
101
102
103 void VWindow::load_defaults()
104 {
105 }
106
107 void VWindow::create_objects()
108 {
109 }
110
111
112 void VWindow::handle_done_event(int result)
113 {
114         playback_engine->interrupt_playback(1);
115         delete_source(1, 0);
116         if( mwindow->in_destructor ) return;
117
118         int total = 0;
119         for(int i = 0; i < mwindow->vwindows.size(); i++)
120         {
121
122 //printf("VWindow::handle_done_event %d %d\n", __LINE__, mwindow->vwindows.get(i)->is_running());
123                 if(mwindow->vwindows.get(i)->is_running()) total++;
124         }
125 // subtract ourselves
126         total--;
127
128 // Update the menu if no viewers visible
129         if(!total)
130         {
131                 mwindow->gui->lock_window("VWindowGUI::close_event");
132                 mwindow->gui->mainmenu->show_vwindow->set_checked(0);
133                 mwindow->gui->unlock_window();
134
135                 mwindow->session->show_vwindow = 0;
136                 mwindow->save_defaults();
137         }
138 }
139
140 BC_Window* VWindow::new_gui()
141 {
142 //printf("VWindow::create_objects 1\n");
143         gui = new VWindowGUI(mwindow, this);
144 //printf("VWindow::create_objects 1\n");
145         gui->create_objects();
146 //printf("VWindow::create_objects 1\n");
147
148         playback_engine = new VPlayback(mwindow, this, gui->canvas);
149 //printf("VWindow::create_objects 1\n");
150
151 // Start command loop
152         playback_engine->create_objects();
153 //printf("VWindow::create_objects 1\n");
154         gui->transport->set_engine(playback_engine);
155 //printf("VWindow::create_objects 1\n");
156         playback_cursor = new VTracking(mwindow, this);
157 //printf("VWindow::create_objects 1\n");
158         playback_cursor->create_objects();
159 //printf("VWindow::create_objects 2\n");
160
161         clip_edit = new ClipEdit(mwindow, 0, this);
162         return gui;
163 }
164
165 void VWindow::handle_close_event(int result)
166 {
167         delete playback_engine;
168         playback_engine = 0;
169 }
170
171
172 EDL* VWindow::get_edl()
173 {
174 //      return mwindow->edl->vwindow_edl;
175         return edl;
176 }
177
178 Indexable* VWindow::get_source()
179 {
180         return this->indexable;
181 }
182
183 void VWindow::change_source(int edl_number)
184 {
185         if(!is_running()) return;
186         if( playback_engine->is_playing_back )
187                 stop_playback(1);
188
189         gui->lock_window("VWindow::change_source 1");
190 //printf("VWindow::change_source %d %p\n", __LINE__, mwindow->edl->get_vwindow_edl(edl_number));
191         if( edl_number >= 0 && edl_number < mwindow->edl->total_vwindow_edls() &&
192                  mwindow->edl->get_vwindow_edl(edl_number) )
193         {
194                 this->edl = mwindow->edl->get_vwindow_edl(edl_number);
195                 this->edl->Garbage::add_user();
196                 gui->change_source(get_edl(), get_edl()->local_session->clip_title);
197                 update_position(CHANGE_ALL, 1, 1, 1);
198         }
199         else
200         {
201                 delete_source(1, 1);
202 //              if(indexable) indexable->Garbage::remove_user();
203 //              indexable = 0;
204 //              mwindow->edl->vwindow_edl_shared = 0;
205         }
206         gui->unlock_window();
207 }
208
209 void VWindow::change_source(Indexable *indexable)
210 {
211         if( !indexable->is_asset ) {
212                 change_source((EDL*)indexable);
213                 return;
214         }
215         if(!running()) return;
216         if( playback_engine->is_playing_back )
217                 stop_playback(1);
218
219         gui->lock_window("VWindow::change_source 2");
220
221         char title[BCTEXTLEN];
222         FileSystem fs;
223         fs.extract_name(title, indexable->path);
224         delete_source(1, 0);
225
226 // Create EDL
227         this->edl = new EDL(mwindow->edl);
228         this->edl->create_objects();
229         mwindow->edl->append_vwindow_edl(this->edl, 1);
230
231 // Generate EDL off of main EDL for cutting
232         Asset *asset = new Asset;
233         asset->copy_from((Asset*)indexable, 0);
234         this->indexable = asset;
235         mwindow->asset_to_edl(this->edl, asset);
236
237 // Update GUI
238         gui->change_source(this->edl, title);
239         update_position(CHANGE_ALL, 1, 1, 1);
240
241         gui->unlock_window();
242 }
243
244 void VWindow::change_source(EDL *edl)
245 {
246         if(!running()) return;
247         if( playback_engine->is_playing_back )
248                 stop_playback(1);
249
250 //printf("VWindow::change_source %d %p\n", __LINE__, edl);
251 // EDLs are identical
252 //      if(edl && mwindow->edl->vwindow_edl &&
253 //              edl->id == mwindow->edl->vwindow_edl->id) return;
254         if(edl && get_edl() && edl->id == get_edl()->id) return;
255
256         gui->lock_window("VWindow::change_source 3");
257
258         delete_source(1, 0);
259
260         if(edl)
261         {
262                 mwindow->edl->append_vwindow_edl(edl, 1);
263                 this->edl = edl;
264                 this->edl->Garbage::add_user();
265
266 //              mwindow->edl->vwindow_edl = edl;
267 // in order not to later delete edl if it is shared
268 //              edl->Garbage::add_user();
269 //              mwindow->edl->vwindow_edl_shared = 1;
270
271 // Update GUI
272                 gui->change_source(edl, edl->local_session->clip_title);
273                 update_position(CHANGE_ALL, 1, 1, 1);
274         }
275         else
276                 gui->change_source(edl, _("Viewer"));
277         gui->unlock_window();
278 }
279
280
281 void VWindow::goto_start()
282 {
283         if(get_edl())
284         {
285                 get_edl()->local_session->set_selectionstart(0);
286                 get_edl()->local_session->set_selectionend(0);
287                 update_position(CHANGE_NONE,
288                         0,
289                         1,
290                         0);
291         }
292 }
293
294 void VWindow::goto_end()
295 {
296         if(get_edl())
297         {
298                 double position = get_edl()->tracks->total_length();
299                 get_edl()->local_session->set_selectionstart(position);
300                 get_edl()->local_session->set_selectionend(position);
301                 update_position(CHANGE_NONE,
302                         0,
303                         1,
304                         0);
305         }
306 }
307
308 void VWindow::update(int do_timebar)
309 {
310         if(do_timebar)
311                 gui->timebar->update(1);
312 }
313
314 void VWindow::update_position(int change_type,
315         int use_slider,
316         int update_slider,
317         int lock_window)
318 {
319         EDL *edl = get_edl();
320         if(edl)
321         {
322 //printf("VWindow::update_position %d\n", __LINE__);
323 //edl->dump();
324                 playback_engine->refresh_frame(change_type, edl);
325
326                 double position = edl->local_session->get_selectionstart(1);
327                 if(lock_window) gui->lock_window("VWindow::update_position");
328                 gui->clock->update(position);
329                 gui->timebar->update(1);
330                 if(lock_window) gui->unlock_window();
331         }
332 }
333
334 void VWindow::stop_playback(int wait)
335 {
336         playback_engine->stop_playback(wait);
337 }
338
339 int VWindow::update_position(double position)
340 {
341         EDL *edl = get_edl();
342         if(edl)
343         {
344                 gui->unlock_window();
345
346                 playback_engine->interrupt_playback(1);
347
348                 position = mwindow->edl->align_to_frame(position, 0);
349                 position = MAX(0, position);
350
351                 edl->local_session->set_selectionstart(position);
352                 edl->local_session->set_selectionend(position);
353
354                 gui->lock_window("VWindow::update_position 1");
355                 update_position(CHANGE_NONE, 0, 1, 0);
356         }
357
358         return 1;
359 }
360
361 void VWindow::set_inpoint()
362 {
363         EDL *edl = get_edl();
364         if(edl)
365         {
366                 edl->set_inpoint(edl->local_session->get_selectionstart(1));
367                 gui->timebar->update(1);
368         }
369 }
370
371 void VWindow::set_outpoint()
372 {
373         EDL *edl = get_edl();
374         if(edl)
375         {
376                 edl->set_outpoint(edl->local_session->get_selectionstart(1));
377                 gui->timebar->update(1);
378         }
379 }
380
381 void VWindow::unset_inoutpoint()
382 {
383         EDL *edl = get_edl();
384         if(edl)
385         {
386                 edl->unset_inoutpoint();
387                 gui->timebar->update(1);
388         }
389 }
390
391 void VWindow::copy(int all)
392 {
393         EDL *edl = get_edl();
394         if(edl)
395         {
396                 double start = all ? 0 :
397                         edl->local_session->get_selectionstart();
398                 double end = all ? edl->tracks->total_length() :
399                         edl->local_session->get_selectionend();
400                 EDL *copy_edl = new EDL; // no parent or assets wont be copied
401                 copy_edl->create_objects();
402                 copy_edl->copy_all(edl);
403                 FileXML file;
404                 copy_edl->copy(start, end, 0, &file, "", 1);
405                 copy_edl->remove_user();
406                 const char *file_string = file.string();
407                 long file_length = strlen(file_string);
408                 mwindow->gui->lock_window();
409                 mwindow->gui->to_clipboard(file_string, file_length, BC_PRIMARY_SELECTION);
410                 mwindow->gui->to_clipboard(file_string, file_length, SECONDARY_SELECTION);
411                 mwindow->gui->unlock_window();
412         }
413 }
414
415 void VWindow::splice_selection()
416 {
417 }
418
419 void VWindow::overwrite_selection()
420 {
421 }
422