4 * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
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.
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.
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
24 #include "assetedit.h"
25 #include "assetpopup.h"
26 #include "assetremove.h"
28 #include "audiodevice.h"
30 #include "awindowgui.h"
31 #include "bccmodels.h"
33 #include "bcsignals.h"
35 #include "binfolder.h"
40 #include "clippopup.h"
42 #include "cwindowgui.h"
47 #include "edlsession.h"
48 #include "effectlist.h"
50 #include "filesystem.h"
51 #include "folderlistmenu.h"
52 #include "indexable.h"
56 #include "labelpopup.h"
57 #include "localsession.h"
58 #include "mainerror.h"
60 #include "mainsession.h"
61 #include "mwindowgui.h"
63 #include "preferences.h"
65 #include "proxypopup.h"
66 #include "renderengine.h"
71 #include "transportque.h"
75 #include "vwindowgui.h"
78 #include "data/lad_picon_png.h"
79 #include "data/ff_audio_png.h"
80 #include "data/ff_video_png.h"
87 const char *AWindowGUI::folder_names[] =
91 N_("Audio Transitions"),
92 N_("Video Transitions"),
99 const char *AVIconDrawing::avicon_names[] =
107 AssetVIcon::AssetVIcon(AssetPicon *picon, int w, int h, double framerate, int64_t length)
108 : VIcon(w, h, framerate), Garbage("AssetVIcon")
111 this->length = length;
116 AssetVIcon::~AssetVIcon()
118 if( picon->gui->vicon_thread->solo == this )
119 picon->gui->vicon_thread->solo = 0;
120 picon->gui->vicon_thread->del_vicon(this);
124 VFrame *AssetVIcon::frame()
126 if( broken ) return 0;
127 AssetVIconThread *avt = picon->gui->vicon_thread;
128 Indexable *idxbl = picon->indexable;
129 Asset *asset = idxbl && idxbl->is_asset ? (Asset *)idxbl : 0;
130 if( !asset ) return vframes()>0 ? (VFrame*)*images[0] : 0;
131 if( !asset->video_data && audio_data && audio_size && length > 0 ) {
132 if( !temp ) temp = new VFrame(0, -1, w, h, BC_RGB888, -1);
134 int sample_rate = asset->get_sample_rate();
135 int64_t audio_samples = asset->get_audio_samples();
136 double duration = (double)audio_samples / sample_rate;
137 picon->draw_hue_bar(temp, duration);
138 int secs = length / frame_rate + 0.5;
139 if( !secs ) secs = 1;
140 int bfrsz = VICON_SAMPLE_RATE;
141 int samples = audio_size/sizeof(vicon_audio_t);
142 double line_pos = (double)seq_no/(length-1);
143 int audio_pos = samples * line_pos * (secs-1)/secs;
144 vicon_audio_t *audio_data = ((vicon_audio_t *)this->audio_data) + audio_pos;
145 static const int mx = (1<<(8*sizeof(*audio_data)-1)) - 1;
146 double data[bfrsz], sample_scale = 1./mx;
147 int len = samples - audio_pos;
148 if( len > bfrsz ) len = bfrsz;
150 while( i < len ) data[i++] = *audio_data++ * sample_scale;
151 while( i < bfrsz ) data[i++] = 0;
152 picon->draw_wave(temp, data, bfrsz, RED, GREEN);
153 int x = (w-1) * line_pos;
154 temp->pixel_rgb = RED;
155 temp->draw_line(x,0, x,h);
158 int vw = avt->vw, vh = avt->vh, vicon_cmodel = avt->vicon_cmodel;
159 if( !asset->video_data ) {
161 temp = new VFrame(0, -1, vw, vh, BC_RGB888, -1);
166 if( seq_no >= images.size() ) {
167 MWindow *mwindow = picon->mwindow;
168 if( temp && (temp->get_w() != asset->width || temp->get_h() != asset->height) ) {
169 delete temp; temp = 0;
172 temp = new VFrame(0, -1, asset->width, asset->height, BC_RGB888, -1);
173 File *file = mwindow->video_cache->check_out(asset, mwindow->edl, 1);
174 if( !file ) { broken = 1; return 0; }
176 while( file && seq_no >= images.size() && !avt->interrupted ) {
177 int64_t pos = images.size() / picon->gui->vicon_thread->refresh_rate * frame_rate;
178 file->set_video_position(pos,0);
180 if( file->read_frame(temp) ) temp->clear_frame();
181 add_image(temp, vw, vh, vicon_cmodel);
182 mwindow->video_cache->check_in(asset);
183 if( timer.get_difference() > 500 ) return 0;
185 file = mwindow->video_cache->check_out(asset, mwindow->edl, 0);
186 for( int retries=10; !file && --retries>=0; usleep(1000) ) {
187 if( avt->interrupted ) return 0;
188 file = mwindow->video_cache->check_out(asset, mwindow->edl, 0);
190 if( !file ) return 0;
192 mwindow->video_cache->check_in(asset);
194 if( seq_no >= images.size() ) return 0;
195 return *images[seq_no];
198 int64_t AssetVIcon::set_seq_no(int64_t no)
200 if( no >= length ) no = 0;
204 int AssetVIcon::get_vx()
206 BC_ListBox *lbox = picon->gui->asset_list;
207 return lbox->get_icon_x(picon);
209 int AssetVIcon::get_vy()
211 BC_ListBox *lbox = picon->gui->asset_list;
212 return lbox->get_icon_y(picon);
215 void AssetVIcon::load_audio()
217 MWindow *mwindow = picon->mwindow;
218 Asset *asset = (Asset *)picon->indexable;
219 File *file = mwindow->audio_cache->check_out(asset, mwindow->edl, 1);
220 int channels = asset->get_audio_channels();
221 if( channels > 2 ) channels = 2;
222 int sample_rate = asset->get_sample_rate();
223 int bfrsz = sample_rate;
224 Samples samples(bfrsz);
225 double time_scale = (double)sample_rate / VICON_SAMPLE_RATE;
226 vicon_audio_t *audio_data = (vicon_audio_t *)this->audio_data;
227 static const int mx = (1<<(8*sizeof(*audio_data)-1)) - 1;
228 double sample_scale = (double)mx / channels;
229 int audio_pos = 0, audio_len = audio_size/sizeof(vicon_audio_t);
230 while( audio_pos < audio_len ) {
231 int64_t pos = audio_pos * time_scale;
232 for( int ch=0; ch<channels; ++ch ) {
233 file->set_channel(ch);
234 file->set_audio_position(pos);
235 file->read_samples(&samples, bfrsz);
236 double *data = samples.get_data();
237 for( int64_t k=audio_pos; k<audio_len; ++k ) {
238 int i = k * time_scale - pos;
239 if( i >= bfrsz ) break;
240 int v = audio_data[k] + data[i] * sample_scale;
241 audio_data[k] = CLIP(v, -mx,mx);
244 audio_pos = (pos + bfrsz) / time_scale;
246 mwindow->audio_cache->check_in(asset);
250 AssetVIconAudio::AssetVIconAudio(AWindowGUI *gui)
254 audio = new AudioDevice(gui->mwindow);
258 AssetVIconAudio::~AssetVIconAudio()
263 void AssetVIconAudio::run()
266 int64_t bfrsz = VICON_SAMPLE_RATE;
267 MWindow *mwindow = gui->mwindow;
268 EDL *edl = mwindow->edl;
269 EDLSession *session = edl->session;
270 AudioOutConfig *aconfig = session->playback_config->aconfig;
271 audio->open_output(aconfig, VICON_SAMPLE_RATE, bfrsz, channels, 0);
272 audio->start_playback();
273 double out0[bfrsz], out1[bfrsz], *out[2] = { out0, out1 };
274 vicon_audio_t *audio_data = (vicon_audio_t *)vicon->audio_data;
275 static const int mx = (1<<(8*sizeof(*audio_data)-1)) - 1;
277 int audio_len = vicon->audio_size/sizeof(vicon_audio_t);
278 while( !interrupted ) {
279 int len = audio_len - audio_pos;
280 if( len <= 0 ) break;
281 if( len > bfrsz ) len = bfrsz;
283 for( int i=0; i<len; ++i,++k )
284 out0[i] = out1[i] = (double)audio_data[k] / mx;
286 audio->write_buffer(out, channels, len);
290 audio->set_last_buffer();
291 audio->stop_audio(interrupted ? 0 : 1);
295 void AssetVIconAudio::start(AssetVIcon *vicon)
297 if( running() ) return;
299 double pos = vicon->length > 0 ? (double)vicon->seq_no/vicon->length : 0;
300 int audio_len = vicon->audio_size/sizeof(vicon_audio_t);
301 audio_pos = pos * audio_len;
306 void AssetVIconAudio::stop(int wait)
308 if( running() && !interrupted ) {
310 audio->stop_audio(wait);
314 vicon->playing_audio = 0;
319 void AssetVIcon::start_audio()
321 if( playing_audio < 0 ) return;
322 picon->gui->vicon_audio->stop(0);
324 picon->gui->vicon_audio->start(this);
327 void AssetVIcon::stop_audio()
329 if( playing_audio > 0 ) {
330 picon->gui->vicon_audio->stop(0);
335 AssetViewPopup::AssetViewPopup(VIconThread *vt, int draw_mode,
336 int x, int y, int w, int h)
337 : ViewPopup(vt, x, y, w, h)
339 this->draw_mode = draw_mode;
340 this->bar_h = (VIEW_POPUP_BAR_H * h) / 200;
344 AssetViewPopup::~AssetViewPopup()
348 int AssetViewPopup::reposition_window(int x, int y, int w, int h)
350 this->bar_h = (VIEW_POPUP_BAR_H * h) / 200;
351 return ViewPopup::reposition_window(x, y, w, h);
354 int AssetViewPopup::button_press_event()
356 if( !is_event_win() ) return 0;
357 AssetVIconThread *avt = (AssetVIconThread *)vt;
358 if( !avt->vicon ) return 0;
361 switch( get_buttonpress() ) {
365 avt->set_view_popup(0);
368 dir = -1; // fall thru
370 switch( draw_mode ) {
371 case ASSET_VIEW_MEDIA:
372 case ASSET_VIEW_MEDIA_MAP:
373 avt->zoom_scale(dir);
380 int x = get_cursor_x(), y = get_cursor_y();
381 AssetVIcon *vicon = (AssetVIcon *)avt->vicon;
382 AssetPicon *picon = vicon->picon;
383 MWindow *mwindow = picon->mwindow;
384 EDL *edl = mwindow->edl;
386 if( y < get_h()/2 ) {
388 picon->indexable ? picon->indexable :
389 picon->edl ? picon->edl : 0;
390 if( !idxbl ) return 0;
391 double sample_rate = idxbl->get_sample_rate();
392 double audio_length = sample_rate > 0 && idxbl->have_audio() ?
393 idxbl->get_audio_samples() / sample_rate : 0;
394 double frame_rate = idxbl->get_frame_rate();
395 double video_length = frame_rate > 0 && idxbl->have_video() ?
396 idxbl->get_video_frames() / frame_rate : 0;
397 double idxbl_length = bmax(audio_length, video_length);
398 double pos = x * idxbl_length / get_w();
399 double start = 0, end = idxbl_length;
400 double lt = DBL_MAX, rt = DBL_MAX;
401 for( Track *track=edl->tracks->first; track!=0; track=track->next ) {
402 for( Edit *edit=track->edits->first; edit!=0; edit=edit->next ) {
403 Indexable *indexable = (Indexable *)edit->asset;
404 if( !indexable ) indexable = (Indexable *)edit->nested_edl;
405 if( !indexable ) continue;
406 if( indexable->id == idxbl->id ||
407 (!indexable->is_asset == !idxbl->is_asset &&
408 !strcmp(indexable->path, idxbl->path)) ) {
409 double start_pos = track->from_units(edit->startsource);
410 double end_pos = track->from_units(edit->startsource + edit->length);
411 double dlt = pos - start_pos, drt = end_pos - pos;
412 if( dlt >= 0 && dlt < lt ) { lt = dlt; start = start_pos; }
413 else if( dlt < 0 && -dlt < rt ) { rt = -dlt; end = start_pos; }
414 if( drt >= 0 && drt < rt ) { rt = drt; end = end_pos; }
415 else if( drt < 0 && -drt < lt ) { lt = -drt; start = end_pos; }
419 mwindow->gui->lock_window("AssetVIcon::popup_button_press");
420 VWindow *vwindow = mwindow->get_viewer(1, 0);
421 vwindow->change_source(idxbl);
422 mwindow->gui->unlock_window();
423 EDL *vedl = vwindow->get_edl();
424 vedl->set_inpoint(start);
425 vedl->set_outpoint(end);
426 vedl->local_session->set_selectionstart(start);
427 vedl->local_session->set_selectionend(start);
428 vwindow->gui->lock_window("AssetViewPopup::button_press_event");
429 vwindow->update_position();
430 vwindow->gui->unlock_window();
435 if( !ctrl_down() && !shift_down() )
436 return cursor_motion_event();
438 picon->indexable ? picon->indexable :
439 picon->edl ? picon->edl : 0;
440 if( !idxbl ) return 0;
441 double total_length = mwindow->edl->tracks->total_length();
442 double pos = x * total_length / get_w();
443 double start = 0, end = total_length;
444 double lt = DBL_MAX, rt = DBL_MAX;
445 for( Track *track=edl->tracks->first; track!=0; track=track->next ) {
446 for( Edit *edit=track->edits->first; edit!=0; edit=edit->next ) {
447 Indexable *indexable = (Indexable *)edit->asset;
448 if( !indexable ) indexable = (Indexable *)edit->nested_edl;
449 if( !indexable ) continue;
450 if( indexable->id == idxbl->id ||
451 (!indexable->is_asset == !idxbl->is_asset &&
452 !strcmp(indexable->path, idxbl->path)) ) {
453 double start_pos = track->from_units(edit->startproject);
454 double end_pos = track->from_units(edit->startproject + edit->length);
455 double dlt = pos - start_pos, drt = end_pos - pos;
456 if( dlt >= 0 && dlt < lt ) { lt = dlt; start = start_pos; }
457 else if( dlt < 0 && -dlt < rt ) { rt = -dlt; end = start_pos; }
458 if( drt >= 0 && drt < rt ) { rt = drt; end = end_pos; }
459 else if( drt < 0 && -drt < lt ) { lt = -drt; start = end_pos; }
463 mwindow->gui->lock_window("AssetVIcon::popup_button_press");
464 mwindow->select_point(start);
465 edl->local_session->set_selectionstart(start);
466 edl->local_session->set_selectionend(!shift_down() ? start : end);
467 mwindow->zoom_sample(edl->local_session->zoom_sample);
468 mwindow->gui->unlock_window();
474 int AssetViewPopup::button_release_event()
476 if( !is_event_win() ) return 0;
481 int AssetViewPopup::cursor_motion_event()
483 AssetVIconThread *avt = (AssetVIconThread *)vt;
484 AssetVIcon *vicon = (AssetVIcon *)avt->vicon;
485 if( vicon && dragging && is_event_win() &&
486 get_button_down() && get_buttonpress() == LEFT_BUTTON &&
487 !ctrl_down() && !alt_down() && !shift_down() ) {
488 switch( draw_mode ) {
489 case ASSET_VIEW_MEDIA_MAP:
490 case ASSET_VIEW_FULL:
491 MWindow *mwindow = vicon->picon->mwindow;
492 EDL *edl = mwindow->edl;
493 int x = get_cursor_x();
494 double total_length = edl->tracks->total_length();
495 double pos = x * total_length / get_w();
496 mwindow->gui->lock_window("AssetVIcon::popup_cursor_motion");
497 mwindow->select_point(pos);
498 mwindow->zoom_sample(edl->local_session->zoom_sample);
499 mwindow->gui->unlock_window();
506 void AssetViewPopup::draw_vframe(VFrame *vframe)
508 switch( draw_mode ) {
509 case ASSET_VIEW_MEDIA:
510 case ASSET_VIEW_ICON:
511 ViewPopup::draw_vframe(vframe);
512 case ASSET_VIEW_NONE:
515 case ASSET_VIEW_MEDIA_MAP:
516 case ASSET_VIEW_FULL:
520 draw_box(0,0,get_w(),get_h());
522 int y2 = get_h()-bar_h;
523 BC_WindowBase::draw_vframe(vframe, 0,y1, get_w(),y2-y1);
524 AssetVIconThread *avt = (AssetVIconThread *)vt;
525 AssetVIcon *vicon = (AssetVIcon *)avt->vicon;
526 AssetPicon *picon = (AssetPicon *)vicon->picon;
528 picon->indexable ? picon->indexable :
529 picon->edl ? picon->edl : 0;
531 double sample_rate = idxbl->get_sample_rate();
532 double audio_length = sample_rate > 0 && idxbl->have_audio() ?
533 idxbl->get_audio_samples() / sample_rate : 0;
534 double frame_rate = idxbl->get_frame_rate();
535 double video_length = frame_rate > 0 && idxbl->have_video() ?
536 idxbl->get_video_frames() / frame_rate : 0;
537 double idxbl_length = bmax(audio_length, video_length);
538 if( !idxbl_length ) idxbl_length = 1;
540 EDL *edl = picon->mwindow->edl;
541 double total_length = edl->tracks->total_length();
542 if( !total_length ) total_length = 1;
543 for( Track *track=edl->tracks->first; track!=0; track=track->next ) {
544 if( !track->is_armed() ) continue;
545 for( Edit *edit=track->edits->first; edit!=0; edit=edit->next ) {
546 Indexable *indexable = (Indexable *)edit->asset;
547 if( !indexable ) indexable = (Indexable *)edit->nested_edl;
548 if( !indexable ) continue;
549 if( indexable->id == idxbl->id ||
550 (!indexable->is_asset == !idxbl->is_asset &&
551 !strcmp(indexable->path, idxbl->path)) ) {
552 double pos1 = track->from_units(edit->startsource);
553 double pos2 = track->from_units(edit->startsource + edit->length);
554 double xscale = get_w() / idxbl_length;
555 int ex1 = pos1 * xscale, ex2 = pos2 * xscale;
557 draw_box(ex1,0, ex2-ex1,y1);
559 draw_line(ex1,0, ex1,y1);
560 draw_line(ex2,0, ex2,y1);
561 pos1 = track->from_units(edit->startproject);
562 pos2 = track->from_units(edit->startproject + edit->length);
563 xscale = get_w() / total_length;
564 int px1 = pos1 * xscale, px2 = pos2 * xscale;
566 draw_box(px1,y2, px2-px1,get_h()-y2);
568 draw_line(px1,y2, px1,get_h()-1);
569 draw_line(px2,y2, px2,get_h()-1);
572 draw_line(ex1,y1, px1,y2);
573 draw_line(ex2,y1, px2,y2);
579 int AssetViewPopup::keypress_event()
582 AssetVIconThread *avt = (AssetVIconThread *)vt;
583 switch( avt->draw_mode ) {
584 case ASSET_VIEW_MEDIA_MAP:
585 switch( get_keypress() ) {
588 avt->draw_mode = ASSET_VIEW_FULL;
592 case ASSET_VIEW_FULL:
593 avt->draw_mode = ASSET_VIEW_MEDIA_MAP;
596 if( result ) // zero change for refresh
598 return ViewPopup::keypress_event();
602 AssetVIconThread::AssetVIconThread(AWindowGUI *gui, Preferences *preferences)
603 : VIconThread(gui->asset_list, preferences->vicon_size * 16/9, preferences->vicon_size,
604 4*preferences->awindow_picon_h * 16/9, 4*preferences->awindow_picon_h)
607 draw_mode = ASSET_VIEW_NONE;
608 int vicon_cmodel = BC_RGB8;
609 switch( preferences->vicon_color_mode ) {
610 case VICON_COLOR_MODE_LOW: vicon_cmodel = BC_RGB8; break;
611 case VICON_COLOR_MODE_MED: vicon_cmodel = BC_RGB565; break;
612 case VICON_COLOR_MODE_HIGH: vicon_cmodel = BC_RGB888; break;
614 this->vicon_cmodel = vicon_cmodel;
615 this->draw_lock = new Mutex("AssetVIconThread::draw_lock");
618 AssetVIconThread::~AssetVIconThread()
623 void AssetVIconThread::drawing_started()
625 draw_lock->lock("AssetVIconThread::drawing_started");
628 void AssetVIconThread::drawing_stopped()
633 void AssetVIconThread::set_view_popup(AssetVIcon *v, int draw_mode)
635 gui->stop_vicon_drawing();
636 this->draw_mode = draw_mode;
638 gui->start_vicon_drawing();
641 void AssetVIconThread::set_view_popup(AssetVIcon *v)
643 if( !v ) draw_mode = ASSET_VIEW_NONE;
644 VIconThread::set_view_popup(v);
647 ViewPopup *AssetVIconThread::new_view_window(ViewPopup *vpopup)
649 BC_WindowBase *parent = wdw->get_parent();
650 int rx = 0, ry = 0, rw = 0, rh = 0;
651 if( draw_mode != ASSET_VIEW_FULL ) {
652 XineramaScreenInfo *info = parent->get_xinerama_info(-1);
653 int cx = info ? info->x_org + info->width/2 : parent->get_root_w(0)/2;
654 int cy = info ? info->y_org + info->height/2 : parent->get_root_h(0)/2;
655 int vx = viewing->get_vx(), vy = viewing->get_vy();
656 wdw->get_root_coordinates(vx, vy, &rx, &ry);
657 rx += (rx >= cx ? -view_w+viewing->w/4 : viewing->w-viewing->w/4);
658 ry += (ry >= cy ? -view_h+viewing->h/4 : viewing->h-viewing->h/4);
659 rw = view_w; rh = view_h;
662 parent->get_fullscreen_geometry(rx, ry, rw, rh);
663 AssetViewPopup *av_popup = (AssetViewPopup *)vpopup;
665 av_popup->reposition_window(rx, ry, rw, rh);
667 av_popup = new AssetViewPopup(this, draw_mode, rx, ry, rw, rh);
668 int playing_audio = gui->play_off ? -1 : 0;
669 if( !playing_audio ) {
670 switch( draw_mode ) {
671 case ASSET_VIEW_NONE:
672 case ASSET_VIEW_ICON:
673 case ASSET_VIEW_MEDIA_MAP:
674 case ASSET_VIEW_FULL:
677 case ASSET_VIEW_MEDIA:
678 switch( gui->vicon_drawing ) {
679 case AVICON_SRC_TARGET:
686 vicon->playing_audio = playing_audio;
687 wdw->set_active_subwindow(av_popup);
691 void AssetVIconThread::stop_vicon_drawing(int wait)
695 drawing_started(); // waits for draw lock
701 AWindowFolderItem::AWindowFolderItem()
707 AWindowFolderItem::AWindowFolderItem(const char *text, int color)
708 : BC_ListBoxItem(text, color)
713 AWindowFolderItem::AWindowFolderItem(const char *text, BC_Pixmap *icon, int color)
714 : BC_ListBoxItem(text, icon, color)
719 AssetPicon *AWindowFolderItem::get_picon()
721 AWindowFolderItem *item = this;
722 while( item->parent ) { item = (AWindowFolderItem*)item->parent; }
723 return (AssetPicon*)item;
726 int AWindowFolderSubItems::matches(const char *text)
728 int i = names.size();
729 while( --i >= 0 && strcmp(names[i], text) );
731 ArrayList<BC_ListBoxItem *> *sublist = get_sublist();
732 i = sublist ? sublist->size() : 0;
734 AWindowFolderSubItems *item = (AWindowFolderSubItems *)sublist->get(i);
735 if( item->matches(text) ) break;
738 return i >= 0 ? 1 : 0;
742 AssetPicon::AssetPicon(MWindow *mwindow,
743 AWindowGUI *gui, Indexable *indexable)
744 : AWindowFolderItem()
747 this->mwindow = mwindow;
749 this->indexable = indexable;
750 indexable->add_user();
751 this->id = indexable->id;
754 AssetPicon::AssetPicon(MWindow *mwindow,
755 AWindowGUI *gui, EDL *edl)
756 : AWindowFolderItem()
759 this->mwindow = mwindow;
766 AssetPicon::AssetPicon(MWindow *mwindow,
767 AWindowGUI *gui, int folder, int persist)
768 : AWindowFolderItem(_(AWindowGUI::folder_names[folder]),
769 folder>=0 && folder<AWINDOW_FOLDERS ?
770 gui->folder_icons[folder] : gui->folder_icon)
774 this->mwindow = mwindow;
776 persistent = persist;
779 AssetPicon::AssetPicon(MWindow *mwindow,
780 AWindowGUI *gui, int folder, const char *title)
781 : AWindowFolderItem(title, gui->folder_icon)
785 this->mwindow = mwindow;
790 AssetPicon::AssetPicon(MWindow *mwindow,
791 AWindowGUI *gui, PluginServer *plugin)
792 : AWindowFolderItem()
795 this->mwindow = mwindow;
797 this->plugin = plugin;
800 AssetPicon::AssetPicon(MWindow *mwindow,
801 AWindowGUI *gui, Label *label)
802 : AWindowFolderItem()
805 this->mwindow = mwindow;
813 AssetPicon::~AssetPicon()
815 if( vicon ) vicon->remove_user();
817 if( indexable ) indexable->remove_user();
818 if( edl ) edl->remove_user();
819 if( icon && !gui->protected_pixmap(icon) ) {
821 if( !plugin ) delete icon_vframe;
825 void AssetPicon::draw_hue_bar(VFrame *frame, double duration)
827 float t = duration > 1 ? (log(duration) / log(3600.f)) : 0;
829 float h = 300 * t, s = 1., v = 1.;
830 float r, g, b; // duration, 0..1hr == hue red..magenta
831 HSV::hsv_to_rgb(r,g,b, h,s,v);
832 int ih = frame->get_h()/8, iw = frame->get_w();
833 int ir = r * 256; CLAMP(ir, 0,255);
834 int ig = g * 256; CLAMP(ig, 0,255);
835 int ib = b * 256; CLAMP(ib, 0,255);
836 unsigned char **rows = frame->get_rows();
837 for( int y=0; y<ih; ++y ) {
838 unsigned char *rp = rows[y];
839 for( int x=0; x<iw; rp+=3,++x ) {
840 rp[0] = ir; rp[1] = ig; rp[2] = ib;
845 void AssetPicon::draw_wave(VFrame *frame, double *dp, int len,
846 int base_color, int line_color, int x, int y, int w, int h)
848 int h1 = h-1, h2 = h/2, iy = h2;
849 int rgb_color = frame->pixel_rgb;
850 for( int ix=0,x1=0,x2=0; ix<w; ++ix,x1=x2 ) {
851 double min = *dp, max = min;
852 x2 = (len * (ix+1))/w;
853 for( int i=x1; i<x2; ++i ) {
854 double value = *dp++;
855 if( value < min ) min = value;
856 if( value > max ) max = value;
858 int ctr = (min + max) / 2;
859 int y0 = (int)(h2 - ctr*h2); CLAMP(y0, 0,h1);
860 int y1 = (int)(h2 - min*h2); CLAMP(y1, 0,h1);
861 int y2 = (int)(h2 - max*h2); CLAMP(y2, 0,h1);
862 frame->pixel_rgb = line_color;
863 frame->draw_line(ix+x,y1+y, ix+x,y2+y);
864 frame->pixel_rgb = base_color;
865 frame->draw_line(ix+x,iy+y, ix+x,y0+y);
868 frame->pixel_rgb = rgb_color;
871 void AssetPicon::reset()
879 foldernum = AW_NO_FOLDER;
894 void AssetPicon::open_render_engine(EDL *edl, int is_audio)
896 TransportCommand command;
897 command.command = is_audio ? NORMAL_FWD : CURRENT_FRAME;
898 command.get_edl()->copy_all(edl);
899 command.change_type = CHANGE_ALL;
900 command.realtime = 0;
901 render_engine = new RenderEngine(0, mwindow->preferences, 0, 0);
902 render_engine->set_vcache(mwindow->video_cache);
903 render_engine->set_acache(mwindow->audio_cache);
904 render_engine->arm_command(&command);
906 void AssetPicon::close_render_engine()
908 delete render_engine; render_engine = 0;
910 void AssetPicon::render_video(int64_t pos, VFrame *vfrm)
912 if( !render_engine || !render_engine->vrender ) return;
913 render_engine->vrender->process_buffer(vfrm, pos, 0);
915 void AssetPicon::render_audio(int64_t pos, Samples **samples, int len)
917 if( !render_engine || !render_engine->arender ) return;
918 render_engine->arender->process_buffer(samples, len, pos);
921 void AssetPicon::create_objects()
924 char name[BCTEXTLEN];
925 int pixmap_w, pixmap_h;
927 int picon_h = mwindow->preferences->awindow_picon_h;
928 pixmap_h = picon_h * BC_WindowBase::get_resources()->icon_scale;
934 if( this->indexable ) {
936 if( this->indexable->is_asset ) {
937 asset = (Asset *)indexable;
938 if( asset->format == FILE_REF ) {
939 cp += sprintf(cp, "ref:");
940 set_color(get_color() ^ 0x5599CC);
944 edl = (EDL *)indexable;
945 cp += sprintf(cp, "edl:");
946 // set_color(get_color() ^ 0xCC9955);
948 fs.extract_name(cp, indexable->path);
951 else if( this->edl ) {
953 strcpy(name, edl->local_session->clip_title);
959 if( asset->video_data ) {
960 if( mwindow->preferences->use_thumbnails ) {
961 gui->unlock_window();
962 File *file = mwindow->video_cache->check_out(asset,
967 int height = asset->height > 0 ? asset->height : 1;
968 pixmap_w = pixmap_h * asset->width / height;
971 file->set_video_position(0, 0);
973 if( gui->temp_picon &&
974 (gui->temp_picon->get_w() != asset->width ||
975 gui->temp_picon->get_h() != asset->height) ) {
976 delete gui->temp_picon;
980 if( !gui->temp_picon ) {
981 gui->temp_picon = new VFrame(0, -1,
982 asset->width, asset->height,
985 { char string[BCTEXTLEN];
986 sprintf(string, _("Reading %s"), name);
987 mwindow->gui->lock_window("AssetPicon::create_objects");
988 mwindow->gui->show_message(string);
989 mwindow->gui->unlock_window(); }
990 file->read_frame(gui->temp_picon);
991 mwindow->video_cache->check_in(asset);
993 gui->lock_window("AssetPicon::create_objects 0");
994 icon = new BC_Pixmap(gui, pixmap_w, pixmap_h);
995 icon->draw_vframe(gui->temp_picon,
996 0, 0, pixmap_w, pixmap_h, 0, 0);
997 icon_vframe = new VFrame(0,
998 -1, pixmap_w, pixmap_h, BC_RGB888, -1);
999 icon_vframe->transfer_from(gui->temp_picon);
1000 if( asset->folder_no == AW_MEDIA_FOLDER ||
1001 asset->folder_no == AW_PROXY_FOLDER ) {
1003 double framerate = asset->get_frame_rate();
1004 if( !framerate ) framerate = VICON_RATE;
1005 int64_t frames = asset->get_video_frames();
1006 double secs = frames / framerate;
1007 if( secs > 5 ) secs = 5;
1008 int64_t length = secs * gui->vicon_thread->refresh_rate;
1009 vicon = new AssetVIcon(this, pixmap_w, pixmap_h, framerate, length);
1010 if( asset->audio_data && secs > 0 ) {
1011 gui->unlock_window();
1012 int audio_len = VICON_SAMPLE_RATE*secs+0.5;
1013 vicon->init_audio(audio_len*sizeof(vicon_audio_t));
1014 vicon->load_audio();
1015 gui->lock_window("AssetPicon::create_objects 1");
1017 gui->vicon_thread->add_vicon(vicon);
1021 eprintf("Unable to open %s\nin asset: %s",asset->path, get_text());
1022 gui->lock_window("AssetPicon::create_objects 2");
1023 icon = gui->video_icon;
1024 icon_vframe = gui->video_vframe;
1028 icon = gui->video_icon;
1029 icon_vframe = gui->video_vframe;
1033 if( asset->audio_data ) {
1034 if( mwindow->preferences->use_thumbnails ) {
1035 gui->unlock_window();
1036 File *file = mwindow->audio_cache->check_out(asset,
1040 pixmap_w = pixmap_h * 16/9;
1041 icon_vframe = new VFrame(0,
1042 -1, pixmap_w, pixmap_h, BC_RGB888, -1);
1043 icon_vframe->clear_frame();
1044 { char string[BCTEXTLEN];
1045 sprintf(string, _("Reading %s"), name);
1046 mwindow->gui->lock_window("AssetPicon::create_objects 3");
1047 mwindow->gui->show_message(string);
1048 mwindow->gui->unlock_window(); }
1049 int sample_rate = asset->get_sample_rate();
1050 int channels = asset->get_audio_channels();
1051 if( channels > 2 ) channels = 2;
1052 int64_t audio_samples = asset->get_audio_samples();
1053 double duration = (double)audio_samples / sample_rate;
1054 draw_hue_bar(icon_vframe, duration);
1055 int bfrsz = sample_rate;
1056 Samples samples(bfrsz);
1057 static int line_colors[2] = { GREEN, YELLOW };
1058 static int base_colors[2] = { RED, PINK };
1059 for( int i=channels; --i>=0; ) {
1060 file->set_channel(i);
1061 file->set_audio_position(0);
1062 file->read_samples(&samples, bfrsz);
1063 draw_wave(icon_vframe, samples.get_data(), bfrsz,
1064 base_colors[i], line_colors[i]);
1066 mwindow->audio_cache->check_in(asset);
1067 if( asset->folder_no == AW_MEDIA_FOLDER ) {
1068 double secs = duration;
1069 if( secs > 5 ) secs = 5;
1070 double refresh_rate = gui->vicon_thread->refresh_rate;
1071 int64_t length = secs * refresh_rate;
1072 vicon = new AssetVIcon(this, pixmap_w, pixmap_h, refresh_rate, length);
1073 int audio_len = VICON_SAMPLE_RATE*secs+0.5;
1074 vicon->init_audio(audio_len*sizeof(vicon_audio_t));
1075 vicon->load_audio();
1076 gui->vicon_thread->add_vicon(vicon);
1078 gui->lock_window("AssetPicon::create_objects 4");
1079 icon = new BC_Pixmap(gui, pixmap_w, pixmap_h);
1080 icon->draw_vframe(icon_vframe,
1081 0, 0, pixmap_w, pixmap_h, 0, 0);
1084 eprintf("Unable to open %s\nin asset: %s",asset->path, get_text());
1085 gui->lock_window("AssetPicon::create_objects 5");
1086 icon = gui->audio_icon;
1087 icon_vframe = gui->audio_vframe;
1091 icon = gui->audio_icon;
1092 icon_vframe = gui->audio_vframe;
1097 comments_time = !stat(asset->path, &st) ? st.st_mtime : 0;
1098 comments_rate = asset->get_frame_rate();
1099 comments_ffmt = asset->format == FILE_FFMPEG ? '=' : '-';
1100 comments_type = asset->format == FILE_FFMPEG ?
1101 asset->vcodec : File::formattostr(asset->format);
1104 if( edl->tracks->playable_video_tracks() ) {
1105 if( mwindow->preferences->use_thumbnails ) {
1106 gui->unlock_window();
1107 AssetVIconThread *avt = gui->vicon_thread;
1108 char clip_icon_path[BCTEXTLEN];
1109 char *clip_icon = edl->local_session->clip_icon;
1111 if( is_clip && clip_icon[0] ) {
1112 snprintf(clip_icon_path, sizeof(clip_icon_path),
1113 "%s/%s", File::get_config_path(), clip_icon);
1114 vframe = VFramePng::vframe_png(clip_icon_path);
1117 ( vframe->get_w() != avt->vw || vframe->get_h() != avt->vh ) ) {
1118 delete vframe; vframe = 0;
1120 int edl_h = edl->get_h(), edl_w = edl->get_w();
1121 int height = edl_h > 0 ? edl_h : 1;
1122 int width = edl_w > 0 ? edl_w : 1;
1123 int color_model = edl->session->color_model;
1125 //printf("render clip: %s\n", name);
1126 VFrame::get_temp(gui->temp_picon, width, height, color_model);
1127 char string[BCTEXTLEN];
1128 sprintf(string, _("Rendering %s"), name);
1129 mwindow->gui->lock_window("AssetPicon::create_objects");
1130 mwindow->gui->show_message(string);
1131 mwindow->gui->unlock_window();
1132 open_render_engine(edl, 0);
1133 render_video(0, gui->temp_picon);
1134 close_render_engine();
1135 vframe = new VFrame(avt->vw, avt->vh, BC_RGB888);
1136 vframe->transfer_from(gui->temp_picon);
1137 if( this->edl && clip_icon[0] )
1138 vframe->write_png(clip_icon_path);
1140 pixmap_w = pixmap_h * width / height;
1141 vicon = new AssetVIcon(this, pixmap_w, pixmap_h, VICON_RATE, 1);
1142 vicon->add_image(vframe, avt->vw, avt->vh, avt->vicon_cmodel);
1143 icon_vframe = new VFrame(pixmap_w, pixmap_h, BC_RGB888);
1144 icon_vframe->transfer_from(vframe);
1146 gui->lock_window("AssetPicon::create_objects 0");
1147 icon = new BC_Pixmap(gui, pixmap_w, pixmap_h);
1148 icon->draw_vframe(icon_vframe,
1149 0, 0, pixmap_w, pixmap_h, 0, 0);
1151 else if( is_clip ) {
1152 icon = gui->clip_icon;
1153 icon_vframe = gui->clip_vframe;
1156 icon = gui->video_icon;
1157 icon_vframe = gui->video_vframe;
1161 if( edl->tracks->playable_audio_tracks() ) {
1162 if( mwindow->preferences->use_thumbnails ) {
1163 gui->unlock_window();
1164 char clip_icon_path[BCTEXTLEN];
1165 char *clip_icon = edl->local_session->clip_icon;
1166 if( is_clip && clip_icon[0] ) {
1167 snprintf(clip_icon_path, sizeof(clip_icon_path),
1168 "%s/%s", File::get_config_path(), clip_icon);
1169 icon_vframe = VFramePng::vframe_png(clip_icon_path);
1171 if( !icon_vframe ) {
1172 pixmap_w = pixmap_h * 16/9;
1173 icon_vframe = new VFrame(0,
1174 -1, pixmap_w, pixmap_h, BC_RGB888, -1);
1175 icon_vframe->clear_frame();
1176 char string[BCTEXTLEN];
1177 sprintf(string, _("Rendering %s"), name);
1178 mwindow->gui->lock_window("AssetPicon::create_objects 3");
1179 mwindow->gui->show_message(string);
1180 mwindow->gui->unlock_window();
1181 int sample_rate = edl->get_sample_rate();
1182 int channels = edl->get_audio_channels();
1183 if( channels > 2 ) channels = 2;
1184 int64_t audio_samples = edl->get_audio_samples();
1185 double duration = (double)audio_samples / sample_rate;
1186 draw_hue_bar(icon_vframe, duration);
1187 Samples *samples[MAX_CHANNELS];
1188 int bfrsz = sample_rate;
1189 for( int i=0; i<MAX_CHANNELS; ++i )
1190 samples[i] = i<channels ? new Samples(bfrsz) : 0;
1191 open_render_engine(edl, 1);
1192 render_audio(0, samples, bfrsz);
1193 close_render_engine();
1194 gui->lock_window("AssetPicon::create_objects 4");
1195 static int line_colors[2] = { GREEN, YELLOW };
1196 static int base_colors[2] = { RED, PINK };
1197 for( int i=channels; --i>=0; ) {
1198 draw_wave(icon_vframe, samples[i]->get_data(), bfrsz,
1199 base_colors[i], line_colors[i]);
1201 for( int i=0; i<channels; ++i ) delete samples[i];
1202 if( is_clip && clip_icon[0] )
1203 icon_vframe->write_png(clip_icon_path);
1206 pixmap_w = icon_vframe->get_w();
1207 pixmap_h = icon_vframe->get_h();
1209 icon = new BC_Pixmap(gui, pixmap_w, pixmap_h);
1210 icon->draw_vframe(icon_vframe,
1211 0, 0, pixmap_w, pixmap_h, 0, 0);
1213 else if( !indexable ) {
1214 icon = gui->clip_icon;
1215 icon_vframe = gui->clip_vframe;
1218 icon = gui->audio_icon;
1219 icon_vframe = gui->audio_vframe;
1224 strcpy(name, _(plugin->title));
1226 icon_vframe = plugin->get_picon();
1228 icon = gui->create_pixmap(icon_vframe);
1229 else if( plugin->audio ) {
1230 if( plugin->transition ) {
1231 icon = gui->atransition_icon;
1232 icon_vframe = gui->atransition_vframe;
1234 else if( plugin->is_ffmpeg() ) {
1235 icon = gui->ff_aud_icon;
1236 icon_vframe = gui->ff_aud_vframe;
1238 else if( plugin->is_ladspa() ) {
1239 icon = gui->ladspa_icon;
1240 icon_vframe = gui->ladspa_vframe;
1243 icon = gui->aeffect_icon;
1244 icon_vframe = gui->aeffect_vframe;
1247 else if( plugin->video ) {
1248 if( plugin->transition ) {
1249 icon = gui->vtransition_icon;
1250 icon_vframe = gui->vtransition_vframe;
1252 else if( plugin->is_ffmpeg() ) {
1253 icon = gui->ff_vid_icon;
1254 icon_vframe = gui->ff_vid_vframe;
1257 icon = gui->veffect_icon;
1258 icon_vframe = gui->veffect_vframe;
1265 mwindow->edl->session->time_format,
1266 mwindow->edl->session->sample_rate,
1267 mwindow->edl->session->frame_rate,
1268 mwindow->edl->session->frames_per_foot);
1270 icon = gui->label_icon;
1271 icon_vframe = gui->label_vframe;
1274 icon = gui->file_icon;
1275 icon_vframe = BC_WindowBase::get_resources()->type_to_icon[ICON_UNKNOWN];
1278 set_icon_vframe(icon_vframe);
1281 AWindowGUI::AWindowGUI(MWindow *mwindow, AWindow *awindow)
1282 : BC_Window(_(PROGRAM_NAME ": Resources"),
1283 mwindow->session->awindow_x, mwindow->session->awindow_y,
1284 mwindow->session->awindow_w, mwindow->session->awindow_h,
1285 xS(100), yS(100), 1, 1, 1)
1287 this->mwindow = mwindow;
1288 this->awindow = awindow;
1290 file_vframe = 0; file_icon = 0;
1291 folder_vframe = 0; folder_icon = 0;
1292 audio_vframe = 0; audio_icon = 0;
1293 video_vframe = 0; video_icon = 0;
1294 label_vframe = 0; label_icon = 0;
1296 aeffect_folder_vframe = 0; aeffect_folder_icon = 0;
1297 atransition_folder_vframe = 0; atransition_folder_icon = 0;
1298 clip_folder_vframe = 0; clip_folder_icon = 0;
1299 label_folder_vframe = 0; label_folder_icon = 0;
1300 media_folder_vframe = 0; media_folder_icon = 0;
1301 proxy_folder_vframe = 0; proxy_folder_icon = 0;
1302 veffect_folder_vframe = 0; veffect_folder_icon = 0;
1303 vtransition_folder_vframe = 0; vtransition_folder_icon = 0;
1305 ladspa_vframe = 0; ladspa_icon = 0;
1306 ff_aud_vframe = 0; ff_aud_icon = 0;
1307 ff_vid_vframe = 0; ff_vid_icon = 0;
1309 clip_vframe = 0; clip_icon = 0;
1310 atransition_vframe = 0; atransition_icon = 0;
1311 vtransition_vframe = 0; vtransition_icon = 0;
1312 aeffect_vframe = 0; aeffect_icon = 0;
1313 veffect_vframe = 0; veffect_icon = 0;
1315 plugin_visibility = ((uint64_t)1<<(8*sizeof(uint64_t)-1))-1;
1317 effectlist_menu = 0;
1322 folderlist_menu = 0;
1325 allow_iconlisting = 1;
1329 vicon_drawing = AVICON_FULL_PLAY;
1332 displayed_folder = AW_NO_FOLDER;
1333 new_folder_thread = 0;
1334 modify_folder_thread = 0;
1335 folder_lock = new Mutex("AWindowGUI::folder_lock");
1338 AWindowGUI::~AWindowGUI()
1340 assets.remove_all_objects();
1341 folders.remove_all_objects();
1342 aeffects.remove_all_objects();
1343 veffects.remove_all_objects();
1344 atransitions.remove_all_objects();
1345 vtransitions.remove_all_objects();
1346 labellist.remove_all_objects();
1347 displayed_assets[1].remove_all_objects();
1349 delete new_folder_thread;
1350 delete modify_folder_thread;
1351 delete vicon_thread;
1356 delete remove_plugin;
1358 delete file_vframe; delete file_icon;
1359 delete folder_vframe; delete folder_icon;
1360 delete audio_vframe; delete audio_icon;
1361 delete video_vframe; delete video_icon;
1362 delete label_vframe; delete label_icon;
1363 delete clip_vframe; delete clip_icon;
1364 delete aeffect_folder_vframe; delete aeffect_folder_icon;
1365 delete atransition_folder_vframe; delete atransition_folder_icon;
1366 delete veffect_folder_vframe; delete veffect_folder_icon;
1367 delete vtransition_folder_vframe; delete vtransition_folder_icon;
1368 delete clip_folder_vframe; delete clip_folder_icon;
1369 delete label_folder_vframe; delete label_folder_icon;
1370 delete media_folder_vframe; delete media_folder_icon;
1371 delete proxy_folder_vframe; delete proxy_folder_icon;
1372 delete ladspa_vframe; delete ladspa_icon;
1373 delete ff_aud_vframe; delete ff_aud_icon;
1374 delete ff_vid_vframe; delete ff_vid_icon;
1375 delete atransition_vframe; delete atransition_icon;
1376 delete vtransition_vframe; delete vtransition_icon;
1377 delete aeffect_vframe; delete aeffect_icon;
1378 delete veffect_vframe; delete veffect_icon;
1382 bool AWindowGUI::protected_pixmap(BC_Pixmap *icon)
1384 return icon == file_icon ||
1385 icon == folder_icon ||
1386 icon == audio_icon ||
1387 icon == video_icon ||
1388 icon == clip_icon ||
1389 icon == label_icon ||
1390 icon == vtransition_icon ||
1391 icon == atransition_icon ||
1392 icon == veffect_icon ||
1393 icon == aeffect_icon ||
1394 icon == ladspa_icon ||
1395 icon == ff_aud_icon ||
1396 icon == ff_vid_icon ||
1397 icon == aeffect_folder_icon ||
1398 icon == veffect_folder_icon ||
1399 icon == atransition_folder_icon ||
1400 icon == vtransition_folder_icon ||
1401 icon == label_folder_icon ||
1402 icon == clip_folder_icon ||
1403 icon == media_folder_icon ||
1404 icon == proxy_folder_icon;
1407 VFrame *AWindowGUI::get_picon(const char *name, const char *plugin_icons)
1409 char png_path[BCTEXTLEN];
1410 char *pp = png_path, *ep = pp + sizeof(png_path)-1;
1411 snprintf(pp, ep-pp, "%s/picon/%s/%s.png",
1412 File::get_plugin_path(), plugin_icons, name);
1413 if( access(png_path, R_OK) ) return 0;
1414 return VFramePng::vframe_png(png_path,0,0);
1417 VFrame *AWindowGUI::get_picon(const char *name)
1419 VFrame *vframe = get_picon(name, mwindow->preferences->plugin_icons);
1421 char png_name[BCSTRLEN], *pp = png_name, *ep = pp + sizeof(png_name)-1;
1422 snprintf(pp, ep-pp, "%s.png", name);
1423 unsigned char *data = mwindow->theme->get_image_data(png_name);
1424 if( data ) vframe = new VFramePng(data, 0.);
1429 void AWindowGUI::resource_icon(VFrame *&vfrm, BC_Pixmap *&icon, const char *fn, int idx)
1431 vfrm = get_picon(fn);
1432 if( !vfrm ) vfrm = BC_WindowBase::get_resources()->type_to_icon[idx];
1433 icon = new BC_Pixmap(this, vfrm, PIXMAP_ALPHA);
1435 void AWindowGUI::theme_icon(VFrame *&vfrm, BC_Pixmap *&icon, const char *fn)
1437 vfrm = get_picon(fn);
1438 if( !vfrm ) vfrm = mwindow->theme->get_image(fn);
1439 icon = new BC_Pixmap(this, vfrm, PIXMAP_ALPHA);
1441 void AWindowGUI::plugin_icon(VFrame *&vfrm, BC_Pixmap *&icon, const char *fn, unsigned char *png)
1443 vfrm = get_picon(fn);
1444 if( !vfrm ) vfrm = new VFramePng(png);
1445 icon = new BC_Pixmap(this, vfrm, PIXMAP_ALPHA);
1448 void AWindowGUI::create_objects()
1450 int ys5 = yS(5), ys10 = yS(10);
1451 lock_window("AWindowGUI::create_objects");
1452 asset_titles[0] = C_("Title");
1453 asset_titles[1] = _("Comments");
1455 set_icon(mwindow->theme->get_image("awindow_icon"));
1457 resource_icon(file_vframe, file_icon, "film_icon", ICON_UNKNOWN);
1458 resource_icon(folder_vframe, folder_icon, "folder_icon", ICON_FOLDER);
1459 resource_icon(audio_vframe, audio_icon, "audio_icon", ICON_SOUND);
1460 resource_icon(video_vframe, video_icon, "video_icon", ICON_FILM);
1461 resource_icon(label_vframe, label_icon, "label_icon", ICON_LABEL);
1463 theme_icon(aeffect_folder_vframe, aeffect_folder_icon, "aeffect_folder");
1464 theme_icon(atransition_folder_vframe, atransition_folder_icon, "atransition_folder");
1465 theme_icon(clip_folder_vframe, clip_folder_icon, "clip_folder");
1466 theme_icon(label_folder_vframe, label_folder_icon, "label_folder");
1467 theme_icon(media_folder_vframe, media_folder_icon, "media_folder");
1468 theme_icon(proxy_folder_vframe, proxy_folder_icon, "proxy_folder");
1469 theme_icon(veffect_folder_vframe, veffect_folder_icon, "veffect_folder");
1470 theme_icon(vtransition_folder_vframe, vtransition_folder_icon, "vtransition_folder");
1472 folder_icons[AW_AEFFECT_FOLDER] = aeffect_folder_icon;
1473 folder_icons[AW_VEFFECT_FOLDER] = veffect_folder_icon;
1474 folder_icons[AW_ATRANSITION_FOLDER] = atransition_folder_icon;
1475 folder_icons[AW_VTRANSITION_FOLDER] = vtransition_folder_icon;
1476 folder_icons[AW_LABEL_FOLDER] = label_folder_icon;
1477 folder_icons[AW_CLIP_FOLDER] = clip_folder_icon;
1478 folder_icons[AW_MEDIA_FOLDER] = media_folder_icon;
1479 folder_icons[AW_PROXY_FOLDER] = proxy_folder_icon;
1481 theme_icon(clip_vframe, clip_icon, "clip_icon");
1482 theme_icon(atransition_vframe, atransition_icon, "atransition_icon");
1483 theme_icon(vtransition_vframe, vtransition_icon, "vtransition_icon");
1484 theme_icon(aeffect_vframe, aeffect_icon, "aeffect_icon");
1485 theme_icon(veffect_vframe, veffect_icon, "veffect_icon");
1487 plugin_icon(ladspa_vframe, ladspa_icon, "lad_picon", lad_picon_png);
1488 plugin_icon(ff_aud_vframe, ff_aud_icon, "ff_audio", ff_audio_png);
1489 plugin_icon(ff_vid_vframe, ff_vid_icon, "ff_video", ff_video_png);
1490 folder_lock->lock("AWindowGUI::create_objects");
1491 // Mandatory folders
1492 folders.append(new AssetPicon(mwindow, this, AW_AEFFECT_FOLDER, 1));
1493 folders.append(new AssetPicon(mwindow, this, AW_VEFFECT_FOLDER, 1));
1494 folders.append(new AssetPicon(mwindow, this, AW_ATRANSITION_FOLDER, 1));
1495 folders.append(new AssetPicon(mwindow, this, AW_VTRANSITION_FOLDER, 1));
1496 folders.append(new AssetPicon(mwindow, this, AW_LABEL_FOLDER, 1));
1497 folders.append(new AssetPicon(mwindow, this, AW_CLIP_FOLDER, 1));
1498 folders.append(new AssetPicon(mwindow, this, AW_PROXY_FOLDER, 1));
1499 folders.append(new AssetPicon(mwindow, this, AW_MEDIA_FOLDER, 1));
1501 create_label_folder();
1502 folder_lock->unlock();
1504 mwindow->theme->get_awindow_sizes(this);
1505 load_defaults(mwindow->defaults);
1506 new_folder_thread = new NewFolderThread(this);
1507 modify_folder_thread = new ModifyFolderThread(this);
1509 int x1 = mwindow->theme->alist_x, y1 = mwindow->theme->alist_y;
1510 int w1 = mwindow->theme->alist_w, h1 = mwindow->theme->alist_h;
1511 search_text = new AWindowSearchText(mwindow, this, x1, y1+ys5);
1512 search_text->create_objects();
1513 int dy = search_text->get_h() + ys10;
1515 add_subwindow(asset_list = new AWindowAssets(mwindow, this, x1, y1, w1, h1));
1517 vicon_thread = new AssetVIconThread(this, mwindow->preferences);
1518 asset_list->update_vicon_area();
1519 vicon_thread->start();
1520 vicon_audio = new AssetVIconAudio(this);
1522 add_subwindow(divider = new AWindowDivider(mwindow, this,
1523 mwindow->theme->adivider_x, mwindow->theme->adivider_y,
1524 mwindow->theme->adivider_w, mwindow->theme->adivider_h));
1526 divider->set_cursor(HSEPARATE_CURSOR, 0, 0);
1528 int fx = mwindow->theme->afolders_x, fy = mwindow->theme->afolders_y;
1529 int fw = mwindow->theme->afolders_w, fh = mwindow->theme->afolders_h;
1530 int n = sizeof(AVIconDrawing::avicon_names)/sizeof(AVIconDrawing::avicon_names[0]);
1531 int tw = 0; const char **av_names = AVIconDrawing::avicon_names;
1532 for( int i=0; i<n; ++i ) {
1533 int nw = get_text_width(MEDIUMFONT, _(av_names[i]));
1534 if( tw < nw ) tw = nw;
1536 int pw = BC_PopupMenu::calculate_w(xS(16), tw, 1);
1537 const char *text = _(AVIconDrawing::avicon_names[vicon_drawing]);
1538 add_subwindow(avicon_drawing = new AVIconDrawing(this, fw, fy, pw, text));
1539 avicon_drawing->create_objects();
1540 add_subwindow(add_tools = new AddTools(mwindow, this, fx, fy, _("Visibility")));
1541 add_tools->create_objects();
1542 fy += add_tools->get_h(); fh -= add_tools->get_h();
1543 add_subwindow(folder_list = new AWindowFolders(mwindow,
1544 this, fx, fy, fw, fh));
1546 folder_list->load_expanders();
1548 //int x = mwindow->theme->abuttons_x;
1549 //int y = mwindow->theme->abuttons_y;
1551 add_subwindow(asset_menu = new AssetPopup(mwindow, this));
1552 asset_menu->create_objects();
1553 add_subwindow(clip_menu = new ClipPopup(mwindow, this));
1554 clip_menu->create_objects();
1555 add_subwindow(label_menu = new LabelPopup(mwindow, this));
1556 label_menu->create_objects();
1557 add_subwindow(proxy_menu = new ProxyPopup(mwindow, this));
1558 proxy_menu->create_objects();
1560 add_subwindow(effectlist_menu = new EffectListMenu(mwindow, this));
1561 effectlist_menu->create_objects();
1562 add_subwindow(assetlist_menu = new AssetListMenu(mwindow, this));
1563 assetlist_menu->create_objects();
1564 add_subwindow(cliplist_menu = new ClipListMenu(mwindow, this));
1565 cliplist_menu->create_objects();
1566 add_subwindow(labellist_menu = new LabelListMenu(mwindow, this));
1567 labellist_menu->create_objects();
1568 add_subwindow(proxylist_menu = new ProxyListMenu(mwindow, this));
1569 proxylist_menu->create_objects();
1571 add_subwindow(folderlist_menu = new FolderListMenu(mwindow, this));
1572 folderlist_menu->create_objects();
1574 create_custom_xatoms();
1578 int AWindowGUI::resize_event(int w, int h)
1580 mwindow->session->awindow_x = get_x();
1581 mwindow->session->awindow_y = get_y();
1582 mwindow->session->awindow_w = w;
1583 mwindow->session->awindow_h = h;
1585 mwindow->theme->get_awindow_sizes(this);
1586 mwindow->theme->draw_awindow_bg(this);
1587 reposition_objects();
1589 // int x = mwindow->theme->abuttons_x;
1590 // int y = mwindow->theme->abuttons_y;
1591 // new_bin->reposition_window(x, y);
1592 // x += new_bin->get_w();
1593 // delete_bin->reposition_window(x, y);
1594 // x += delete_bin->get_w();
1595 // rename_bin->reposition_window(x, y);
1596 // x += rename_bin->get_w();
1597 // delete_disk->reposition_window(x, y);
1598 // x += delete_disk->get_w();
1599 // delete_project->reposition_window(x, y);
1600 // x += delete_project->get_w();
1601 // info->reposition_window(x, y);
1602 // x += info->get_w();
1603 // redraw_index->reposition_window(x, y);
1604 // x += redraw_index->get_w();
1605 // paste->reposition_window(x, y);
1606 // x += paste->get_w();
1607 // append->reposition_window(x, y);
1608 // x += append->get_w();
1609 // view->reposition_window(x, y);
1611 BC_WindowBase::resize_event(w, h);
1612 asset_list->update_vicon_area();
1616 int AWindowGUI::translation_event()
1618 mwindow->session->awindow_x = get_x();
1619 mwindow->session->awindow_y = get_y();
1623 void AWindowGUI::reposition_objects()
1625 int ys5 = yS(5), ys10 = yS(10);
1626 int x1 = mwindow->theme->alist_x, y1 = mwindow->theme->alist_y;
1627 int w1 = mwindow->theme->alist_w, h1 = mwindow->theme->alist_h;
1628 search_text->reposition_window(x1, y1+ys5, w1);
1629 int dy = search_text->get_h() + ys10;
1631 asset_list->reposition_window(x1, y1, w1, h1);
1632 divider->reposition_window(
1633 mwindow->theme->adivider_x, mwindow->theme->adivider_y,
1634 mwindow->theme->adivider_w, mwindow->theme->adivider_h);
1635 int fx = mwindow->theme->afolders_x, fy = mwindow->theme->afolders_y;
1636 int fw = mwindow->theme->afolders_w, fh = mwindow->theme->afolders_h;
1637 add_tools->resize_event(fw-avicon_w, add_tools->get_h());
1638 avicon_drawing->reposition_window(fw-avicon_drawing->get_w(), fy);
1639 fy += add_tools->get_h(); fh -= add_tools->get_h();
1640 folder_list->reposition_window(fx, fy, fw, fh);
1643 int AWindowGUI::save_defaults(BC_Hash *defaults)
1645 defaults->update("PLUGIN_VISIBILTY", plugin_visibility);
1646 defaults->update("VICON_DRAWING", vicon_drawing);
1647 defaults->update("TIP_INFO", tip_info);
1651 int AWindowGUI::load_defaults(BC_Hash *defaults)
1653 plugin_visibility = defaults->get("PLUGIN_VISIBILTY", plugin_visibility);
1654 vicon_drawing = defaults->get("VICON_DRAWING", vicon_drawing);
1655 tip_info = defaults->get("TIP_INFO", tip_info);
1659 int AWindowGUI::close_event()
1662 mwindow->session->show_awindow = 0;
1665 mwindow->gui->lock_window("AWindowGUI::close_event");
1666 mwindow->gui->mainmenu->show_awindow->set_checked(0);
1667 mwindow->gui->unlock_window();
1669 lock_window("AWindowGUI::close_event");
1670 save_defaults(mwindow->defaults);
1671 mwindow->save_defaults();
1675 int AWindowGUI::start_vicon_drawing()
1677 if( play_off ) return stop_vicon_drawing();
1678 if( !vicon_thread->interrupted ) return 1;
1679 switch( vicon_drawing ) {
1680 case AVICON_FULL_PLAY: // all vicons, viewing, target
1682 case AVICON_MOUSE_OVER: // one vicon, viewing, target
1683 if( vicon_thread->solo ) break;
1685 case AVICON_SRC_TARGET: // no vicons, no view, target
1686 case AVICON_NO_PLAY: // no vicons, no view, no target
1689 if( mwindow->edl->session->awindow_folder == AW_MEDIA_FOLDER ||
1690 mwindow->edl->session->awindow_folder == AW_PROXY_FOLDER ||
1691 mwindow->edl->session->awindow_folder == AW_CLIP_FOLDER ||
1692 mwindow->edl->session->awindow_folder >= AWINDOW_USER_FOLDERS ) {
1693 switch( mwindow->edl->session->assetlist_format ) {
1695 case ASSETS_ICONS_PACKED:
1696 case ASSETS_ICON_LIST:
1697 asset_list->update_vicon_area();
1698 vicon_thread->start_drawing();
1707 int AWindowGUI::stop_vicon_drawing(int wait)
1709 vicon_thread->stop_vicon_drawing(wait);
1714 VFrame *AssetPicon::get_vicon_frame()
1716 if( !vicon ) return 0;
1717 if( gui->vicon_thread->interrupted ) return 0;
1718 VFrame *frame = vicon->frame();
1719 if( !frame ) return 0;
1721 vicon_frame = new VFrame(vicon->w, vicon->h, frame->get_color_model());
1722 vicon_frame->transfer_from(frame);
1726 int AWindowGUI::cycle_assetlist_format()
1728 EDLSession *session = mwindow->edl->session;
1729 int format = ASSETS_TEXT;
1730 if( allow_iconlisting ) {
1731 switch( session->assetlist_format ) {
1733 format = ASSETS_ICONS;
1736 format = ASSETS_ICONS_PACKED;
1738 case ASSETS_ICONS_PACKED:
1739 format = ASSETS_ICON_LIST;
1741 case ASSETS_ICON_LIST:
1742 format = ASSETS_TEXT;
1746 stop_vicon_drawing();
1747 session->assetlist_format = format;
1748 asset_list->update_format(session->assetlist_format, 0);
1749 async_update_assets();
1750 start_vicon_drawing();
1754 void AWindowGUI::hide_tip_info()
1756 asset_list->hide_tooltip();
1760 AWindowRemovePluginGUI::
1761 AWindowRemovePluginGUI(AWindow *awindow, AWindowRemovePlugin *thread,
1762 int x, int y, PluginServer *plugin)
1763 : BC_Window(_(PROGRAM_NAME ": Remove plugin"), x,y,
1764 xS(500),yS(200), xS(50), yS(50),
1767 this->awindow = awindow;
1768 this->thread = thread;
1769 this->plugin = plugin;
1770 VFrame *vframe = plugin->get_picon();
1771 icon = vframe ? create_pixmap(vframe) : 0;
1772 plugin_list.append(new BC_ListBoxItem(plugin->title, icon));
1775 AWindowRemovePluginGUI::
1776 ~AWindowRemovePluginGUI()
1778 if( !awindow->gui->protected_pixmap(icon) )
1780 plugin_list.remove_all();
1783 void AWindowRemovePluginGUI::create_objects()
1785 int xs10 = xS(10), xs20 = xS(20);
1786 int ys5 = yS(5), ys10 = yS(10);
1787 lock_window("AWindowRemovePluginGUI::create_objects");
1788 BC_Button *ok_button = new BC_OKButton(this);
1789 add_subwindow(ok_button);
1790 BC_Button *cancel_button = new BC_CancelButton(this);
1791 add_subwindow(cancel_button);
1792 int x = xs10, y = ys10;
1793 BC_Title *title = new BC_Title(x, y, _("remove plugin?"));
1794 add_subwindow(title);
1795 y += title->get_h() + ys5;
1796 list = new BC_ListBox(x, y,
1797 get_w() - xs20, ok_button->get_y() - y - ys5, LISTBOX_TEXT, &plugin_list,
1798 0, 0, 1, 0, 0, LISTBOX_SINGLE, ICON_LEFT, 0);
1799 add_subwindow(list);
1804 int AWindowRemovePlugin::remove_plugin(PluginServer *plugin, ArrayList<BC_ListBoxItem*> &folder)
1807 for( int i=0; i<folder.size(); ) {
1808 AssetPicon *picon = (AssetPicon *)folder[i];
1809 if( picon->plugin == plugin ) {
1810 folder.remove_object_number(i);
1819 void AWindowRemovePlugin::handle_close_event(int result)
1822 printf(_("remove %s\n"), plugin->path);
1823 awindow->gui->lock_window("AWindowRemovePlugin::handle_close_event");
1824 ArrayList<BC_ListBoxItem*> *folder =
1825 plugin->audio ? plugin->transition ?
1826 &awindow->gui->atransitions :
1827 &awindow->gui->aeffects :
1828 plugin->video ? plugin->transition ?
1829 &awindow->gui->vtransitions :
1830 &awindow->gui->veffects :
1832 if( folder ) remove_plugin(plugin, *folder);
1833 MWindow *mwindow = awindow->mwindow;
1834 awindow->gui->unlock_window();
1835 char plugin_path[BCTEXTLEN];
1836 strcpy(plugin_path, plugin->path);
1837 mwindow->plugindb->remove(plugin);
1838 remove(plugin_path);
1839 char index_path[BCTEXTLEN];
1840 mwindow->create_defaults_path(index_path, PLUGIN_FILE);
1842 char picon_path[BCTEXTLEN];
1844 snprintf(picon_path, sizeof(picon_path), "%s/picon",
1845 File::get_plugin_path());
1846 char png_name[BCSTRLEN], png_path[BCTEXTLEN];
1847 plugin->get_plugin_png_name(png_name);
1848 fs.update(picon_path);
1849 for( int i=0; i<fs.dir_list.total; ++i ) {
1850 char *fs_path = fs.dir_list[i]->path;
1851 if( !fs.is_dir(fs_path) ) continue;
1852 snprintf(png_path, sizeof(picon_path), "%s/%s",
1856 delete plugin; plugin = 0;
1857 awindow->gui->async_update_assets();
1861 AWindowRemovePlugin::
1862 AWindowRemovePlugin(AWindow *awindow, PluginServer *plugin)
1865 this->awindow = awindow;
1866 this->plugin = plugin;
1869 AWindowRemovePlugin::
1870 ~AWindowRemovePlugin()
1875 BC_Window* AWindowRemovePlugin::new_gui()
1877 int x = awindow->gui->get_abs_cursor_x(0);
1878 int y = awindow->gui->get_abs_cursor_y(0);
1879 AWindowRemovePluginGUI *gui = new AWindowRemovePluginGUI(awindow, this, x, y, plugin);
1880 gui->create_objects();
1884 int AWindowGUI::keypress_event()
1886 switch( get_keypress() ) {
1894 tip_info = !tip_info ? 1 : 0;
1895 if( !tip_info ) hide_tip_info();
1898 if( !ctrl_down() && !shift_down() ) {
1899 assetlist_menu->load_file->handle_event();
1904 return cycle_assetlist_format();
1906 if( shift_down() && ctrl_down() ) {
1907 PluginServer* plugin = selected_plugin();
1908 if( !plugin ) break;
1909 remove_plugin = new AWindowRemovePlugin(awindow, plugin);
1911 remove_plugin->start();
1912 lock_window("AWindowGUI::keypress_event 1");
1916 if( shift_down() ) {
1917 mwindow->awindow->asset_remove->start();
1921 mwindow->remove_assets_from_project(1, 1, 1,
1922 mwindow->session->drag_assets,
1923 mwindow->session->drag_clips);
1924 lock_window("AWindowGUI::keypress_event 2");
1930 if( shift_down() && ctrl_down() ) {
1931 resend_event(mwindow->gui);
1941 int AWindowGUI::create_custom_xatoms()
1943 UpdateAssetsXAtom = create_xatom("CWINDOWGUI_UPDATE_ASSETS");
1946 int AWindowGUI::receive_custom_xatoms(xatom_event *event)
1948 if( event->message_type == UpdateAssetsXAtom ) {
1955 void AWindowGUI::async_update_assets()
1958 event.message_type = UpdateAssetsXAtom;
1959 send_custom_xatom(&event);
1963 void AWindowGUI::update_folder_list()
1965 for( int i = 0; i < folders.total; i++ ) {
1966 AssetPicon *picon = (AssetPicon*)folders.values[i];
1970 // Search assets for folders
1971 for( int i = 0; i < mwindow->edl->folders.total; i++ ) {
1972 BinFolder *bin_folder = mwindow->edl->folders[i];
1975 for( int j = 0; j < folders.total; j++ ) {
1976 AssetPicon *picon = (AssetPicon*)folders[j];
1977 if( !strcasecmp(picon->get_text(), bin_folder->title) ) {
1985 const char *title = bin_folder->title;
1986 int folder = bin_folder->awindow_folder;
1987 AssetPicon *picon = new AssetPicon(mwindow, this, folder, title);
1988 picon->create_objects();
1989 folders.append(picon);
1993 // Delete unused non-persistent folders
1994 int do_autoplace = 0;
1995 for( int i=folders.total; --i>=0; ) {
1996 AssetPicon *picon = (AssetPicon*)folders.values[i];
1997 if( !picon->in_use && !picon->persistent ) {
1999 folders.remove_number(i);
2004 folder_list->set_autoplacement(&folders, 0, 1);
2007 void AWindowGUI::create_persistent_folder(ArrayList<BC_ListBoxItem*> *output,
2008 int do_audio, int do_video, int is_realtime, int is_transition)
2010 ArrayList<PluginServer*> plugin_list;
2011 // Get pointers to plugindb entries
2012 mwindow->search_plugindb(do_audio, do_video, is_realtime, is_transition,
2015 for( int i = 0; i < plugin_list.total; i++ ) {
2016 PluginServer *server = plugin_list.values[i];
2017 int visible = plugin_visibility & (1<<server->dir_idx);
2018 if( !visible ) continue;
2019 // Create new listitem
2020 AssetPicon *picon = new AssetPicon(mwindow, this, server);
2021 picon->create_objects();
2022 output->append(picon);
2026 void AWindowGUI::create_label_folder()
2029 for( current = mwindow->edl->labels->first; current; current = NEXT ) {
2030 AssetPicon *picon = new AssetPicon(mwindow, this, current);
2031 picon->create_objects();
2032 labellist.append(picon);
2037 void AWindowGUI::update_asset_list()
2039 ArrayList<AssetPicon *> new_assets;
2040 for( int i = 0; i < assets.total; i++ ) {
2041 AssetPicon *picon = (AssetPicon*)assets.values[i];
2045 mwindow->gui->lock_window("AWindowGUI::update_asset_list");
2046 // Synchronize EDL clips
2047 for( int i=0; i<mwindow->edl->clips.size(); ++i ) {
2050 // Look for clip in existing listitems
2051 for( int j = 0; j < assets.total && !exists; j++ ) {
2052 AssetPicon *picon = (AssetPicon*)assets.values[j];
2054 if( picon->id == mwindow->edl->clips[i]->id ) {
2055 picon->edl = mwindow->edl->clips[i];
2056 picon->set_text(mwindow->edl->clips[i]->local_session->clip_title);
2062 // Create new listitem
2064 AssetPicon *picon = new AssetPicon(mwindow,
2065 this, mwindow->edl->clips[i]);
2066 new_assets.append(picon);
2070 // Synchronize EDL assets
2071 for( Asset *current=mwindow->edl->assets->first; current; current=NEXT ) {
2074 // Look for asset in existing listitems
2075 for( int j = 0; j < assets.total && !exists; j++ ) {
2076 AssetPicon *picon = (AssetPicon*)assets.values[j];
2078 if( picon->id == current->id ) {
2079 picon->indexable = current;
2085 // Create new listitem
2087 AssetPicon *picon = new AssetPicon(mwindow,
2089 new_assets.append(picon);
2093 // Synchronize nested EDLs
2094 for( int i=0; i<mwindow->edl->nested_edls.size(); ++i ) {
2096 EDL *nested_edl = mwindow->edl->nested_edls[i];
2098 // Look for asset in existing listitems
2099 for( int j=0; j<assets.total && !exists; ++j ) {
2100 AssetPicon *picon = (AssetPicon*)assets.values[j];
2102 if( picon->id == nested_edl->id ) {
2103 picon->indexable = nested_edl;
2109 // Create new listitem
2111 AssetPicon *picon = new AssetPicon(mwindow,
2112 this, (Indexable*)nested_edl);
2113 new_assets.append(picon);
2116 mwindow->gui->unlock_window();
2118 for( int i=0; i<new_assets.size(); ++i ) {
2119 AssetPicon *picon = new_assets[i];
2120 picon->create_objects();
2121 if( picon->indexable )
2122 picon->foldernum = AW_MEDIA_FOLDER;
2123 else if( picon->edl )
2124 picon->foldernum = AW_CLIP_FOLDER;
2125 assets.append(picon);
2128 mwindow->gui->lock_window();
2129 mwindow->gui->default_message();
2130 mwindow->gui->unlock_window();
2132 for( int i = assets.size() - 1; i >= 0; i-- ) {
2133 AssetPicon *picon = (AssetPicon*)assets.get(i);
2134 if( !picon->in_use ) {
2136 assets.remove_number(i);
2139 if( picon->indexable && picon->indexable->is_asset ) {
2140 Asset *asset = (Asset *)picon->indexable;
2142 picon->comments_time = !stat(asset->path, &st) ? st.st_mtime : 0;
2143 picon->comments_rate = asset->get_frame_rate();
2144 picon->comments_ffmt = asset->format == FILE_FFMPEG ? '=' : '-';
2145 picon->comments_type = asset->format == FILE_FFMPEG ?
2146 asset->vcodec : File::formattostr(asset->format);
2151 void AWindowGUI::update_picon(Indexable *indexable)
2154 for( int i = 0; i < assets.total; i++ ) {
2155 AssetPicon *picon = (AssetPicon*)assets.values[i];
2156 if( picon->indexable == indexable ||
2157 picon->edl == (EDL *)indexable ) {
2158 char name[BCTEXTLEN];
2160 fs.extract_name(name, indexable->path);
2161 picon->set_text(name);
2162 vicon = picon->vicon;
2167 stop_vicon_drawing();
2168 vicon->clear_images();
2169 vicon->reset(indexable->get_frame_rate());
2170 start_vicon_drawing();
2174 void AWindowGUI::sort_assets()
2176 folder_lock->lock("AWindowGUI::sort_assets");
2177 switch( mwindow->edl->session->awindow_folder ) {
2178 case AW_AEFFECT_FOLDER:
2179 sort_picons(&aeffects);
2181 case AW_VEFFECT_FOLDER:
2182 sort_picons(&veffects);
2184 case AW_ATRANSITION_FOLDER:
2185 sort_picons(&atransitions);
2187 case AW_VTRANSITION_FOLDER:
2188 sort_picons(&vtransitions);
2190 case AW_LABEL_FOLDER:
2191 sort_picons(&labellist);
2194 sort_picons(&assets);
2198 asset_list->update_format(asset_list->get_format(), 0);
2199 folder_lock->unlock();
2203 void AWindowGUI::sort_folders()
2205 folder_lock->lock("AWindowGUI::update_assets");
2206 // folder_list->collapse_recursive(&folders, 0);
2207 folder_list->set_autoplacement(&folders, 0, 1);
2208 sort_picons(&folders);
2209 folder_list->update_format(folder_list->get_format(), 0);
2210 folder_lock->unlock();
2214 EDL *AWindowGUI::collect_proxy(Asset *proxy_asset)
2216 char path[BCTEXTLEN];
2217 int proxy_scale = mwindow->edl->session->proxy_scale;
2218 ProxyRender::from_proxy_path(path, proxy_asset, proxy_scale);
2219 Indexable *unproxy_idxbl =
2220 proxy_asset->proxy_edl ?
2221 (Indexable *) mwindow->edl->get_nested_edl(path) :
2222 (Indexable *) mwindow->edl->assets->get_asset(path);
2223 if( !unproxy_idxbl || !unproxy_idxbl->get_video_layers() ) return 0;
2224 // make a clip from proxy video tracks and unproxy audio tracks
2225 EDL *proxy_edl = new EDL(mwindow->edl);
2226 proxy_edl->create_objects();
2227 proxy_edl->set_path(proxy_asset->path);
2228 FileSystem fs; fs.extract_name(path, proxy_asset->path);
2229 strcpy(proxy_edl->local_session->clip_title, path);
2230 strcpy(proxy_edl->local_session->clip_notes, _("Proxy clip"));
2231 proxy_edl->session->video_tracks = proxy_asset->layers;
2232 proxy_edl->session->audio_tracks = unproxy_idxbl->get_audio_channels();
2233 proxy_edl->create_default_tracks();
2234 double length = proxy_asset->frame_rate > 0 ?
2235 ( proxy_asset->video_length >= 0 ?
2236 ( proxy_asset->video_length / proxy_asset->frame_rate ) :
2237 ( proxy_edl->session->si_useduration ?
2238 proxy_edl->session->si_duration :
2239 1.0 / proxy_asset->frame_rate ) ) :
2240 1.0 / proxy_edl->session->frame_rate;
2241 Track *current = proxy_edl->tracks->first;
2242 for( int vtrack=0; current; current=NEXT ) {
2243 if( current->data_type != TRACK_VIDEO ) continue;
2244 current->insert_asset(proxy_asset, 0, length, 0, vtrack++);
2246 int64_t samples = unproxy_idxbl->get_audio_samples();
2247 int sample_rate = unproxy_idxbl->get_sample_rate();
2248 length = sample_rate > 0 ? (double)samples / sample_rate : 0;
2249 current = proxy_edl->tracks->first;
2250 for( int atrack=0; current; current=NEXT ) {
2251 if( current->data_type != TRACK_AUDIO ) continue;
2252 Asset *asset = unproxy_idxbl->is_asset ? (Asset *)unproxy_idxbl : 0;
2253 EDL *nested_edl = unproxy_idxbl->is_asset ? 0 : (EDL *)unproxy_idxbl;
2254 current->insert_asset(asset, nested_edl, length, 0, atrack++);
2256 proxy_edl->folder_no = AW_PROXY_FOLDER;
2261 void AWindowGUI::collect_assets(int proxy)
2263 mwindow->session->drag_assets->remove_all();
2264 mwindow->session->drag_clips->remove_all();
2265 int i = 0; AssetPicon *result;
2266 while( (result = (AssetPicon*)asset_list->get_selection(0, i++)) != 0 ) {
2267 Indexable *indexable = result->indexable;
2268 if( proxy && indexable && indexable->is_asset &&
2269 indexable->folder_no == AW_PROXY_FOLDER ) {
2270 EDL *drag_edl = collect_proxy((Asset*)indexable);
2271 if( drag_edl ) mwindow->session->drag_clips->append(drag_edl);
2275 mwindow->session->drag_assets->append(indexable);
2279 mwindow->session->drag_clips->append(result->edl);
2285 void AWindowGUI::copy_picons(AssetPicon *picon, ArrayList<BC_ListBoxItem*> *src)
2287 // Remove current pointers
2288 ArrayList<BC_ListBoxItem*> *dst = displayed_assets;
2289 dst[0].remove_all();
2290 dst[1].remove_all_objects();
2292 AWindowFolderSubItems *sub_items = picon ? picon->sub_items : 0;
2293 int folder = mwindow->edl->session->awindow_folder;
2294 BinFolder *bin_folder = folder < AWINDOW_USER_FOLDERS ? 0 :
2295 mwindow->edl->get_folder(folder);
2297 // Create new pointers
2298 for( int i = 0; i < src->total; i++ ) {
2299 int visible = folder >= AW_CLIP_FOLDER ? 0 : 1;
2300 picon = (AssetPicon*)src->values[i];
2301 picon->sort_key = -1;
2302 if( !visible && bin_folder ) {
2303 Indexable *idxbl = bin_folder->is_clips ? (Indexable *)picon->edl :
2304 picon->indexable ? picon->indexable :
2305 picon->edl ? picon->edl->get_proxy_asset() : 0;
2307 picon->sort_key = mwindow->edl->folders.matches_indexable(folder, idxbl);
2308 if( picon->sort_key < 0 ) continue;
2312 if( !visible && picon->indexable && picon->indexable->folder_no == folder )
2314 if( !visible && picon->edl && picon->edl->folder_no == folder )
2316 if( visible && sub_items ) {
2317 if( !sub_items->matches(picon->get_text()) )
2321 const char *text = search_text->get_text();
2322 if( text && text[0] )
2323 visible = bstrcasestr(picon->get_text(), text) ? 1 : 0;
2325 if( visible && picon->vicon && picon->vicon->hidden )
2326 picon->vicon->hidden = 0;
2328 BC_ListBoxItem *item2, *item1;
2329 dst[0].append(item1 = picon);
2331 dst[1].append(item2 = new BC_ListBoxItem(picon->edl->local_session->clip_notes));
2334 dst[1].append(item2 = new BC_ListBoxItem(picon->label->textstr));
2335 else if( picon->comments_time ) {
2336 char date_time[BCSTRLEN];
2337 struct tm stm; localtime_r(&picon->comments_time, &stm);
2338 sprintf(date_time,"%04d.%02d.%02d %02d:%02d:%02d @%0.2f %c%s",
2339 stm.tm_year+1900, stm.tm_mon+1, stm.tm_mday,
2340 stm.tm_hour, stm.tm_min, stm.tm_sec,
2341 picon->comments_rate, picon->comments_ffmt,
2342 picon->comments_type);
2343 dst[1].append(item2 = new BC_ListBoxItem(date_time));
2346 dst[1].append(item2 = new BC_ListBoxItem(""));
2347 item1->set_autoplace_text(1); item1->set_autoplace_icon(1);
2348 item2->set_autoplace_text(1); item2->set_autoplace_icon(1);
2353 void AWindowGUI::sort_picons(ArrayList<BC_ListBoxItem*> *src)
2355 int done = 0, changed = 0;
2358 for( int i=0; i<src->total-1; ++i ) {
2359 AssetPicon *item1 = (AssetPicon *)src->values[i];
2360 AssetPicon *item2 = (AssetPicon *)src->values[i + 1];
2361 double v = item2->sort_key - item1->sort_key;
2362 if( v > 0 ) continue;
2364 const char *cp1 = item1->get_text();
2365 const char *bp1 = strrchr(cp1, '/');
2366 if( bp1 ) cp1 = bp1 + 1;
2367 const char *cp2 = item2->get_text();
2368 const char *bp2 = strrchr(cp2, '/');
2369 if( bp2 ) cp2 = bp2 + 1;
2370 if( strcmp(cp2, cp1) >= 0 ) continue;
2372 src->values[i + 1] = item1;
2373 src->values[i] = item2;
2374 done = 0; changed = 1;
2378 for( int i=0; i<src->total; ++i ) {
2379 AssetPicon *item = (AssetPicon *)src->values[i];
2380 item->set_autoplace_icon(1);
2381 item->set_autoplace_text(1);
2386 void AWindowGUI::filter_displayed_assets()
2388 //allow_iconlisting = 1;
2389 asset_titles[0] = C_("Title");
2390 asset_titles[1] = _("Comments");
2391 AssetPicon *picon = 0;
2392 int selected_folder = mwindow->edl->session->awindow_folder;
2393 // Ensure the current folder icon is highlighted
2394 for( int i = 0; i < folders.total; i++ ) {
2395 AssetPicon *folder_item = (AssetPicon *)folders.values[i];
2396 int selected = folder_item->foldernum == selected_folder ? 1 : 0;
2397 folder_item->set_selected(selected);
2398 if( selected ) picon = folder_item;
2401 ArrayList<BC_ListBoxItem*> *src = &assets;
2402 switch( selected_folder ) {
2403 case AW_AEFFECT_FOLDER: src = &aeffects; break;
2404 case AW_VEFFECT_FOLDER: src = &veffects; break;
2405 case AW_ATRANSITION_FOLDER: src = &atransitions; break;
2406 case AW_VTRANSITION_FOLDER: src = &vtransitions; break;
2407 case AW_LABEL_FOLDER: src = &labellist;
2408 asset_titles[0] = _("Time Stamps");
2409 asset_titles[1] = C_("Title");
2410 //allow_iconlisting = 0;
2413 copy_picons(picon, src);
2417 void AWindowGUI::update_assets()
2419 stop_vicon_drawing();
2420 folder_lock->lock("AWindowGUI::update_assets");
2421 update_folder_list();
2422 update_asset_list();
2423 labellist.remove_all_objects();
2424 create_label_folder();
2426 if( displayed_folder != mwindow->edl->session->awindow_folder )
2427 search_text->clear();
2428 vicon_thread->hide_vicons();
2429 filter_displayed_assets();
2430 folder_lock->unlock();
2432 if( mwindow->edl->session->folderlist_format != folder_list->get_format() ) {
2433 folder_list->update_format(mwindow->edl->session->folderlist_format, 0);
2435 int folder_xposition = folder_list->get_xposition();
2436 int folder_yposition = folder_list->get_yposition();
2437 folder_list->update(&folders, 0, 0, 1, folder_xposition, folder_yposition, -1);
2439 if( mwindow->edl->session->assetlist_format != asset_list->get_format() ) {
2440 asset_list->update_format(mwindow->edl->session->assetlist_format, 0);
2442 int asset_xposition = asset_list->get_xposition();
2443 int asset_yposition = asset_list->get_yposition();
2444 if( displayed_folder != mwindow->edl->session->awindow_folder ) {
2445 displayed_folder = mwindow->edl->session->awindow_folder;
2446 asset_xposition = asset_yposition = 0;
2448 asset_list->update(displayed_assets, asset_titles,
2449 mwindow->edl->session->asset_columns, ASSET_COLUMNS,
2450 asset_xposition, asset_yposition, -1, 0);
2451 asset_list->center_selection();
2454 start_vicon_drawing();
2458 void AWindowGUI::update_effects()
2460 aeffects.remove_all_objects();
2461 create_persistent_folder(&aeffects, 1, 0, 1, 0);
2462 veffects.remove_all_objects();
2463 create_persistent_folder(&veffects, 0, 1, 1, 0);
2464 atransitions.remove_all_objects();
2465 create_persistent_folder(&atransitions, 1, 0, 0, 1);
2466 vtransitions.remove_all_objects();
2467 create_persistent_folder(&vtransitions, 0, 1, 0, 1);
2470 int AWindowGUI::drag_motion()
2472 if( get_hidden() ) return 0;
2478 int AWindowGUI::drag_stop()
2480 if( get_hidden() ) return 0;
2484 Indexable* AWindowGUI::selected_asset()
2486 AssetPicon *picon = (AssetPicon*)asset_list->get_selection(0, 0);
2487 return picon ? picon->indexable : 0;
2490 PluginServer* AWindowGUI::selected_plugin()
2492 AssetPicon *picon = (AssetPicon*)asset_list->get_selection(0, 0);
2493 return picon ? picon->plugin : 0;
2496 AssetPicon* AWindowGUI::selected_folder()
2498 AssetPicon *picon = (AssetPicon*)folder_list->get_selection(0, 0);
2509 AWindowDivider::AWindowDivider(MWindow *mwindow, AWindowGUI *gui, int x, int y, int w, int h)
2510 : BC_SubWindow(x, y, w, h)
2512 this->mwindow = mwindow;
2515 AWindowDivider::~AWindowDivider()
2519 int AWindowDivider::button_press_event()
2521 if( is_event_win() && cursor_inside() ) {
2522 mwindow->session->current_operation = DRAG_PARTITION;
2528 int AWindowDivider::cursor_motion_event()
2530 if( mwindow->session->current_operation == DRAG_PARTITION ) {
2532 int wmax = mwindow->session->awindow_w - mwindow->theme->adivider_w - wmin;
2533 int fw = gui->get_relative_cursor_x();
2534 if( fw > wmax ) fw = wmax;
2535 if( fw < wmin ) fw = wmin;
2536 mwindow->session->afolders_w = fw;
2537 mwindow->theme->get_awindow_sizes(gui);
2538 gui->reposition_objects();
2544 int AWindowDivider::button_release_event()
2546 if( mwindow->session->current_operation == DRAG_PARTITION ) {
2547 mwindow->session->current_operation = NO_OPERATION;
2558 AWindowFolders::AWindowFolders(MWindow *mwindow, AWindowGUI *gui, int x, int y, int w, int h)
2559 : BC_ListBox(x, y, w, h,
2560 mwindow->edl->session->folderlist_format == FOLDERS_ICONS ?
2561 LISTBOX_ICONS : LISTBOX_TEXT,
2562 &gui->folders, // Each column has an ArrayList of BC_ListBoxItems.
2563 0, // Titles for columns. Set to 0 for no titles
2564 0, // width of each column
2565 1, // Total columns.
2566 0, // Pixel of top of window.
2567 0, // If this listbox is a popup window
2568 LISTBOX_SINGLE, // Select one item or multiple items
2569 ICON_TOP, // Position of icon relative to text of each item
2572 this->mwindow = mwindow;
2579 AWindowFolders::~AWindowFolders()
2583 int AWindowFolders::selection_changed()
2585 AWindowFolderItem *item0 = (AWindowFolderItem*)get_selection(0, 0);
2586 AWindowFolderItem *item1 = (AWindowFolderItem*)get_selection(0, 1);
2587 // prefer expanded entry
2588 AWindowFolderItem *item = item1 ? item1 : item0;
2589 if( item0 && item1 && last_item0 == item0 && last_item1 == item1 ) {
2590 item1->set_selected(0);
2597 AssetPicon *picon = item->get_picon();
2598 picon->sub_items = (AWindowFolderSubItems*)(!item->parent ? 0 : item);
2600 gui->stop_vicon_drawing();
2602 if( get_button_down() && get_buttonpress() == RIGHT_BUTTON ) {
2603 gui->folderlist_menu->update_titles();
2604 gui->folderlist_menu->activate_menu();
2607 mwindow->edl->session->awindow_folder = picon->foldernum;
2608 gui->asset_list->draw_background();
2609 gui->async_update_assets();
2611 gui->start_vicon_drawing();
2616 int AWindowFolders::button_press_event()
2618 gui->hide_tip_info();
2619 int result = BC_ListBox::button_press_event();
2622 if( get_buttonpress() == RIGHT_BUTTON &&
2623 is_event_win() && cursor_inside() ) {
2624 gui->folderlist_menu->update_titles();
2625 gui->folderlist_menu->activate_menu();
2633 int AWindowFolders::drag_stop()
2636 if( get_hidden() ) return 0;
2637 if( mwindow->session->current_operation == DRAG_ASSET &&
2638 gui->folder_list->cursor_above() ) { // check user folder
2639 int item_no = gui->folder_list->get_cursor_data_item_no();
2640 AssetPicon *picon = (AssetPicon *)(item_no < 0 ? 0 : gui->folders[item_no]);
2641 if( picon && picon->foldernum >= AWINDOW_USER_FOLDERS ) {
2642 BinFolder *folder = mwindow->edl->get_folder(picon->foldernum);
2643 ArrayList<Indexable *> *drags = folder->is_clips ?
2644 ((ArrayList<Indexable *> *)mwindow->session->drag_clips) :
2645 ((ArrayList<Indexable *> *)mwindow->session->drag_assets);
2646 if( folder && drags && !folder->add_patterns(drags, shift_down()) )
2648 mwindow->session->current_operation = ::NO_OPERATION;
2655 AWindowFolderSubItems::AWindowFolderSubItems(AWindowFolderItem *parent, const char *text)
2656 : AWindowFolderItem(text)
2658 this->parent = parent;
2661 int AWindowFolders::load_expanders()
2663 char expanders_path[BCTEXTLEN];
2664 mwindow->create_defaults_path(expanders_path, EXPANDERS_FILE);
2665 FILE *fp = fopen(expanders_path, "r");
2667 snprintf(expanders_path, sizeof(expanders_path), "%s/%s",
2668 File::get_cindat_path(), EXPANDERS_FILE);
2669 char *cp = strrchr(expanders_path,'.');
2670 if( cp ) strcpy(cp+1, mwindow->cin_lang);
2671 fp = fopen(expanders_path, "r");
2674 snprintf(expanders_path, sizeof(expanders_path), "%s/%s",
2675 File::get_cindat_path(), EXPANDERS_FILE);
2676 fp = fopen(expanders_path, "r");
2679 const char tab = '\t';
2680 char line[BCTEXTLEN]; line[0] = 0;
2681 AWindowFolderItem *item = 0, *parent;
2682 AWindowFolderSubItems *sub_items = 0;
2684 while( fgets(line,sizeof(line),fp) ) {
2685 if( line[0] == '#' ) continue;
2686 int i = strlen(line);
2687 if( i > 0 && line[i-1] == '\n' ) line[--i] = 0;
2688 if( i == 0 ) continue;
2690 for( char *cp=line; *cp==tab; ++cp ) ++i;
2692 int i = gui->folders.size();
2694 AssetPicon *folder = (AssetPicon *)gui->folders[i];
2695 if( !strcmp(folder->get_text(),_(line)) ) break;
2697 item = (AWindowFolderItem*)(i >= 0 ? gui->folders[i] : 0);
2702 if( i > k+1 ) continue;
2704 if( line[i] != '-' && sub_items ) {
2705 sub_items->names.append(cstrdup(_(&line[i])));
2713 item = item->parent;
2716 parent = item->parent;
2718 ArrayList<BC_ListBoxItem*> *sublist = parent->get_sublist();
2719 if( !sublist ) sublist = parent->new_sublist(1);
2720 sub_items = new AWindowFolderSubItems(parent, &line[i]);
2721 sublist->append(item = sub_items);
2728 AWindowAssets::AWindowAssets(MWindow *mwindow, AWindowGUI *gui, int x, int y, int w, int h)
2729 : BC_ListBox(x, y, w, h, !gui->allow_iconlisting ? LISTBOX_TEXT :
2730 mwindow->edl->session->assetlist_format == ASSETS_ICONS ? LISTBOX_ICONS :
2731 mwindow->edl->session->assetlist_format == ASSETS_ICONS_PACKED ? LISTBOX_ICONS_PACKED :
2732 mwindow->edl->session->assetlist_format == ASSETS_ICON_LIST ? LISTBOX_ICON_LIST :
2734 &gui->assets, // Each column has an ArrayList of BC_ListBoxItems.
2735 gui->asset_titles,// Titles for columns. Set to 0 for no titles
2736 mwindow->edl->session->asset_columns, // width of each column
2737 1, // Total columns.
2738 0, // Pixel of top of window.
2739 0, // If this listbox is a popup window
2740 LISTBOX_MULTIPLE, // Select one item or multiple items
2741 ICON_TOP, // Position of icon relative to text of each item
2742 -1) // Allow drags, require shift for scrolling
2744 this->mwindow = mwindow;
2746 this->info_tip = -1;
2748 set_scroll_stretch(1, 1);
2751 AWindowAssets::~AWindowAssets()
2755 int AWindowAssets::button_press_event()
2758 AssetVIconThread *avt = gui->vicon_thread;
2759 if( avt->draw_mode != ASSET_VIEW_NONE && is_event_win() ) {
2760 int dir = 1, button = get_buttonpress();
2762 case WHEEL_DOWN: dir = -1; // fall thru
2764 int x = get_cursor_x(), y = get_cursor_y();
2765 if( avt->cursor_inside(x, y) && avt->view_win )
2766 avt->zoom_scale(dir);
2771 int result = BC_ListBox::button_press_event();
2773 if( !result && get_buttonpress() == RIGHT_BUTTON &&
2774 is_event_win() && cursor_inside() ) {
2775 BC_ListBox::deactivate_selection();
2776 int folder = mwindow->edl->session->awindow_folder;
2778 case AW_AEFFECT_FOLDER:
2779 case AW_VEFFECT_FOLDER:
2780 case AW_ATRANSITION_FOLDER:
2781 case AW_VTRANSITION_FOLDER:
2782 gui->effectlist_menu->update();
2783 gui->effectlist_menu->activate_menu();
2785 case AW_LABEL_FOLDER:
2786 gui->labellist_menu->update();
2787 gui->labellist_menu->activate_menu();
2789 case AW_CLIP_FOLDER:
2790 gui->cliplist_menu->update();
2791 gui->cliplist_menu->activate_menu();
2793 case AW_PROXY_FOLDER:
2794 gui->proxylist_menu->update();
2795 gui->proxylist_menu->activate_menu();
2798 case AW_MEDIA_FOLDER: {
2799 int shots = folder==AW_MEDIA_FOLDER || folder>=AWINDOW_USER_FOLDERS;
2800 gui->assetlist_menu->update_titles(shots);
2801 gui->assetlist_menu->activate_menu();
2811 int AWindowAssets::handle_event()
2813 AssetPicon *asset_picon = (AssetPicon *)get_selection(0, 0);
2814 if( !asset_picon ) return 0;
2815 Indexable *picon_idxbl = asset_picon->indexable;
2816 EDL *picon_edl = asset_picon->edl;
2818 VWindow *vwindow = 0;
2819 switch( mwindow->edl->session->awindow_folder ) {
2820 case AW_AEFFECT_FOLDER:
2821 case AW_VEFFECT_FOLDER:
2822 case AW_ATRANSITION_FOLDER:
2823 case AW_VTRANSITION_FOLDER: return 1;
2824 case AW_PROXY_FOLDER:
2825 proxy = 1; // fall thru
2827 if( mwindow->vwindows.size() > DEFAULT_VWINDOW )
2828 vwindow = mwindow->vwindows.get(DEFAULT_VWINDOW);
2831 if( !vwindow || !vwindow->is_running() ) return 1;
2832 if( proxy && picon_idxbl && picon_idxbl->is_asset ) {
2833 picon_edl = gui->collect_proxy((Asset*)picon_idxbl);
2837 if( picon_idxbl ) vwindow->change_source(picon_idxbl);
2838 else if( picon_edl ) vwindow->change_source(picon_edl);
2842 int AWindowAssets::selection_changed()
2844 // Show popup window
2846 int folder = mwindow->edl->session->awindow_folder;
2847 if( get_button_down() && get_buttonpress() == RIGHT_BUTTON &&
2848 (item = (AssetPicon*)get_selection(0, 0)) ) {
2850 case AW_AEFFECT_FOLDER:
2851 case AW_VEFFECT_FOLDER:
2852 case AW_ATRANSITION_FOLDER:
2853 case AW_VTRANSITION_FOLDER:
2854 gui->effectlist_menu->update();
2855 gui->effectlist_menu->activate_menu();
2857 case AW_LABEL_FOLDER:
2858 if( !item->label ) break;
2859 gui->label_menu->activate_menu();
2861 case AW_CLIP_FOLDER:
2862 if( !item->indexable && !item->edl ) break;
2863 gui->clip_menu->update();
2864 gui->clip_menu->activate_menu();
2866 case AW_PROXY_FOLDER:
2867 if( !item->indexable && !item->edl ) break;
2868 gui->proxy_menu->update();
2869 gui->proxy_menu->activate_menu();
2872 if( !item->indexable && !item->edl ) break;
2873 gui->asset_menu->update();
2874 gui->asset_menu->activate_menu();
2878 deactivate_selection();
2880 else if( get_button_down() && !gui->play_off &&
2881 mwindow->edl->session->assetlist_format != ASSETS_TEXT ) {
2882 item = (AssetPicon*)get_selection(0, 0);
2883 if( item && !get_selection(0, 1) ) {
2885 case AW_MEDIA_FOLDER:
2886 case AW_PROXY_FOLDER:
2887 case AWINDOW_USER_FOLDERS:
2888 if( get_buttonpress() == LEFT_BUTTON ||
2889 get_buttonpress() == MIDDLE_BUTTON ) {
2890 AssetVIcon *vicon = 0;
2891 AssetVIconThread *avt = gui->vicon_thread;
2892 if( !avt->vicon && gui->vicon_drawing != AVICON_NO_PLAY )
2893 vicon = item->vicon;
2894 int draw_mode = !vicon ?
2896 get_buttonpress() == MIDDLE_BUTTON ?
2897 ASSET_VIEW_MEDIA_MAP : ASSET_VIEW_MEDIA;
2898 avt->set_view_popup(vicon, draw_mode);
2901 case AW_CLIP_FOLDER:
2902 if( get_buttonpress() == LEFT_BUTTON ) {
2903 AssetVIcon *vicon = 0;
2904 AssetVIconThread *avt = gui->vicon_thread;
2905 if( !avt->vicon && gui->vicon_drawing != AVICON_NO_PLAY )
2906 vicon = item->vicon;
2907 gui->vicon_thread->set_view_popup(vicon, ASSET_VIEW_ICON);
2913 gui->vicon_thread->set_view_popup(0);
2914 if( gui->vicon_drawing != AVICON_FULL_PLAY )
2915 gui->stop_vicon_drawing();
2921 void AWindowAssets::draw_background()
2923 clear_box(0,0,get_w(),get_h(),get_bg_surface());
2924 set_color(BC_WindowBase::get_resources()->audiovideo_color);
2925 set_font(LARGEFONT);
2926 int folder = mwindow->edl->session->awindow_folder;
2927 const char *title = mwindow->edl->get_folder_name(folder);
2928 draw_text(get_w() - get_text_width(LARGEFONT, title) - xS(4), yS(30),
2929 title, -1, get_bg_surface());
2932 int AWindowAssets::drag_start_event()
2934 gui->vicon_thread->set_view_popup(0);
2935 int collect_pluginservers = 0;
2936 int collect_assets = 0, proxy = 0;
2938 if( BC_ListBox::drag_start_event() ) {
2939 switch( mwindow->edl->session->awindow_folder ) {
2940 case AW_AEFFECT_FOLDER:
2941 mwindow->session->current_operation = DRAG_AEFFECT;
2942 collect_pluginservers = 1;
2944 case AW_VEFFECT_FOLDER:
2945 mwindow->session->current_operation = DRAG_VEFFECT;
2946 collect_pluginservers = 1;
2948 case AW_ATRANSITION_FOLDER:
2949 mwindow->session->current_operation = DRAG_ATRANSITION;
2950 collect_pluginservers = 1;
2952 case AW_VTRANSITION_FOLDER:
2953 mwindow->session->current_operation = DRAG_VTRANSITION;
2954 collect_pluginservers = 1;
2956 case AW_LABEL_FOLDER:
2959 case AW_PROXY_FOLDER:
2960 proxy = 1; // fall thru
2961 case AW_MEDIA_FOLDER:
2963 mwindow->session->current_operation = DRAG_ASSET;
2968 if( collect_pluginservers ) {
2970 mwindow->session->drag_pluginservers->remove_all();
2973 AssetPicon *result = (AssetPicon*)get_selection(0, i++);
2974 if( !result ) break;
2976 mwindow->session->drag_pluginservers->append(result->plugin);
2980 if( collect_assets ) {
2981 gui->collect_assets(proxy);
2989 int AWindowAssets::drag_motion_event()
2991 BC_ListBox::drag_motion_event();
2994 mwindow->gui->lock_window("AWindowAssets::drag_motion_event");
2995 mwindow->gui->drag_motion();
2996 mwindow->gui->unlock_window();
2998 for( int i = 0; i < mwindow->vwindows.size(); i++ ) {
2999 VWindow *vwindow = mwindow->vwindows.get(i);
3000 if( !vwindow->is_running() ) continue;
3001 vwindow->gui->lock_window("AWindowAssets::drag_motion_event");
3002 vwindow->gui->drag_motion();
3003 vwindow->gui->unlock_window();
3006 mwindow->cwindow->gui->lock_window("AWindowAssets::drag_motion_event");
3007 mwindow->cwindow->gui->drag_motion();
3008 mwindow->cwindow->gui->unlock_window();
3010 lock_window("AWindowAssets::drag_motion_event");
3011 if( mwindow->session->current_operation == DRAG_ASSET &&
3012 gui->folder_list->cursor_above() ) { // highlight user folder
3013 BC_ListBoxItem *item = 0;
3014 int item_no = gui->folder_list->get_cursor_data_item_no(&item);
3015 if( item_no >= 0 ) {
3016 AssetPicon *folder = (AssetPicon *)gui->folders[item_no];
3017 if( folder->foldernum < AWINDOW_USER_FOLDERS ) item_no = -1;
3020 item_no = gui->folder_list->item_to_index(&gui->folders, item);
3021 int folder_xposition = gui->folder_list->get_xposition();
3022 int folder_yposition = gui->folder_list->get_yposition();
3023 gui->folder_list->update(&gui->folders, 0, 0, 1,
3024 folder_xposition, folder_yposition, item_no, 0, 1);
3029 int AWindowAssets::drag_stop_event()
3033 result = gui->drag_stop();
3038 mwindow->gui->lock_window("AWindowAssets::drag_stop_event");
3039 result = mwindow->gui->drag_stop();
3040 mwindow->gui->unlock_window();
3044 for( int i = 0; !result && i < mwindow->vwindows.size(); i++ ) {
3045 VWindow *vwindow = mwindow->vwindows.get(i);
3046 if( !vwindow ) continue;
3047 if( !vwindow->is_running() ) continue;
3048 if( vwindow->gui->is_hidden() ) continue;
3049 vwindow->gui->lock_window("AWindowAssets::drag_stop_event");
3050 if( vwindow->gui->cursor_above() &&
3051 vwindow->gui->get_cursor_over_window() ) {
3052 result = vwindow->gui->drag_stop();
3054 vwindow->gui->unlock_window();
3059 mwindow->cwindow->gui->lock_window("AWindowAssets::drag_stop_event");
3060 result = mwindow->cwindow->gui->drag_stop();
3061 mwindow->cwindow->gui->unlock_window();
3064 lock_window("AWindowAssets::drag_stop_event");
3066 result = gui->folder_list->drag_stop();
3071 get_drag_popup()->set_animation(0);
3073 BC_ListBox::drag_stop_event();
3074 // since NO_OPERATION is also defined in listbox, we have to reach for global scope...
3075 mwindow->session->current_operation = ::NO_OPERATION;
3080 int AWindowAssets::column_resize_event()
3082 mwindow->edl->session->asset_columns[0] = get_column_width(0);
3083 mwindow->edl->session->asset_columns[1] = get_column_width(1);
3087 int AWindowAssets::cursor_enter_event()
3089 int ret = BC_ListBox::cursor_enter_event();
3090 switch( gui->vicon_drawing ) {
3091 case AVICON_FULL_PLAY:
3092 gui->start_vicon_drawing();
3094 case AVICON_MOUSE_OVER:
3095 case AVICON_SRC_TARGET:
3096 case AVICON_NO_PLAY:
3103 int AWindowAssets::cursor_leave_event()
3106 if( !is_event_win() ) return 0;
3107 if( !gui->vicon_thread->viewing )
3108 gui->stop_vicon_drawing();
3109 return BC_ListBox::cursor_leave_event();
3112 int AWindowAssets::focus_out_event()
3114 gui->stop_vicon_drawing();
3115 gui->vicon_thread->set_view_popup(0);
3116 return BC_ListBox::focus_out_event();
3119 void AWindowAssets::update_vicon_area()
3121 int x0 = 0, x1 = get_w();
3122 int y0 = get_title_h();
3124 if( is_highlighted() ) {
3125 x0 += LISTBOX_BORDER; x1 -= LISTBOX_BORDER;
3126 y0 += LISTBOX_BORDER; y1 -= LISTBOX_BORDER;
3128 gui->vicon_thread->set_drawing_area(x0,y0, x1,y1);
3131 int AWindowAssets::mouse_over_event(int no)
3133 AssetPicon *picon = no >= 0 && no < gui->displayed_assets[0].size() ?
3134 (AssetPicon *)gui->displayed_assets[0][no] : 0;
3135 AssetVIcon *vicon = !picon ? 0 : picon->vicon;
3136 switch( gui->vicon_drawing ) {
3137 case AVICON_FULL_PLAY:
3138 gui->vicon_thread->solo = 0;
3139 if( vicon && gui->vicon_thread->viewing )
3140 gui->vicon_thread->set_view_popup(vicon);
3142 case AVICON_MOUSE_OVER:
3144 gui->vicon_thread->solo = vicon;
3145 gui->start_vicon_drawing();
3147 case AVICON_SRC_TARGET:
3149 if( gui->vicon_thread->viewing )
3150 gui->vicon_thread->set_view_popup(vicon);
3152 case AVICON_NO_PLAY:
3156 if( no < 0 && info_tip >= 0 ) {
3159 if( gui->tip_info && no >= 0 &&
3160 info_tip != no && picon && picon->plugin ) {
3161 const char *info = picon->plugin->tip;
3162 if( !info ) info = _("No info available");
3163 show_tip_info(info, no);
3168 void AWindowAssets::show_tip_info(const char *info, int no)
3170 int tw = get_text_width(MEDIUMFONT, info) + TOOLTIP_MARGIN * 2;
3171 int th = get_text_height(MEDIUMFONT, info) + TOOLTIP_MARGIN * 2;
3172 int tx = get_w() - (tw + xS(28));
3173 int ty = get_h() - (th + yS(28));
3174 show_tooltip(info, tx, ty, tw, th);
3178 void AWindowAssets::hide_tip_info()
3185 AWindowSearchTextBox::AWindowSearchTextBox(AWindowSearchText *search_text, int x, int y, int w)
3186 : BC_TextBox(x, y, w, 1, "")
3188 this->search_text = search_text;
3191 int AWindowSearchTextBox::handle_event()
3193 return search_text->handle_event();
3196 AWindowSearchText::AWindowSearchText(MWindow *mwindow, AWindowGUI *gui, int x, int y)
3198 this->mwindow = mwindow;
3204 void AWindowSearchText::create_objects()
3208 gui->add_subwindow(text_title = new BC_Title(x1, y1, _("Search:")));
3209 x1 += text_title->get_w() + xs10;
3210 int w1 = gui->get_w() - x1 - 2*xs10;
3211 gui->add_subwindow(text_box = new AWindowSearchTextBox(this, x1, y1, w1));
3214 int AWindowSearchText::handle_event()
3216 gui->async_update_assets();
3220 int AWindowSearchText::get_w()
3222 return text_box->get_w() + text_title->get_w() + xS(10);
3225 int AWindowSearchText::get_h()
3227 return bmax(text_box->get_h(),text_title->get_h());
3230 void AWindowSearchText::reposition_window(int x, int y, int w)
3234 text_title->reposition_window(x1, y1);
3235 x1 += text_title->get_w() + xs10;
3236 int w1 = gui->get_w() - x1 - 2*xs10;
3237 text_box->reposition_window(x1, y1, w1);
3240 const char *AWindowSearchText::get_text()
3242 return text_box->get_text();
3245 void AWindowSearchText::clear()
3247 text_box->update("");
3250 AWindowDeleteDisk::AWindowDeleteDisk(MWindow *mwindow, AWindowGUI *gui, int x, int y)
3251 : BC_Button(x, y, mwindow->theme->deletedisk_data)
3253 this->mwindow = mwindow;
3255 set_tooltip(_("Delete asset from disk"));
3258 int AWindowDeleteDisk::handle_event()
3263 AWindowDeleteProject::AWindowDeleteProject(MWindow *mwindow, AWindowGUI *gui, int x, int y)
3264 : BC_Button(x, y, mwindow->theme->deleteproject_data)
3266 this->mwindow = mwindow;
3268 set_tooltip(_("Delete asset from project"));
3271 int AWindowDeleteProject::handle_event()
3276 // AWindowInfo::AWindowInfo(MWindow *mwindow, AWindowGUI *gui, int x, int y)
3277 // : BC_Button(x, y, mwindow->theme->infoasset_data)
3279 // this->mwindow = mwindow;
3281 // set_tooltip(_("Edit information on asset"));
3284 // int AWindowInfo::handle_event()
3286 // int cur_x, cur_y;
3287 // gui->get_abs_cursor(cur_x, cur_y, 0);
3288 // gui->awindow->asset_edit->edit_asset(gui->selected_asset(), cur_x, cur_y);
3292 AWindowRedrawIndex::AWindowRedrawIndex(MWindow *mwindow, AWindowGUI *gui, int x, int y)
3293 : BC_Button(x, y, mwindow->theme->redrawindex_data)
3295 this->mwindow = mwindow;
3297 set_tooltip(_("Redraw index"));
3300 int AWindowRedrawIndex::handle_event()
3305 AWindowPaste::AWindowPaste(MWindow *mwindow, AWindowGUI *gui, int x, int y)
3306 : BC_Button(x, y, mwindow->theme->pasteasset_data)
3308 this->mwindow = mwindow;
3310 set_tooltip(_("Paste asset on recordable tracks"));
3313 int AWindowPaste::handle_event()
3318 AWindowAppend::AWindowAppend(MWindow *mwindow, AWindowGUI *gui, int x, int y)
3319 : BC_Button(x, y, mwindow->theme->appendasset_data)
3321 this->mwindow = mwindow;
3323 set_tooltip(_("Append asset in new tracks"));
3326 int AWindowAppend::handle_event()
3331 AWindowView::AWindowView(MWindow *mwindow, AWindowGUI *gui, int x, int y)
3332 : BC_Button(x, y, mwindow->theme->viewasset_data)
3334 this->mwindow = mwindow;
3336 set_tooltip(_("View asset"));
3339 int AWindowView::handle_event()
3344 AddTools::AddTools(MWindow *mwindow, AWindowGUI *gui, int x, int y, const char *title)
3345 : BC_PopupMenu(x, y, title, -1, 0)
3347 this->mwindow = mwindow;
3351 void AddTools::create_objects()
3354 add_item(new AddPluginItem(this, "ffmpeg", PLUGIN_FFMPEG_ID));
3355 vis |= 1 << PLUGIN_FFMPEG_ID;
3356 add_item(new AddPluginItem(this, "ladspa", PLUGIN_LADSPA_ID));
3357 vis |= 1 << PLUGIN_LADSPA_ID;
3359 add_item(new AddPluginItem(this, "lv2", PLUGIN_LV2_ID));
3360 vis |= 1 << PLUGIN_LV2_ID;
3362 for( int i=0; i<MWindow::plugindb->size(); ++i ) {
3363 PluginServer *plugin = MWindow::plugindb->get(i);
3364 if( !plugin->audio && !plugin->video ) continue;
3365 int idx = plugin->dir_idx;
3366 uint32_t msk = 1 << idx;
3367 if( (msk & vis) != 0 ) continue;
3369 char parent[BCTEXTLEN];
3370 strcpy(parent, plugin->path);
3371 char *bp = strrchr(parent, '/');
3372 if( bp ) { *bp = 0; bp = strrchr(parent, '/'); }
3373 if( !bp ) bp = parent; else ++bp;
3374 add_item(new AddPluginItem(this, bp, idx));
3379 // plugin_dirs list from toplevel makefile include plugin_defs
3384 N_("audio_transitions")
3391 N_("video_transitions")
3394 AddPluginItem::AddPluginItem(AddTools *menu, char const *text, int idx)
3395 : BC_MenuItem(_(text))
3399 uint64_t msk = (uint64_t)1 << idx, vis = menu->gui->plugin_visibility;
3400 int chk = (msk & vis) ? 1 : 0;
3404 int AddPluginItem::handle_event()
3406 int chk = get_checked() ^ 1;
3408 uint64_t msk = (uint64_t)1 << idx, vis = menu->gui->plugin_visibility;
3409 menu->gui->plugin_visibility = chk ? vis | msk : vis & ~msk;
3410 menu->gui->update_effects();
3411 menu->gui->save_defaults(menu->mwindow->defaults);
3412 menu->gui->async_update_assets();
3416 AVIconDrawingItem::AVIconDrawingItem(AVIconDrawing *avicon, const char *text, int id)
3419 this->avicon = avicon;
3423 int AVIconDrawingItem::handle_event()
3425 for( int i=0; i<AVICON_PLAY_MODES; ++i ) {
3426 AVIconDrawingItem *item = (AVIconDrawingItem *) avicon->get_item(i);
3427 item->set_checked(id == i);
3429 AWindowGUI *agui = avicon->agui;
3431 avicon->set_text(get_text());
3432 agui->stop_vicon_drawing();
3433 agui->vicon_thread->set_view_popup(0);
3434 agui->vicon_thread->solo = 0;
3435 agui->vicon_drawing = id;
3436 agui->start_vicon_drawing();
3440 int AVIconDrawing::draw_face(int dx, int color)
3442 int ret = BC_PopupMenu::draw_face(dx, color);
3443 if( agui->play_off && agui->vicon_drawing != AVICON_NO_PLAY ) {
3444 int lx = get_margin(), ly = get_h()/2;
3445 draw_line(lx,ly, get_w()-2*lx,ly);
3450 AVIconDrawing::AVIconDrawing(AWindowGUI *agui, int x, int y, int w, const char *text)
3451 : BC_PopupMenu(x-w, y, w, text, 1, 0, 4)
3456 AVIconDrawing::~AVIconDrawing()
3460 void AVIconDrawing::create_objects()
3462 AVIconDrawingItem *item;
3463 for( int i=0; i<AVICON_PLAY_MODES; ++i ) {
3464 add_item(item = new AVIconDrawingItem(this, avicon_names[i], i));
3465 item->set_checked(agui->vicon_drawing == i);
3469 int AVIconDrawing::button_press_event()
3471 if( !is_event_win() ) return 0;
3472 if( get_buttonpress() == MIDDLE_BUTTON ) {
3473 agui->play_off = !agui->play_off ? 1 : 0;
3476 agui->start_vicon_drawing();
3479 return BC_PopupMenu::button_press_event();
3482 AWindowListFormat::AWindowListFormat(MWindow *mwindow, AWindowGUI *gui)
3483 : BC_MenuItem("","v",'v')
3485 this->mwindow = mwindow;
3489 int AWindowListFormat::handle_event()
3491 return gui->cycle_assetlist_format();
3494 void AWindowListFormat::update()
3496 EDLSession *session = mwindow->edl->session;
3497 const char *text = 0;
3498 switch( session->assetlist_format ) {
3500 text = _("Display icons");
3503 text = _("Display icons packed");
3505 case ASSETS_ICONS_PACKED:
3506 text = _("Display icon list");
3508 case ASSETS_ICON_LIST:
3509 text = _("Display text");
3515 AWindowListSort::AWindowListSort(MWindow *mwindow, AWindowGUI *gui)
3516 : BC_MenuItem(_("Sort items"))
3518 this->mwindow = mwindow;
3522 int AWindowListSort::handle_event()
3528 AssetSelectUsedItem::AssetSelectUsedItem(AssetSelectUsed *select_used, const char *text, int action)
3531 this->select_used = select_used;
3532 this->action = action;
3535 int AssetSelectUsedItem::handle_event()
3537 MWindow *mwindow = select_used->mwindow;
3538 AWindowGUI *gui = select_used->gui;
3539 AWindowAssets *asset_list = gui->asset_list;
3540 ArrayList<BC_ListBoxItem*> *data = gui->displayed_assets;
3545 asset_list->set_all_selected(data, action==SELECT_ALL ? 1 : 0);
3549 asset_list->set_all_selected(data, 0);
3550 for( int i = 0; i < data->total; i++ ) {
3551 AssetPicon *picon = (AssetPicon*)data->values[i];
3552 Indexable *idxbl = picon->indexable ? picon->indexable :
3553 picon->edl ? picon->edl->get_proxy_asset() : 0;
3554 int used = idxbl && mwindow->edl->in_use(idxbl) ? 1 : 0;
3555 asset_list->set_selected(data, i, action==SELECT_USED ? used : !used);
3560 int asset_xposition = asset_list->get_xposition();
3561 int asset_yposition = asset_list->get_yposition();
3562 asset_list->update(gui->displayed_assets, gui->asset_titles,
3563 mwindow->edl->session->asset_columns, ASSET_COLUMNS,
3564 asset_xposition, asset_yposition, -1, 0);
3565 asset_list->center_selection();
3569 AssetSelectUsed::AssetSelectUsed(MWindow *mwindow, AWindowGUI *gui)
3570 : BC_MenuItem(_("Select"))
3572 this->mwindow = mwindow;