156d86ab7ba84d520ac3bafa2bfd428a64c9eec3
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / assetpopup.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 "assetedit.h"
24 #include "assetpopup.h"
25 #include "assetremove.h"
26 #include "assets.h"
27 #include "awindow.h"
28 #include "awindowgui.h"
29 #include "bccapture.h"
30 #include "bcdisplayinfo.h"
31 #include "bcsignals.h"
32 #include "cache.h"
33 #include "clipedit.h"
34 #include "cstrdup.h"
35 #include "cwindow.h"
36 #include "cwindowgui.h"
37 #include "edl.h"
38 #include "edlsession.h"
39 #include "file.h"
40 #include "filesystem.h"
41 #include "filexml.h"
42 #include "language.h"
43 #include "loadfile.h"
44 #include "localsession.h"
45 #include "mainerror.h"
46 #include "mainindexes.h"
47 #include "mainmenu.h"
48 #include "mainsession.h"
49 #include "mwindow.h"
50 #include "mwindowgui.h"
51 #include "preferences.h"
52 #include "renderengine.h"
53 #include "tracks.h"
54 #include "transportque.h"
55 #include "vframe.h"
56 #include "vrender.h"
57 #include "vwindow.h"
58 #include "vwindowgui.h"
59 #include "zwindow.h"
60
61
62 AssetPopup::AssetPopup(MWindow *mwindow, AWindowGUI *gui)
63  : BC_PopupMenu(0, 0, 0, "", 0)
64 {
65         this->mwindow = mwindow;
66         this->gui = gui;
67 }
68
69 AssetPopup::~AssetPopup()
70 {
71 }
72
73 void AssetPopup::create_objects()
74 {
75         BC_MenuItem *menu_item;
76         BC_SubMenu *submenu;
77         add_item(info = new AssetPopupInfo(mwindow, this));
78         add_item(format = new AWindowListFormat(mwindow, gui));
79         add_item(new AssetPopupSort(mwindow, this));
80         add_item(index = new AssetPopupBuildIndex(mwindow, this));
81         add_item(view = new AssetPopupView(mwindow, this));
82         add_item(view_window = new AssetPopupViewWindow(mwindow, this));
83         add_item(open_mixer = new AssetPopupOpenMixer(mwindow, this));
84         add_item(insert_mixer = new AssetPopupInsertMixer(mwindow, this));
85         add_item(new AssetPopupPaste(mwindow, this));
86         add_item(menu_item = new BC_MenuItem(_("Match...")));
87         menu_item->add_submenu(submenu = new BC_SubMenu());
88         submenu->add_submenuitem(new AssetMatchSize(mwindow, this));
89         submenu->add_submenuitem(new AssetMatchRate(mwindow, this));
90         submenu->add_submenuitem(new AssetMatchAll(mwindow, this));
91         add_item(menu_item = new BC_MenuItem(_("Remove...")));
92         menu_item->add_submenu(submenu = new BC_SubMenu());
93         submenu->add_submenuitem(new AssetPopupProjectRemove(mwindow, this));
94         submenu->add_submenuitem(new AssetPopupDiskRemove(mwindow, this));
95 }
96
97 void AssetPopup::paste_assets()
98 {
99 // Collect items into the drag vectors for temporary storage
100         gui->lock_window("AssetPopup::paste_assets");
101         mwindow->gui->lock_window("AssetPopup::paste_assets");
102         mwindow->cwindow->gui->lock_window("AssetPopup::paste_assets");
103
104         int proxy = mwindow->edl->session->awindow_folder == AW_PROXY_FOLDER ? 1 : 0;
105         gui->collect_assets(proxy);
106         mwindow->paste_assets(mwindow->edl->local_session->get_selectionstart(1),
107                 mwindow->edl->tracks->first, 0);   // do not overwrite
108
109         gui->unlock_window();
110         mwindow->gui->unlock_window();
111         mwindow->cwindow->gui->unlock_window();
112 }
113
114 void AssetPopup::match_size()
115 {
116 // Collect items into the drag vectors for temporary storage
117         gui->collect_assets();
118         mwindow->gui->lock_window("AssetPopup::match_size");
119         mwindow->asset_to_size();
120         mwindow->gui->unlock_window();
121 }
122
123 void AssetPopup::match_rate()
124 {
125 // Collect items into the drag vectors for temporary storage
126         gui->collect_assets();
127         mwindow->gui->lock_window("AssetPopup::match_rate");
128         mwindow->asset_to_rate();
129         mwindow->gui->unlock_window();
130 }
131
132 void AssetPopup::match_all()
133 {
134 // Collect items into the drag vectors for temporary storage
135         gui->collect_assets();
136         mwindow->gui->lock_window("AssetPopup::match_rate");
137         mwindow->asset_to_all();
138         mwindow->gui->unlock_window();
139 }
140
141 int AssetPopup::update()
142 {
143         format->update();
144         int proxy = mwindow->edl->session->awindow_folder == AW_PROXY_FOLDER ? 1 : 0;
145         gui->collect_assets(proxy);
146         return 0;
147 }
148
149
150 AssetPopupInfo::AssetPopupInfo(MWindow *mwindow, AssetPopup *popup)
151  : BC_MenuItem(_("Info..."))
152 {
153         this->mwindow = mwindow;
154         this->popup = popup;
155 }
156
157 AssetPopupInfo::~AssetPopupInfo()
158 {
159 }
160
161 int AssetPopupInfo::handle_event()
162 {
163         int cur_x, cur_y;
164         popup->gui->get_abs_cursor(cur_x, cur_y);
165         int n = mwindow->session->drag_assets->size();
166         if( n > 0 ) {
167                 int xs30 = xS(30), ys30 = yS(30);
168                 for( int i=0; i<n; ++i ) {
169                         AssetEdit *asset_edit = mwindow->awindow->get_asset_editor();
170                         asset_edit->edit_asset(
171                                 mwindow->session->drag_assets->values[i], cur_x-xs30*i, cur_y-ys30*i);
172                 }
173         }
174         else if( mwindow->session->drag_clips->size() ) {
175                 popup->gui->awindow->clip_edit->edit_clip(
176                         mwindow->session->drag_clips->values[0], cur_x, cur_y);
177         }
178         return 1;
179 }
180
181
182 AssetPopupBuildIndex::AssetPopupBuildIndex(MWindow *mwindow, AssetPopup *popup)
183  : BC_MenuItem(_("Rebuild index"))
184 {
185         this->mwindow = mwindow;
186         this->popup = popup;
187 }
188
189 AssetPopupBuildIndex::~AssetPopupBuildIndex()
190 {
191 }
192
193 int AssetPopupBuildIndex::handle_event()
194 {
195 //printf("AssetPopupBuildIndex::handle_event 1\n");
196         mwindow->rebuild_indices();
197         return 1;
198 }
199
200
201 AssetPopupSort::AssetPopupSort(MWindow *mwindow, AssetPopup *popup)
202  : BC_MenuItem(_("Sort"))
203 {
204         this->mwindow = mwindow;
205         this->popup = popup;
206 }
207
208 AssetPopupSort::~AssetPopupSort()
209 {
210 }
211
212 int AssetPopupSort::handle_event()
213 {
214         mwindow->awindow->gui->sort_assets();
215         return 1;
216 }
217
218
219 AssetPopupView::AssetPopupView(MWindow *mwindow, AssetPopup *popup)
220  : BC_MenuItem(_("View"))
221 {
222         this->mwindow = mwindow;
223         this->popup = popup;
224 }
225
226 AssetPopupView::~AssetPopupView()
227 {
228 }
229
230 int AssetPopupView::handle_event()
231 {
232         VWindow *vwindow = mwindow->get_viewer(1, DEFAULT_VWINDOW);
233
234         if( mwindow->session->drag_assets->total )
235                 vwindow->change_source(
236                         mwindow->session->drag_assets->values[0]);
237         else
238         if( mwindow->session->drag_clips->total )
239                 vwindow->change_source(
240                         mwindow->session->drag_clips->values[0]);
241
242         return 1;
243 }
244
245
246 AssetPopupViewWindow::AssetPopupViewWindow(MWindow *mwindow, AssetPopup *popup)
247  : BC_MenuItem(_("View in new window"))
248 {
249         this->mwindow = mwindow;
250         this->popup = popup;
251 }
252
253 AssetPopupViewWindow::~AssetPopupViewWindow()
254 {
255 }
256
257 int AssetPopupViewWindow::handle_event()
258 {
259         for( int i=0; i<mwindow->session->drag_assets->size(); ++i ) {
260                 VWindow *vwindow = mwindow->get_viewer(1);
261                 vwindow->gui->lock_window("AssetPopupView::handle_event 1");
262                 vwindow->change_source(mwindow->session->drag_assets->get(i));
263                 vwindow->gui->unlock_window();
264         }
265         for( int i=0; i<mwindow->session->drag_clips->size(); ++i ) {
266                 VWindow *vwindow = mwindow->get_viewer(1);
267                 vwindow->gui->lock_window("AssetPopupView::handle_event 2");
268                 vwindow->change_source(mwindow->session->drag_clips->get(i));
269                 vwindow->gui->unlock_window();
270         }
271         return 1;
272 }
273
274 AssetPopupOpenMixer::AssetPopupOpenMixer(MWindow *mwindow, AssetPopup *popup)
275  : BC_MenuItem(_("Open Mixers"))
276 {
277         this->mwindow = mwindow;
278         this->popup = popup;
279 }
280
281 AssetPopupOpenMixer::~AssetPopupOpenMixer()
282 {
283 }
284
285 int AssetPopupOpenMixer::handle_event()
286 {
287         mwindow->gui->lock_window("AssetPopupOpenMixer::handle_event");
288         mwindow->create_mixers();
289         mwindow->gui->unlock_window();
290         return 1;
291 }
292
293 AssetPopupInsertMixer::AssetPopupInsertMixer(MWindow *mwindow, AssetPopup *popup)
294  : BC_MenuItem(_("Insert Mixers"))
295 {
296         this->mwindow = mwindow;
297         this->popup = popup;
298 }
299
300 AssetPopupInsertMixer::~AssetPopupInsertMixer()
301 {
302 }
303
304 int AssetPopupInsertMixer::handle_event()
305 {
306         mwindow->gui->lock_window("AssetPopupInsertMixer::handle_event");
307         mwindow->create_mixers(-1);
308         mwindow->gui->unlock_window();
309         return 1;
310 }
311
312 AssetPopupPaste::AssetPopupPaste(MWindow *mwindow, AssetPopup *popup)
313  : BC_MenuItem(_("Paste"))
314 {
315         this->mwindow = mwindow;
316         this->popup = popup;
317 }
318
319 AssetPopupPaste::~AssetPopupPaste()
320 {
321 }
322
323 int AssetPopupPaste::handle_event()
324 {
325         popup->paste_assets();
326         return 1;
327 }
328
329
330 AssetMatchSize::AssetMatchSize(MWindow *mwindow, AssetPopup *popup)
331  : BC_MenuItem(_("Match project size"))
332 {
333         this->mwindow = mwindow;
334         this->popup = popup;
335 }
336
337 int AssetMatchSize::handle_event()
338 {
339         popup->match_size();
340         return 1;
341 }
342
343 AssetMatchRate::AssetMatchRate(MWindow *mwindow, AssetPopup *popup)
344  : BC_MenuItem(_("Match frame rate"))
345 {
346         this->mwindow = mwindow;
347         this->popup = popup;
348 }
349
350 int AssetMatchRate::handle_event()
351 {
352         popup->match_rate();
353         return 1;
354 }
355
356 AssetMatchAll::AssetMatchAll(MWindow *mwindow, AssetPopup *popup)
357  : BC_MenuItem(_("Match all"))
358 {
359         this->mwindow = mwindow;
360         this->popup = popup;
361 }
362
363 int AssetMatchAll::handle_event()
364 {
365         popup->match_all();
366         return 1;
367 }
368
369
370 AssetPopupProjectRemove::AssetPopupProjectRemove(MWindow *mwindow, AssetPopup *popup)
371  : BC_MenuItem(_("Remove from project"))
372 {
373         this->mwindow = mwindow;
374         this->popup = popup;
375 }
376
377 AssetPopupProjectRemove::~AssetPopupProjectRemove()
378 {
379 }
380
381 int AssetPopupProjectRemove::handle_event()
382 {
383         popup->gui->unlock_window();
384         mwindow->remove_assets_from_project(1, 1, 1,
385                 mwindow->session->drag_assets, 0);
386         popup->gui->lock_window("AssetPopupProjectRemove::handle_event");
387         return 1;
388 }
389
390
391 AssetPopupDiskRemove::AssetPopupDiskRemove(MWindow *mwindow, AssetPopup *popup)
392  : BC_MenuItem(_("Remove from disk"))
393 {
394         this->mwindow = mwindow;
395         this->popup = popup;
396 }
397
398
399 AssetPopupDiskRemove::~AssetPopupDiskRemove()
400 {
401 }
402
403 int AssetPopupDiskRemove::handle_event()
404 {
405         mwindow->awindow->asset_remove->start();
406         return 1;
407 }
408
409
410 AssetListMenu::AssetListMenu(MWindow *mwindow, AWindowGUI *gui)
411  : BC_PopupMenu(0, 0, 0, "", 0)
412 {
413         this->mwindow = mwindow;
414         this->gui = gui;
415 }
416
417 AssetListMenu::~AssetListMenu()
418 {
419         if( !shots_displayed ) {
420                 delete asset_snapshot;
421                 delete asset_grabshot;
422         }
423 }
424
425 void AssetListMenu::create_objects()
426 {
427         add_item(load_file = new AssetPopupLoadFile(mwindow, gui));
428         add_item(format = new AWindowListFormat(mwindow, gui));
429         add_item(select_used = new AssetSelectUsed(mwindow, gui));
430         BC_SubMenu *submenu;
431         select_used->add_submenu(submenu = new BC_SubMenu());
432         submenu->add_submenuitem(new AssetSelectUsedItem(select_used, _("All"), SELECT_ALL));
433         submenu->add_submenuitem(new AssetSelectUsedItem(select_used, _("Used"), SELECT_USED));
434         submenu->add_submenuitem(new AssetSelectUsedItem(select_used, _("Unused"), SELECT_UNUSED));
435         submenu->add_submenuitem(new AssetSelectUsedItem(select_used, _("None"), SELECT_NONE));
436         add_item(new AWindowListSort(mwindow, gui));
437         add_item(new AssetListCopy(mwindow, gui));
438         add_item(new AssetListPaste(mwindow, gui));
439         SnapshotSubMenu *snapshot_submenu;
440         add_item(asset_snapshot = new AssetSnapshot(mwindow, this));
441         asset_snapshot->add_submenu(snapshot_submenu = new SnapshotSubMenu(asset_snapshot));
442         snapshot_submenu->add_submenuitem(new SnapshotMenuItem(snapshot_submenu, _("png"),  SNAPSHOT_PNG));
443         snapshot_submenu->add_submenuitem(new SnapshotMenuItem(snapshot_submenu, _("jpeg"), SNAPSHOT_JPEG));
444         snapshot_submenu->add_submenuitem(new SnapshotMenuItem(snapshot_submenu, _("tiff"), SNAPSHOT_TIFF));
445         snapshot_submenu->add_submenuitem(new SnapshotMenuItem(snapshot_submenu, _("ppm"),  SNAPSHOT_PPM));
446         GrabshotSubMenu *grabshot_submenu;
447         add_item(asset_grabshot = new AssetGrabshot(mwindow, this));
448         asset_grabshot->add_submenu(grabshot_submenu = new GrabshotSubMenu(asset_grabshot));
449         grabshot_submenu->add_submenuitem(new GrabshotMenuItem(grabshot_submenu, _("png"),  GRABSHOT_PNG));
450         grabshot_submenu->add_submenuitem(new GrabshotMenuItem(grabshot_submenu, _("jpeg"), GRABSHOT_JPEG));
451         grabshot_submenu->add_submenuitem(new GrabshotMenuItem(grabshot_submenu, _("tiff"), GRABSHOT_TIFF));
452         grabshot_submenu->add_submenuitem(new GrabshotMenuItem(grabshot_submenu, _("ppm"),  GRABSHOT_PPM));
453         update_titles(shots_displayed = 1);
454 }
455
456 AssetPopupLoadFile::AssetPopupLoadFile(MWindow *mwindow, AWindowGUI *gui)
457  : BC_MenuItem(_("Load files..."), "o", 'o')
458 {
459         this->mwindow = mwindow;
460         this->gui = gui;
461 }
462
463 AssetPopupLoadFile::~AssetPopupLoadFile()
464 {
465 }
466
467 int AssetPopupLoadFile::handle_event()
468 {
469         mwindow->gui->mainmenu->load_file->thread->start();
470         return 1;
471 }
472
473 void AssetListMenu::update_titles(int shots)
474 {
475         format->update();
476         if( shots && !shots_displayed ) {
477                 shots_displayed = 1;
478                 add_item(asset_snapshot);
479                 add_item(asset_grabshot);
480         }
481         else if( !shots && shots_displayed ) {
482                 shots_displayed = 0;
483                 remove_item(asset_snapshot);
484                 remove_item(asset_grabshot);
485         }
486 }
487
488 AssetListCopy::AssetListCopy(MWindow *mwindow, AWindowGUI *gui)
489  : BC_MenuItem(_("Copy file list"))
490 {
491         this->mwindow = mwindow;
492         this->gui = gui;
493         copy_dialog = 0;
494 }
495 AssetListCopy::~AssetListCopy()
496 {
497         delete copy_dialog;
498 }
499
500 int AssetListCopy::handle_event()
501 {
502         int len = 0;
503         MWindowGUI *gui = mwindow->gui;
504         gui->lock_window("AssetListCopy::handle_event");
505         mwindow->awindow->gui->collect_assets();
506         int n = mwindow->session->drag_assets->total;
507         for( int i=0; i<n; ++i ) {
508                 Indexable *indexable = mwindow->session->drag_assets->values[i];
509                 const char *path = indexable->path;
510                 if( !*path ) continue;
511                 len += strlen(path) + 1;
512         }
513         char *text = new char[len+1], *cp = text;
514         for( int i=0; i<n; ++i ) {
515                 Indexable *indexable = mwindow->session->drag_assets->values[i];
516                 const char *path = indexable->path;
517                 if( !*path ) continue;
518                 cp += sprintf(cp, "%s\n", path);
519         }
520         *cp = 0;
521         int cur_x, cur_y;
522         gui->get_abs_cursor(cur_x, cur_y, 0);
523         gui->unlock_window(); 
524
525         if( n ) {
526                 if( !copy_dialog )
527                         copy_dialog = new AssetCopyDialog(this);
528                 copy_dialog->start(text, cur_x, cur_y);
529         }
530         else {
531                 eprintf(_("Nothing selected"));
532                 delete [] text;
533         }
534         return 1;
535 }
536
537 AssetCopyDialog::AssetCopyDialog(AssetListCopy *copy)
538  : BC_DialogThread()
539 {
540         this->copy = copy;
541         copy_window = 0;
542 }
543
544 void AssetCopyDialog::start(char *text, int x, int y)
545 {
546         close_window();
547         this->text = text;
548         this->x = x;  this->y = y;
549         BC_DialogThread::start();
550 }
551
552 AssetCopyDialog::~AssetCopyDialog()
553 {
554         close_window();
555 }
556
557 BC_Window* AssetCopyDialog::new_gui()
558 {
559         BC_DisplayInfo display_info;
560
561         copy_window = new AssetCopyWindow(this);
562         copy_window->create_objects();
563         return copy_window;
564 }
565
566 void AssetCopyDialog::handle_done_event(int result)
567 {
568         delete [] text;  text = 0;
569 }
570
571 void AssetCopyDialog::handle_close_event(int result)
572 {
573         copy_window = 0;
574 }
575
576 #define ACW_W xS(500)
577 #define ACW_H yS(200)
578
579 AssetCopyWindow::AssetCopyWindow(AssetCopyDialog *copy_dialog)
580  : BC_Window(_(PROGRAM_NAME ": Copy File List"),
581         copy_dialog->x - ACW_W/2, copy_dialog->y - ACW_H/2,
582         ACW_W, ACW_H, ACW_W, ACW_H, 1, 0, 1)
583 {
584         this->copy_dialog = copy_dialog;
585 }
586
587 AssetCopyWindow::~AssetCopyWindow()
588 {
589 }
590
591 void AssetCopyWindow::create_objects()
592 {
593         lock_window("AssetCopyWindow::create_objects");
594         BC_Title *title;
595         int xs10 = xS(10);
596         int ys5 = yS(5), ys10 = yS(10);
597         int x = xs10, y = ys10;
598         add_subwindow(title = new BC_Title(x, y, _("List of asset paths:")));
599         y += title->get_h() + ys5;
600         int text_w = get_w() - x - 10;
601         int text_h = get_h() - y - BC_OKButton::calculate_h() - ys5;
602         int text_rows = BC_TextBox::pixels_to_rows(this, MEDIUMFONT, text_h);
603         char *text = copy_dialog->text;
604         int len = strlen(text) + BCTEXTLEN;
605         file_list = new BC_ScrollTextBox(this, x, y, text_w, text_rows, text, len);
606         file_list->create_objects();
607
608         add_subwindow(new BC_OKButton(this));
609         show_window();
610         unlock_window();
611 }
612
613 int AssetCopyWindow::resize_event(int w, int h)
614 {
615         int fx = file_list->get_x(), fy = file_list->get_y();
616         int text_w = w - fx - xS(10);
617         int text_h = h - fy - BC_OKButton::calculate_h() - yS(5);
618         int text_rows = BC_TextBox::pixels_to_rows(this, MEDIUMFONT, text_h);
619         file_list->reposition_window(fx, fy, text_w, text_rows);
620         return 0;
621 }
622
623 AssetListPaste::AssetListPaste(MWindow *mwindow, AWindowGUI *gui)
624  : BC_MenuItem(_("Paste file list"))
625 {
626         this->mwindow = mwindow;
627         this->gui = gui;
628         paste_dialog = 0;
629 }
630 AssetListPaste::~AssetListPaste()
631 {
632         delete paste_dialog;
633 }
634
635 int AssetListPaste::handle_event()
636 {
637         if( !paste_dialog )
638                 paste_dialog = new AssetPasteDialog(this);
639         else
640                 paste_dialog->close_window();
641         int cur_x, cur_y;
642         gui->get_abs_cursor(cur_x, cur_y, 0);
643         paste_dialog->start(cur_x, cur_y);
644         return 1;
645 }
646
647 AssetPasteDialog::AssetPasteDialog(AssetListPaste *paste)
648  : BC_DialogThread()
649 {
650         this->paste = paste;
651         paste_window = 0;
652 }
653
654 AssetPasteDialog::~AssetPasteDialog()
655 {
656         close_window();
657 }
658
659 BC_Window* AssetPasteDialog::new_gui()
660 {
661         paste_window = new AssetPasteWindow(this);
662         paste_window->create_objects();
663         return paste_window;
664 }
665
666 void AssetPasteDialog::handle_done_event(int result)
667 {
668         if( result ) return;
669         const char *bp = paste_window->file_list->get_text(), *ep = bp+strlen(bp);
670         ArrayList<char*> path_list;
671         path_list.set_array_delete();
672
673         for( const char *cp=bp; cp<ep && *cp; ) {
674                 const char *dp = strchr(cp, '\n');
675                 if( !dp ) dp = ep;
676                 char path[BCTEXTLEN], *pp = path;
677                 int len = sizeof(path)-1;
678                 while( --len>0 && cp<dp ) *pp++ = *cp++;
679                 if( *cp ) ++cp;
680                 *pp = 0;
681                 if( !strlen(path) ) continue;
682                 path_list.append(cstrdup(path));
683         }
684         if( !path_list.size() ) return;
685
686         MWindow *mwindow = paste->mwindow;
687         mwindow->interrupt_indexes();
688         mwindow->gui->lock_window("AssetPasteDialog::handle_done_event");
689         result = mwindow->load_filenames(&path_list, LOADMODE_RESOURCESONLY, 0);
690         mwindow->gui->unlock_window();
691         path_list.remove_all_objects();
692         mwindow->save_backup();
693         mwindow->restart_brender();
694         mwindow->session->changes_made = 1;
695 }
696
697 void AssetPasteDialog::handle_close_event(int result)
698 {
699         paste_window = 0;
700 }
701
702 void AssetPasteDialog::start(int x, int y)
703 {
704         this->x = x;  this->y = y;
705         BC_DialogThread::start();
706 }
707
708 #define APW_W xS(500)
709 #define APW_H yS(200)
710
711 AssetPasteWindow::AssetPasteWindow(AssetPasteDialog *paste_dialog)
712  : BC_Window(_(PROGRAM_NAME ": Paste File List"),
713         paste_dialog->x - APW_W/2, paste_dialog->y - APW_H/2,
714         APW_W, APW_H, APW_W, APW_H, 1, 0, 1)
715 {
716         this->paste_dialog = paste_dialog;
717 }
718
719 AssetPasteWindow::~AssetPasteWindow()
720 {
721 }
722
723 void AssetPasteWindow::create_objects()
724 {
725         lock_window("AssetPasteWindow::create_objects()");
726         BC_Title *title;
727         int xs10 = xS(10);
728         int ys5 = yS(5), ys10 = yS(10);
729         int x = xs10, y = ys10;
730         add_subwindow(title = new BC_Title(x, y, _("Enter list of asset paths:")));
731         y += title->get_h() + ys5;
732         int text_w = get_w() - x - xs10;
733         int text_h = get_h() - y - BC_OKButton::calculate_h() - ys5;
734         int text_rows = BC_TextBox::pixels_to_rows(this, MEDIUMFONT, text_h);
735         file_list = new BC_ScrollTextBox(this, x, y, text_w, text_rows, (char*)0, 65536);
736         file_list->create_objects();
737         add_subwindow(new BC_OKButton(this));
738         add_subwindow(new BC_CancelButton(this));
739         show_window();
740         unlock_window();
741 }
742
743 int AssetPasteWindow::resize_event(int w, int h)
744 {
745         int fx = file_list->get_x(), fy = file_list->get_y();
746         int text_w = w - fx - xS(10);
747         int text_h = h - fy - BC_OKButton::calculate_h() - yS(5);
748         int text_rows = BC_TextBox::pixels_to_rows(this, MEDIUMFONT, text_h);
749         file_list->reposition_window(fx, fy, text_w, text_rows);
750         return 0;
751 }
752
753
754
755 AssetSnapshot::AssetSnapshot(MWindow *mwindow, AssetListMenu *asset_list_menu)
756  : BC_MenuItem(_("Snapshot..."))
757 {
758         this->mwindow = mwindow;
759         this->asset_list_menu = asset_list_menu;
760 }
761
762 AssetSnapshot::~AssetSnapshot()
763 {
764 }
765
766 SnapshotSubMenu::SnapshotSubMenu(AssetSnapshot *asset_snapshot)
767 {
768         this->asset_snapshot = asset_snapshot;
769 }
770
771 SnapshotSubMenu::~SnapshotSubMenu()
772 {
773 }
774
775 SnapshotMenuItem::SnapshotMenuItem(SnapshotSubMenu *submenu, const char *text, int mode)
776  : BC_MenuItem(text)
777 {
778         this->submenu = submenu;
779         this->mode = mode;
780 }
781
782 SnapshotMenuItem::~SnapshotMenuItem()
783 {
784 }
785
786 int SnapshotMenuItem::handle_event()
787 {
788         MWindow *mwindow = submenu->asset_snapshot->mwindow;
789         EDL *edl = mwindow->edl;
790         if( !edl->have_video() ) return 1;
791
792         Preferences *preferences = mwindow->preferences;
793         char filename[BCTEXTLEN];
794         static const char *exts[] = { "png", "jpg", "tif", "ppm" };
795         time_t tt;     time(&tt);
796         struct tm tm;  localtime_r(&tt,&tm);
797         snprintf(filename,sizeof(filename),"%s/%s_%04d%02d%02d-%02d%02d%02d.%s",
798                 preferences->snapshot_path, _("snap"),
799                 1900+tm.tm_year,1+tm.tm_mon,tm.tm_mday,
800                 tm.tm_hour,tm.tm_min,tm.tm_sec, exts[mode]);
801         char *asset_path = FileSystem::basepath(filename);
802         Asset *asset = new Asset(asset_path);
803         delete [] asset_path;
804
805         int fw = edl->get_w(), fh = edl->get_h();
806         int fcolor_model = edl->session->color_model;
807
808         switch( mode ) {
809         case SNAPSHOT_PNG:
810                 asset->format = FILE_PNG;
811                 asset->png_use_alpha = 1;
812                 break;
813         case SNAPSHOT_JPEG:
814                 asset->format = FILE_JPEG;
815                 asset->jpeg_quality = 90;
816                 break;
817         case SNAPSHOT_TIFF:
818                 asset->format = FILE_TIFF;
819                 asset->tiff_cmodel = 0;
820                 asset->tiff_compression = 0;
821                 break;
822         case SNAPSHOT_PPM:
823                 asset->format = FILE_PPM;
824                 break;
825         }
826         asset->width = fw;
827         asset->height = fh;
828         asset->audio_data = 0;
829         asset->video_data = 1;
830         asset->video_length = 1;
831         asset->layers = 1;
832
833         File file;
834         int processors = preferences->project_smp + 1;
835         if( processors > 8 ) processors = 8;
836         file.set_processors(processors);
837         int ret = file.open_file(preferences, asset, 0, 1);
838         if( !ret ) {
839                 file.start_video_thread(1, fcolor_model,
840                         processors > 1 ? 2 : 1, 0);
841                 VFrame ***frames = file.get_video_buffer();
842                 VFrame *frame = frames[0][0];
843                 TransportCommand command;
844                 //command.command = audio_tracks ? NORMAL_FWD : CURRENT_FRAME;
845                 command.command = CURRENT_FRAME;
846                 command.get_edl()->copy_all(edl);
847                 command.change_type = CHANGE_ALL;
848                 command.realtime = 0;
849
850                 RenderEngine render_engine(0, preferences, 0, 0);
851                 CICache video_cache(preferences);
852                 render_engine.set_vcache(&video_cache);
853                 render_engine.arm_command(&command);
854
855                 double position = edl->local_session->get_selectionstart(1);
856                 int64_t source_position = (int64_t)(position * edl->get_frame_rate());
857                 ret = !render_engine.vrender ? 1 :
858                         render_engine.vrender->process_buffer(frame, source_position, 0);
859                 if( !ret )
860                         ret = file.write_video_buffer(1);
861                 file.close_file();
862         }
863         if( !ret ) {
864                 asset->folder_no = AW_MEDIA_FOLDER;
865                 mwindow->edl->assets->append(asset);
866                 mwindow->awindow->gui->async_update_assets();
867         }
868         else {
869                 eprintf(_("snapshot render failed"));
870                 asset->remove_user();
871         }
872         return 1;
873 }
874
875
876 AssetGrabshot::AssetGrabshot(MWindow *mwindow, AssetListMenu *asset_list_menu)
877  : BC_MenuItem(_("Grabshot..."))
878 {
879         this->mwindow = mwindow;
880         this->asset_list_menu = asset_list_menu;
881 }
882
883 AssetGrabshot::~AssetGrabshot()
884 {
885 }
886
887 GrabshotSubMenu::GrabshotSubMenu(AssetGrabshot *asset_grabshot)
888 {
889         this->asset_grabshot = asset_grabshot;
890 }
891
892 GrabshotSubMenu::~GrabshotSubMenu()
893 {
894 }
895
896 GrabshotMenuItem::GrabshotMenuItem(GrabshotSubMenu *submenu, const char *text, int mode)
897  : BC_MenuItem(text)
898 {
899         this->submenu = submenu;
900         this->mode = mode;
901         grab_thread = 0;
902 }
903
904 GrabshotMenuItem::~GrabshotMenuItem()
905 {
906         delete grab_thread;
907 }
908
909 int GrabshotMenuItem::handle_event()
910 {
911         if( !grab_thread )
912                 grab_thread = new GrabshotThread(submenu->asset_grabshot->mwindow);
913         if( !grab_thread->running() )
914                 grab_thread->start(this);
915         return 1;
916 }
917
918 GrabshotThread::GrabshotThread(MWindow *mwindow)
919  : Thread(1, 0, 0)
920 {
921         this->mwindow = mwindow;
922         popup = 0;
923         done = -1;
924 }
925 GrabshotThread::~GrabshotThread()
926 {
927         delete popup;
928 }
929
930 void GrabshotThread::start(GrabshotMenuItem *menu_item)
931 {
932         popup = new GrabshotPopup(this, menu_item->mode);
933         popup->lock_window("GrabshotThread::start");
934         for( int i=0; i<4; ++i )
935                 edge[i] = new BC_Popup(mwindow->gui, 0,0, 1,1, ORANGE, 1);
936         mwindow->gui->grab_buttons();
937         mwindow->gui->grab_cursor();
938         popup->grab(mwindow->gui);
939         popup->create_objects();
940         popup->show_window();
941         popup->unlock_window();
942         done = 0;
943         Thread::start();
944 }
945
946 void GrabshotThread::run()
947 {
948         popup->lock_window("GrabshotThread::run 0");
949         while( !done ) {
950                 popup->update();
951                 popup->unlock_window();
952                 enable_cancel();
953                 Timer::delay(200);
954                 disable_cancel();
955                 popup->lock_window("GrabshotThread::run 1");
956         }
957         mwindow->gui->ungrab_cursor();
958         mwindow->gui->ungrab_buttons();
959         popup->ungrab(mwindow->gui);
960         for( int i=0; i<4; ++i ) delete edge[i];
961         popup->unlock_window();
962         delete popup;  popup = 0;
963 }
964
965 GrabshotPopup::GrabshotPopup(GrabshotThread *grab_thread, int mode)
966  : BC_Popup(grab_thread->mwindow->gui, 0,0, 16,16, -1,1)
967 {
968         this->grab_thread = grab_thread;
969         this->mode = mode;
970         dragging = -1;
971         grab_color = ORANGE;
972         x0 = y0 = x1 = y1 = -1;
973         lx0 = ly0 = lx1 = ly1 = -1;
974 }
975 GrabshotPopup::~GrabshotPopup()
976 {
977 }
978
979 int GrabshotPopup::grab_event(XEvent *event)
980 {
981         int cur_drag = dragging;
982         switch( event->type ) {
983         case ButtonPress:
984                 if( cur_drag > 0 ) return 1;
985                 x0 = event->xbutton.x_root;
986                 y0 = event->xbutton.y_root;
987                 if( !cur_drag ) {
988                         draw_selection(-1);
989                         if( event->xbutton.button == RIGHT_BUTTON ) break;
990                         if( x0>=get_x() && x0<get_x()+get_w() &&
991                             y0>=get_y() && y0<get_y()+get_h() ) break;
992                 }
993                 x1 = x0;  y1 = y0;
994                 draw_selection(1);
995                 dragging = 1;
996                 return 1;
997         case ButtonRelease:
998                 dragging = 0;
999         case MotionNotify:
1000                 if( cur_drag > 0 ) {
1001                         x1 = event->xbutton.x_root;
1002                         y1 = event->xbutton.y_root;
1003                         draw_selection(0);
1004                 }
1005                 return 1;
1006         default:
1007                 return 0;
1008         }
1009
1010         int cx = lx0,     cy = ly0;
1011         int cw = lx1-lx0, ch = ly1-ly0;
1012         hide_window();
1013         sync_display();
1014         grab_thread->done = 1;
1015
1016         MWindow *mwindow = grab_thread->mwindow;
1017         Preferences *preferences = mwindow->preferences;
1018         char filename[BCTEXTLEN];
1019         static const char *exts[] = { "png", "jpg", "tif", "ppm" };
1020         time_t tt;     time(&tt);
1021         struct tm tm;  localtime_r(&tt,&tm);
1022         snprintf(filename,sizeof(filename),"%s/%s_%04d%02d%02d-%02d%02d%02d.%s",
1023                 preferences->snapshot_path, _("grab"),
1024                 1900+tm.tm_year,1+tm.tm_mon,tm.tm_mday,
1025                 tm.tm_hour,tm.tm_min,tm.tm_sec, exts[mode]);
1026         char *asset_path = FileSystem::basepath(filename);
1027         Asset *asset = new Asset(asset_path);
1028         delete [] asset_path;
1029         switch( mode ) {
1030         case GRABSHOT_PNG:
1031                 asset->format = FILE_PNG;
1032                 asset->png_use_alpha = 1;
1033                 break;
1034         case GRABSHOT_JPEG:
1035                 asset->format = FILE_JPEG;
1036                 asset->jpeg_quality = 90;
1037                 break;
1038         case GRABSHOT_TIFF:
1039                 asset->format = FILE_TIFF;
1040                 asset->tiff_cmodel = 0;
1041                 asset->tiff_compression = 0;
1042                 break;
1043         case GRABSHOT_PPM:
1044                 asset->format = FILE_PPM;
1045                 break;
1046         }
1047
1048 // no odd dimensions
1049         int rw = get_root_w(0), rh = get_root_h(0);
1050         if( cx < 0 ) { cw += cx;  cx = 0; }
1051         if( cy < 0 ) { ch += cy;  cy = 0; }
1052         if( cx+cw > rw ) cw = rw-cx;
1053         if( cy+ch > rh ) ch = rh-cy;
1054         if( !cw || !ch ) return 1;
1055
1056         VFrame vframe(cw,ch, BC_RGB888);
1057         if( cx+cw < rw ) ++cw;
1058         if( cy+ch < rh ) ++ch;
1059         BC_Capture capture_bitmap(cw,ch, 0);
1060         capture_bitmap.capture_frame(&vframe, cx,cy);
1061
1062         asset->width = vframe.get_w();
1063         asset->height = vframe.get_h();
1064         asset->audio_data = 0;
1065         asset->video_data = 1;
1066         asset->video_length = 1;
1067         asset->layers = 1;
1068
1069         File file;
1070         int fcolor_model = mwindow->edl->session->color_model;
1071         int processors = preferences->project_smp + 1;
1072         if( processors > 8 ) processors = 8;
1073         file.set_processors(processors);
1074         int ret = file.open_file(preferences, asset, 0, 1);
1075         if( !ret ) {
1076                 file.start_video_thread(1, fcolor_model,
1077                         processors > 1 ? 2 : 1, 0);
1078                 VFrame ***frames = file.get_video_buffer();
1079                 VFrame *frame = frames[0][0];
1080                 frame->transfer_from(&vframe);
1081                 ret = file.write_video_buffer(1);
1082                 file.close_file();
1083         }
1084         if( !ret ) {
1085                 asset->folder_no = AW_MEDIA_FOLDER;
1086                 mwindow->edl->assets->append(asset);
1087                 mwindow->awindow->gui->async_update_assets();
1088         }
1089         else {
1090                 eprintf(_("grabshot render failed"));
1091                 asset->remove_user();
1092         }
1093
1094         return 1;
1095 }
1096
1097 void GrabshotPopup::update()
1098 {
1099         set_color(grab_color ^= GREEN);
1100         draw_box(0,0, get_w(),get_h());
1101         flash(1);
1102 }
1103
1104 void GrabshotPopup::draw_selection(int show)
1105 {
1106         if( show < 0 ) {
1107                 for( int i=0; i<4; ++i ) hide_window(0);
1108                 flush();
1109                 return;
1110         }
1111
1112         int nx0 = x0 < x1 ? x0 : x1;
1113         int nx1 = x0 < x1 ? x1 : x0;
1114         int ny0 = y0 < y1 ? y0 : y1;
1115         int ny1 = y0 < y1 ? y1 : y0;
1116         lx0 = nx0;  lx1 = nx1;  ly0 = ny0;  ly1 = ny1;
1117
1118         --nx0;  --ny0;
1119         BC_Popup **edge = grab_thread->edge;
1120         edge[0]->reposition_window(nx0,ny0, nx1-nx0, 1);
1121         edge[1]->reposition_window(nx1,ny0, 1, ny1-ny0);
1122         edge[2]->reposition_window(nx0,ny1, nx1-nx0, 1);
1123         edge[3]->reposition_window(nx0,ny0, 1, ny1-ny0);
1124
1125         if( show > 0 ) {
1126                 for( int i=0; i<4; ++i ) edge[i]->show_window(0);
1127         }
1128         flush();
1129 }
1130