allow ffmpeg video to resample curr_pos, add bluray format
[goodguy/history.git] / cinelerra-5.0 / 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 "clip.h"
25 #include "clipedit.h"
26 #include "bchash.h"
27 #include "edl.h"
28 #include "edlsession.h"
29 #include "filesystem.h"
30 #include "filexml.h"
31 #include "indexable.h"
32 #include "language.h"
33 #include "localsession.h"
34 #include "mainclock.h"
35 #include "mainmenu.h"
36 #include "mainsession.h"
37 #include "mwindow.h"
38 #include "mwindowgui.h"
39 #include "playbackengine.h"
40 #include "tracks.h"
41 #include "transportque.h"
42 #include "vplayback.h"
43 #include "vtimebar.h"
44 #include "vtracking.h"
45 #include "vwindow.h"
46 #include "vwindowgui.h"
47
48
49 VWindow::VWindow(MWindow *mwindow) : BC_DialogThread()
50 {
51         this->mwindow = mwindow;
52         gui = 0;
53         playback_engine = 0;
54         playback_cursor = 0;
55         clip_edit = 0;
56         indexable = 0;
57         edl = 0;
58 }
59
60
61 VWindow::~VWindow()
62 {
63         if(is_running()) {
64                 close_window();
65                 join();
66         }
67 //printf("VWindow::~VWindow 1\n");
68         delete playback_engine;
69 //printf("VWindow::~VWindow 1\n");
70         delete playback_cursor;
71         delete_source(1, 0);
72         delete clip_edit;
73 //printf("VWindow::~VWindow 2\n");
74 }
75
76 void VWindow::delete_source(int do_main_edl, int update_gui)
77 {
78         if(do_main_edl) mwindow->edl->remove_vwindow_edl(get_edl());
79
80
81         if(edl)
82         {
83 //printf("VWindow::delete_source %d %p\n", __LINE__, edl);
84                 edl->Garbage::remove_user();
85 //printf("VWindow::delete_source %d\n", __LINE__);
86                 edl = 0;
87         }
88
89 //      if(mwindow->edl->vwindow_edl && !mwindow->edl->vwindow_edl_shared)
90 //      {
91 //              mwindow->edl->vwindow_edl->Garbage::remove_user();
92 //              mwindow->edl->vwindow_edl = 0;
93 //              mwindow->edl->vwindow_edl_shared = 0;
94 //      }
95
96 //printf("VWindow::delete_source %d\n", __LINE__);
97         if(indexable) indexable->Garbage::remove_user();
98 //printf("VWindow::delete_source %d\n", __LINE__);
99         indexable = 0;
100
101         if(update_gui) gui->change_source(0, _("Viewer"));
102 }
103
104
105 void VWindow::load_defaults()
106 {
107 }
108
109 void VWindow::create_objects()
110 {
111 }
112
113
114 void VWindow::handle_close_event(int result)
115 {
116         delete_source(1, 0);
117         delete playback_engine;
118         delete playback_cursor;
119         delete clip_edit;
120         playback_engine = 0;
121         playback_cursor = 0;
122         clip_edit = 0;
123         if( mwindow->in_destructor ) return;
124
125         int total = 0;
126         for(int i = 0; i < mwindow->vwindows.size(); i++)
127         {
128
129 //printf("VWindow::handle_close_event %d %d\n", __LINE__, mwindow->vwindows.get(i)->is_running());
130                 if(mwindow->vwindows.get(i)->is_running()) total++;
131         }
132 // subtract ourselves
133         total--;
134
135 // Update the menu if no viewers visible
136         if(!total)
137         {
138                 mwindow->gui->lock_window("VWindowGUI::close_event");
139                 mwindow->gui->mainmenu->show_vwindow->set_checked(0);
140                 mwindow->gui->unlock_window();
141                 
142                 mwindow->session->show_vwindow = 0;
143                 mwindow->save_defaults();
144         }
145 }
146
147
148
149 BC_Window* VWindow::new_gui()
150 {
151 //printf("VWindow::create_objects 1\n");
152         gui = new VWindowGUI(mwindow, this);
153 //printf("VWindow::create_objects 1\n");
154         gui->create_objects();
155 //printf("VWindow::create_objects 1\n");
156
157         playback_engine = new VPlayback(mwindow, this, gui->canvas);
158 //printf("VWindow::create_objects 1\n");
159
160 // Start command loop
161         playback_engine->create_objects();
162 //printf("VWindow::create_objects 1\n");
163         gui->transport->set_engine(playback_engine);
164 //printf("VWindow::create_objects 1\n");
165         playback_cursor = new VTracking(mwindow, this);
166 //printf("VWindow::create_objects 1\n");
167         playback_cursor->create_objects();
168 //printf("VWindow::create_objects 2\n");
169
170         clip_edit = new ClipEdit(mwindow, 0, this);
171         return gui;
172 }
173
174
175 EDL* VWindow::get_edl()
176 {
177 //      return mwindow->edl->vwindow_edl;
178         return edl;
179 }
180
181 Indexable* VWindow::get_source()
182 {
183         return this->indexable;
184 }
185
186 void VWindow::change_source(int edl_number)
187 {
188         if(!is_running()) return;
189
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 }
207
208 void VWindow::change_source(Indexable *indexable)
209 {
210         if(!running()) return;
211 //printf("VWindow::change_source %d\n", __LINE__);
212 //      if(asset && this->asset &&
213 //              asset->id == this->asset->id &&
214 //              asset == this->asset) return;
215
216 //printf("VWindow::change_source %d\n", __LINE__);
217
218         char title[BCTEXTLEN];
219         FileSystem fs;
220         fs.extract_name(title, indexable->path);
221 //printf("VWindow::change_source 1\n");
222
223         delete_source(1, 0);
224 //printf("VWindow::change_source 1\n");
225
226 // Generate EDL off of main EDL for cutting
227         Asset *asset = 0;
228         EDL *nested_edl = 0;
229         if(indexable->is_asset)
230         {
231                 this->indexable = asset = new Asset;
232                 asset->copy_from((Asset*)indexable, 0);
233         }
234         else
235         {
236                 this->indexable = nested_edl = new EDL;
237                 nested_edl->create_objects();
238                 nested_edl->copy_all((EDL*)indexable);
239         }
240
241 // Create EDL
242         this->edl = new EDL(mwindow->edl);
243         this->edl->create_objects();
244         mwindow->edl->append_vwindow_edl(this->edl, 1);
245
246 //      mwindow->edl->vwindow_edl = new EDL(mwindow->edl);
247 //      mwindow->edl->vwindow_edl_shared = 0;
248 //      mwindow->edl->vwindow_edl->create_objects();
249
250 //printf("VWindow::change_source 1 %d %p %p\n", __LINE__, asset, nested_edl);
251         if(asset)
252                 mwindow->asset_to_edl(this->edl, asset);
253         else
254                 mwindow->edl_to_nested(this->edl, nested_edl);
255
256 // Update GUI
257         gui->change_source(this->edl, title);
258         update_position(CHANGE_ALL, 1, 1, 1);
259
260
261
262 //printf("VWindow::change_source 2\n");
263 }
264
265 void VWindow::change_source(EDL *edl)
266 {
267         if(!running()) return;
268 //printf("VWindow::change_source %d %p\n", __LINE__, edl);
269 // EDLs are identical
270 //      if(edl && mwindow->edl->vwindow_edl && 
271 //              edl->id == mwindow->edl->vwindow_edl->id) return;
272         if(edl && get_edl() && edl->id == get_edl()->id) return;
273
274         delete_source(1, 0);
275
276         if(edl)
277         {
278                 mwindow->edl->append_vwindow_edl(edl, 1);
279                 this->edl = edl;
280                 this->edl->Garbage::add_user();
281
282 //              mwindow->edl->vwindow_edl = edl;
283 // in order not to later delete edl if it is shared
284 //              edl->Garbage::add_user();
285 //              mwindow->edl->vwindow_edl_shared = 1;
286
287 // Update GUI
288                 gui->change_source(edl, edl->local_session->clip_title);
289                 update_position(CHANGE_ALL, 1, 1, 1);
290         }
291         else
292                 gui->change_source(edl, _("Viewer"));
293 }
294
295 void VWindow::change_source(char *folder, int item)
296 {
297 //printf("VWindow::change_source %d\n", __LINE__);
298         int result = 0;
299         if(!running()) return;
300 // Search EDLs
301         if(!strcasecmp(folder, CLIP_FOLDER))
302         {
303                 if(item < mwindow->edl->clips.total)
304                 {
305                         change_source(mwindow->edl->clips.values[item]);
306                         result = 1;
307                 }
308         }
309         else
310 // Search media
311         if(!strcasecmp(folder, MEDIA_FOLDER))
312         {
313                 if(item < mwindow->edl->assets->total())
314                 {
315                         change_source(mwindow->edl->assets->get_item_number(item));
316                         result = 1;
317                 }
318         }
319         else
320 // Search extra clip folders
321         {
322         }
323         
324         if(!result)
325         {
326                 delete_source(1, 1);
327         }
328 }
329
330
331
332
333 void VWindow::goto_start()
334 {
335         if(get_edl())
336         {
337                 get_edl()->local_session->set_selectionstart(0);
338                 get_edl()->local_session->set_selectionend(0);
339                 update_position(CHANGE_NONE, 
340                         0, 
341                         1, 
342                         0);
343         }
344 }
345
346 void VWindow::goto_end()
347 {
348         if(get_edl())
349         {
350                 double position = get_edl()->tracks->total_length();
351                 get_edl()->local_session->set_selectionstart(position);
352                 get_edl()->local_session->set_selectionend(position);
353                 update_position(CHANGE_NONE, 
354                         0, 
355                         1,
356                         0);
357         }
358 }
359
360 void VWindow::update(int do_timebar)
361 {
362         if(do_timebar)
363                 gui->timebar->update(1);
364 }
365
366 void VWindow::update_position(int change_type, 
367         int use_slider, 
368         int update_slider,
369         int lock_window)
370 {
371         EDL *edl = get_edl();
372         if(edl)
373         {
374 //printf("VWindow::update_position %d\n", __LINE__);
375 //edl->dump();
376                 playback_engine->que->send_command(CURRENT_FRAME, 
377                         change_type,
378                         edl,
379                         1);
380
381                 if(lock_window) gui->lock_window("VWindow::update_position");
382                 gui->clock->update(edl->local_session->get_selectionstart(1));
383                 if(lock_window) gui->unlock_window();
384         }
385 }
386
387
388
389
390
391 int VWindow::update_position(double position)
392 {
393         EDL *edl = get_edl();
394         if(edl)
395         {
396                 gui->unlock_window();
397
398                 playback_engine->interrupt_playback(1);
399
400                 position = mwindow->edl->align_to_frame(position, 0);
401                 position = MAX(0, position);
402
403                 edl->local_session->set_selectionstart(position);
404                 edl->local_session->set_selectionend(position);
405
406                 gui->lock_window("VWindow::update_position 1");
407                 update_position(CHANGE_NONE, 0, 1, 0);
408         }
409
410         return 1;
411 }
412
413
414 void VWindow::set_inpoint()
415 {
416         EDL *edl = get_edl();
417         if(edl)
418         {
419                 edl->set_inpoint(edl->local_session->get_selectionstart(1));
420                 gui->timebar->update(1);
421         }
422 }
423
424 void VWindow::set_outpoint()
425 {
426         EDL *edl = get_edl();
427         if(edl)
428         {
429                 edl->set_outpoint(edl->local_session->get_selectionstart(1));
430                 gui->timebar->update(1);
431         }
432 }
433
434 void VWindow::clear_inpoint()
435 {
436         EDL *edl = get_edl();
437         if(edl)
438         {
439                 edl->local_session->unset_inpoint();
440                 gui->timebar->update(1);
441         }
442 }
443
444 void VWindow::clear_outpoint()
445 {
446         EDL *edl = get_edl();
447         if(edl)
448         {
449                 edl->local_session->unset_outpoint();
450                 gui->timebar->update(1);
451         }
452 }
453
454 void VWindow::copy()
455 {
456         EDL *edl = get_edl();
457         if(edl)
458         {
459                 double start = edl->local_session->get_selectionstart();
460                 double end = edl->local_session->get_selectionend();
461                 FileXML file;
462                 edl->copy(start,
463                         end,
464                         0,
465                         0,
466                         0,
467                         &file,
468                         "",
469                         1);
470                 const char *file_string = file.string();
471                 long file_length = strlen(file_string);
472                 mwindow->gui->lock_window();
473                 mwindow->gui->get_clipboard()->to_clipboard(file_string, file_length,
474                         SECONDARY_SELECTION);
475                 mwindow->gui->get_clipboard()->to_clipboard(file_string, file_length,
476                         BC_PRIMARY_SELECTION);
477                 mwindow->gui->unlock_window();
478         }
479 }
480
481 void VWindow::splice_selection()
482 {
483 }
484
485 void VWindow::overwrite_selection()
486 {
487 }
488