9769b99847f940811adaeacc8c5a47c32fd8901e
[goodguy/history.git] / cinelerra-5.1 / cinelerra / awindowgui.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "asset.h"
23 #include "assetedit.h"
24 #include "assetpopup.h"
25 #include "assets.h"
26 #include "awindowgui.h"
27 #include "awindow.h"
28 #include "bccmodels.h"
29 #include "bcsignals.h"
30 #include "bchash.h"
31 #include "cache.h"
32 #include "cstrdup.h"
33 #include "clip.h"
34 #include "clippopup.h"
35 #include "cursors.h"
36 #include "cwindowgui.h"
37 #include "cwindow.h"
38 #include "edl.h"
39 #include "edlsession.h"
40 #include "effectlist.h"
41 #include "file.h"
42 #include "filesystem.h"
43 #include "folderlistmenu.h"
44 #include "indexable.h"
45 #include "keys.h"
46 #include "language.h"
47 #include "labels.h"
48 #include "labelpopup.h"
49 #include "localsession.h"
50 #include "mainmenu.h"
51 #include "mainsession.h"
52 #include "mwindowgui.h"
53 #include "mwindow.h"
54 #include "nestededls.h"
55 #include "newfolder.h"
56 #include "preferences.h"
57 #include "samples.h"
58 #include "theme.h"
59 #include "vframe.h"
60 #include "vicon.h"
61 #include "vwindowgui.h"
62 #include "vwindow.h"
63
64 #include "data/lad_picon_png.h"
65 #include "data/ff_audio_png.h"
66 #include "data/ff_video_png.h"
67
68 #include<stdio.h>
69 #include<unistd.h>
70 #include<fcntl.h>
71
72
73 const char *AWindowGUI::folder_names[] =
74 {
75         N_("Audio Effects"),
76         N_("Video Effects"),
77         N_("Audio Transitions"),
78         N_("Video Transitions"),
79         N_("Labels"),
80         N_("Clips"),
81         N_("Media"),
82         N_("Proxy"),
83 };
84
85
86 AssetVIcon::AssetVIcon(AssetPicon *picon, int w, int h, double framerate, int64_t length)
87  : VIcon(w, h, framerate)
88 {
89         this->picon = picon;
90         this->length = length;
91         temp = 0;
92 }
93
94 AssetVIcon::~AssetVIcon()
95 {
96         delete temp;
97 }
98
99 VFrame *AssetVIcon::frame()
100 {
101         if( seq_no >= images.size() ) {
102                 MWindow *mwindow = picon->mwindow;
103                 Asset *asset = (Asset *)picon->indexable;
104                 File *file = mwindow->video_cache->check_out(asset, mwindow->edl, 1);
105                 if( !file ) return 0;
106                 if( temp && (temp->get_w() != asset->width || temp->get_h() != asset->height) ) {
107                         delete temp;  temp = 0;
108                 }
109                 if( !temp )
110                         temp = new VFrame(0, -1, asset->width, asset->height, BC_RGB888, -1);
111                 int ww = picon->gui->vicon_thread->view_w;
112                 int hh = picon->gui->vicon_thread->view_h;
113                 while( seq_no >= images.size() ) {
114                         file->set_layer(0);
115                         int64_t pos = images.size() / picon->gui->vicon_thread->refresh_rate * frame_rate;
116                         file->set_video_position(pos,0);
117                         if( file->read_frame(temp) ) temp->clear_frame();
118                         add_image(temp, ww, hh, BC_RGB8);
119                 }
120                 mwindow->video_cache->check_in(asset);
121         }
122         return *images[seq_no];
123 }
124
125 int64_t AssetVIcon::set_seq_no(int64_t no)
126 {
127         if( no >= length ) no = 0;
128         return seq_no = no;
129 }
130
131 int AssetVIcon::get_vx()
132 {
133         BC_ListBox *lbox = picon->gui->asset_list;
134         return lbox->get_item_x(picon);
135 }
136 int AssetVIcon::get_vy()
137 {
138         BC_ListBox *lbox = picon->gui->asset_list;
139         return lbox->get_item_y(picon) + lbox->get_title_h();
140 }
141
142
143 AssetPicon::AssetPicon(MWindow *mwindow,
144         AWindowGUI *gui, Indexable *indexable)
145  : BC_ListBoxItem()
146 {
147         reset();
148         this->mwindow = mwindow;
149         this->gui = gui;
150         this->indexable = indexable;
151         indexable->add_user();
152         this->id = indexable->id;
153 }
154
155 AssetPicon::AssetPicon(MWindow *mwindow,
156         AWindowGUI *gui, EDL *edl)
157  : BC_ListBoxItem()
158 {
159         reset();
160         this->mwindow = mwindow;
161         this->gui = gui;
162         this->edl = edl;
163         edl->add_user();
164         this->id = edl->id;
165 }
166
167 AssetPicon::AssetPicon(MWindow *mwindow,
168         AWindowGUI *gui, int folder, int persist)
169  : BC_ListBoxItem(_(AWindowGUI::folder_names[folder]),
170         folder>=0 && folder<AWINDOW_FOLDERS ?
171                 gui->folder_icons[folder]: gui->folder_icon)
172 {
173         reset();
174         foldernum = folder;
175         this->mwindow = mwindow;
176         this->gui = gui;
177         persistent = persist;
178 }
179
180 AssetPicon::AssetPicon(MWindow *mwindow,
181         AWindowGUI *gui, PluginServer *plugin)
182  : BC_ListBoxItem()
183 {
184         reset();
185         this->mwindow = mwindow;
186         this->gui = gui;
187         this->plugin = plugin;
188 }
189
190 AssetPicon::AssetPicon(MWindow *mwindow,
191         AWindowGUI *gui, Label *label)
192  : BC_ListBoxItem()
193 {
194         reset();
195         this->mwindow = mwindow;
196         this->gui = gui;
197         this->label = label;
198         indexable = 0;
199         icon = 0;
200         id = 0;
201 }
202
203 AssetPicon::~AssetPicon()
204 {
205         if( vicon )
206                 gui->vicon_thread->del_vicon(vicon);
207         if( indexable ) indexable->remove_user();
208         if( edl ) edl->remove_user();
209         if( icon && !gui->protected_pixmap(icon) ) {
210                 delete icon;
211                 if( !plugin ) delete icon_vframe;
212         }
213 }
214
215 void AssetPicon::draw_wave(VFrame *frame, double *dp, int len, int base_color, int line_color)
216 {
217         int w = frame->get_w(), h = frame->get_h();
218         int h1 = h-1, h2 = h/2, y = h2;
219         int rgb_color = frame->pixel_rgb;
220         for( int x=0,x1=0,x2=0; x<w; ++x,x1=x2 ) {
221                 double min = *dp, max = min;
222                 x2 = (len * (x+1))/w;
223                 for( int i=x1; i<x2; ++i ) {
224                         double value = *dp++;
225                         if( value < min ) min = value;
226                         if( value > max ) max = value;
227                 }
228                 int ctr = (min + max) / 2;
229                 int y0 = (int)(h2 - ctr*h2);  CLAMP(y0, 0,h1);
230                 int y1 = (int)(h2 - min*h2);  CLAMP(y1, 0,h1);
231                 int y2 = (int)(h2 - max*h2);  CLAMP(y2, 0,h1);
232                 frame->pixel_rgb = line_color;
233                 frame->draw_line(x,y1, x,y2);
234                 frame->pixel_rgb = base_color;
235                 frame->draw_line(x,y, x,y0);
236                 y = y0;
237         }
238         frame->pixel_rgb = rgb_color;
239 }
240
241 void AssetPicon::reset()
242 {
243         plugin = 0;
244         label = 0;
245         indexable = 0;
246         edl = 0;
247         foldernum = AW_NO_FOLDER;
248         icon = 0;
249         icon_vframe = 0;
250         vicon = 0;
251         in_use = 1;
252         mtime = 0;
253         id = 0;
254         persistent = 0;
255 }
256
257 void AssetPicon::create_objects()
258 {
259         FileSystem fs;
260         char name[BCTEXTLEN];
261         int pixmap_w, pixmap_h;
262
263         pixmap_h = 50 * BC_WindowBase::get_resources()->icon_scale;
264
265         if( indexable ) {
266                 fs.extract_name(name, indexable->path);
267                 set_text(name);
268         }
269
270         if( indexable && indexable->is_asset ) {
271                 Asset *asset = (Asset*)indexable;
272                 if( asset->video_data ) {
273                         if( mwindow->preferences->use_thumbnails ) {
274                                 gui->unlock_window();
275                                 File *file = mwindow->video_cache->check_out(asset,
276                                         mwindow->edl,
277                                         1);
278
279                                 if( file ) {
280                                         int height = asset->height > 0 ? asset->height : 1;
281                                         pixmap_w = pixmap_h * asset->width / height;
282
283                                         file->set_layer(0);
284                                         file->set_video_position(0, 0);
285
286                                         if( gui->temp_picon &&
287                                                 (gui->temp_picon->get_w() != asset->width ||
288                                                 gui->temp_picon->get_h() != asset->height) ) {
289                                                 delete gui->temp_picon;
290                                                 gui->temp_picon = 0;
291                                         }
292
293                                         if( !gui->temp_picon ) {
294                                                 gui->temp_picon = new VFrame(0, -1,
295                                                         asset->width, asset->height,
296                                                         BC_RGB888, -1);
297                                         }
298                                         { char string[BCTEXTLEN];
299                                         sprintf(string, _("Reading %s"), name);
300                                         mwindow->gui->lock_window("AssetPicon::create_objects");
301                                         mwindow->gui->show_message(string);
302                                         mwindow->gui->unlock_window(); }
303                                         file->read_frame(gui->temp_picon);
304                                         mwindow->video_cache->check_in(asset);
305
306                                         gui->lock_window("AssetPicon::create_objects 1");
307                                         icon = new BC_Pixmap(gui, pixmap_w, pixmap_h);
308                                         icon->draw_vframe(gui->temp_picon,
309                                                 0, 0, pixmap_w, pixmap_h, 0, 0);
310                                         icon_vframe = new VFrame(0,
311                                                 -1, pixmap_w, pixmap_h, BC_RGB888, -1);
312                                         icon_vframe->transfer_from(gui->temp_picon);
313                                         if( asset->awindow_folder == AW_MEDIA_FOLDER ) {
314 // vicon images
315                                                 double framerate = asset->get_frame_rate();
316                                                 if( !framerate ) framerate = VICON_RATE;
317                                                 int64_t frames = asset->get_video_frames();
318                                                 double secs = frames / framerate;
319                                                 if( secs > 5 ) secs = 5;
320                                                 int64_t length = secs * gui->vicon_thread->refresh_rate;
321                                                 vicon = new AssetVIcon(this, pixmap_w, pixmap_h, framerate, length);
322                                                 gui->vicon_thread->add_vicon(vicon);
323                                         }
324
325                                 }
326                                 else {
327                                         gui->lock_window("AssetPicon::create_objects 2");
328                                         icon = gui->video_icon;
329                                         icon_vframe = gui->video_vframe;
330                                 }
331                         }
332                         else {
333                                 icon = gui->video_icon;
334                                 icon_vframe = gui->video_vframe;
335                         }
336                 }
337                 else
338                 if( asset->audio_data ) {
339                         if( mwindow->preferences->use_thumbnails ) {
340                                 gui->unlock_window();
341                                 File *file = mwindow->audio_cache->check_out(asset,
342                                         mwindow->edl,
343                                         1);
344                                 if( file ) {
345                                         pixmap_w = pixmap_h * 16/9;
346                                         icon_vframe = new VFrame(0,
347                                                 -1, pixmap_w, pixmap_h, BC_RGB888, -1);
348                                         { char string[BCTEXTLEN];
349                                         sprintf(string, _("Reading %s"), name);
350                                         mwindow->gui->lock_window("AssetPicon::create_objects 3");
351                                         mwindow->gui->show_message(string);
352                                         mwindow->gui->unlock_window(); }
353                                         int sample_rate = asset->get_sample_rate();
354                                         int channels = asset->get_audio_channels();
355                                         if( channels > 2 ) channels = 2;
356                                         int64_t length = asset->get_audio_samples();
357                                         double duration = (double)length / sample_rate;
358                                         float t = duration > 1 ? (logf(duration) / logf(3600.f)) : 0;
359                                         if( t > 1 ) t = 1;
360                                         float h = 300 * t, s = 1., v = 1.;
361                                         float r, g, b; // duration, 0..1hr == hue red..magenta
362                                         HSV::hsv_to_rgb(r,g,b, h,s,v);
363                                         int ih = icon_vframe->get_h()/8, iw = icon_vframe->get_w();
364                                         int ir = r * 256;  CLAMP(ir, 0,255);
365                                         int ig = g * 256;  CLAMP(ig, 0,255);
366                                         int ib = b * 256;  CLAMP(ib, 0,255);
367                                         unsigned char **rows = icon_vframe->get_rows();
368                                         for( int y=0; y<ih; ++y ) {
369                                                 unsigned char *rp = rows[y];
370                                                 for( int x=0; x<iw; rp+=3,++x ) {
371                                                         rp[0] = ir;  rp[1] = ig;  rp[2] = ib;
372                                                 }
373                                         }
374                                         length = sample_rate;
375                                         Samples samples(length);
376                                         static int line_colors[2] = { GREEN, YELLOW };
377                                         static int base_colors[2] = { RED, PINK };
378                                         for( int i=channels; --i>=0; ) {
379                                                 file->set_channel(i);
380                                                 file->set_audio_position(0);
381                                                 file->read_samples(&samples, length);
382                                                 draw_wave(icon_vframe, samples.get_data(), length,
383                                                         base_colors[i], line_colors[i]);
384                                         }
385                                         mwindow->audio_cache->check_in(asset);
386                                         gui->lock_window("AssetPicon::create_objects 4");
387                                         icon = new BC_Pixmap(gui, pixmap_w, pixmap_h);
388                                         icon->draw_vframe(icon_vframe,
389                                                 0, 0, pixmap_w, pixmap_h, 0, 0);
390                                 }
391                                 else {
392                                         gui->lock_window("AssetPicon::create_objects 5");
393                                         icon = gui->audio_icon;
394                                         icon_vframe = gui->audio_vframe;
395                                 }
396                         }
397                         else {
398                                 icon = gui->audio_icon;
399                                 icon_vframe = gui->audio_vframe;
400                         }
401
402                 }
403                 struct stat st;
404                 mtime = !stat(asset->path, &st) ? st.st_mtime : 0;
405         }
406         else
407         if( indexable && !indexable->is_asset ) {
408                 icon = gui->video_icon;
409                 icon_vframe = gui->video_vframe;
410         }
411         else
412         if( edl ) {
413                 set_text(strcpy(name, edl->local_session->clip_title));
414                 icon = gui->clip_icon;
415                 icon_vframe = gui->clip_vframe;
416         }
417         else
418         if( plugin ) {
419                 strcpy(name, _(plugin->title));
420                 set_text(name);
421                 icon_vframe = plugin->get_picon();
422                 if( icon_vframe )
423                         icon = gui->create_pixmap(icon_vframe);
424                 else if( plugin->audio ) {
425                         if( plugin->transition ) {
426                                 icon = gui->atransition_icon;
427                                 icon_vframe = gui->atransition_vframe;
428                         }
429                         else if( plugin->is_ffmpeg() ) {
430                                 icon = gui->ff_aud_icon;
431                                 icon_vframe = gui->ff_aud_vframe;
432                         }
433                         else if( plugin->is_ladspa() ) {
434                                 icon = gui->ladspa_icon;
435                                 icon_vframe = gui->ladspa_vframe;
436                         }
437                         else {
438                                 icon = gui->aeffect_icon;
439                                 icon_vframe = gui->aeffect_vframe;
440                         }
441                 }
442                 else if( plugin->video ) {
443                         if( plugin->transition ) {
444                                 icon = gui->vtransition_icon;
445                                 icon_vframe = gui->vtransition_vframe;
446                         }
447                         else if( plugin->is_ffmpeg() ) {
448                                 icon = gui->ff_vid_icon;
449                                 icon_vframe = gui->ff_vid_vframe;
450                         }
451                         else {
452                                 icon = gui->veffect_icon;
453                                 icon_vframe = gui->veffect_vframe;
454                         }
455                 }
456         }
457         else
458         if( label ) {
459                 Units::totext(name,
460                               label->position,
461                               mwindow->edl->session->time_format,
462                               mwindow->edl->session->sample_rate,
463                               mwindow->edl->session->frame_rate,
464                               mwindow->edl->session->frames_per_foot);
465                 set_text(name);
466                 icon = gui->label_icon;
467                 icon_vframe = gui->label_vframe;
468         }
469         if( !icon ) {
470                 icon = gui->file_icon;
471                 icon_vframe = BC_WindowBase::get_resources()->type_to_icon[ICON_UNKNOWN];
472         }
473         set_icon(icon);
474         set_icon_vframe(icon_vframe);
475 }
476
477 AWindowGUI::AWindowGUI(MWindow *mwindow, AWindow *awindow)
478  : BC_Window(_(PROGRAM_NAME ": Resources"),
479         mwindow->session->awindow_x, mwindow->session->awindow_y,
480         mwindow->session->awindow_w, mwindow->session->awindow_h,
481         100, 100, 1, 1, 1)
482 {
483         this->mwindow = mwindow;
484         this->awindow = awindow;
485
486         file_vframe = 0;                file_icon = 0;
487         folder_vframe = 0;              folder_icon = 0;
488         audio_vframe = 0;               audio_icon = 0;
489         video_vframe = 0;               video_icon = 0;
490         label_vframe = 0;               label_icon = 0;
491
492         atransition_vframe = 0;         atransition_icon = 0;
493         vtransition_vframe = 0;         vtransition_icon = 0;
494         aeffect_vframe = 0;             aeffect_icon = 0;
495         ladspa_vframe = 0;              ladspa_icon = 0;
496         veffect_vframe = 0;             veffect_icon = 0;
497         ff_aud_vframe = 0;              ff_aud_icon = 0;
498         ff_vid_vframe = 0;              ff_vid_icon = 0;
499
500         aeffect_folder_vframe = 0;      aeffect_folder_icon = 0;
501         atransition_folder_vframe = 0;  atransition_folder_icon = 0;
502         clip_folder_vframe = 0;         clip_folder_icon = 0;
503         label_folder_vframe = 0;        label_folder_icon = 0;
504         media_folder_vframe = 0;        media_folder_icon = 0;
505         proxy_folder_vframe = 0;        proxy_folder_icon = 0;
506         veffect_folder_vframe = 0;      veffect_folder_icon = 0;
507         vtransition_folder_vframe = 0;  vtransition_folder_icon = 0;
508
509         ladspa_vframe = 0;              ladspa_icon = 0;
510         ff_aud_vframe = 0;              ff_aud_icon = 0;
511         ff_vid_vframe = 0;              ff_vid_icon = 0;
512
513         clip_vframe = 0;                clip_icon = 0;
514         atransition_vframe = 0;         atransition_icon = 0;
515         vtransition_vframe = 0;         vtransition_icon = 0;
516         aeffect_vframe = 0;             aeffect_icon = 0;
517         veffect_vframe = 0;             veffect_icon = 0;
518
519         plugin_visibility = ((uint64_t)1<<(8*sizeof(uint64_t)-1))-1;
520         newfolder_thread = 0;
521         asset_menu = 0;
522         effectlist_menu = 0;
523         assetlist_menu = 0;
524         cliplist_menu = 0;
525         labellist_menu = 0;
526         folderlist_menu = 0;
527         temp_picon = 0;
528         search_text = 0;
529         allow_iconlisting = 1;
530         remove_plugin = 0;
531         vicon_thread = 0;
532         vicon_drawing = 1;
533         displayed_folder = AW_NO_FOLDER;
534 }
535
536 AWindowGUI::~AWindowGUI()
537 {
538         assets.remove_all_objects();
539         folders.remove_all_objects();
540         aeffects.remove_all_objects();
541         veffects.remove_all_objects();
542         atransitions.remove_all_objects();
543         vtransitions.remove_all_objects();
544         labellist.remove_all_objects();
545         displayed_assets[1].remove_all_objects();
546
547         delete vicon_thread;
548         delete newfolder_thread;
549
550         delete asset_menu;
551         delete clip_menu;
552         delete label_menu;
553         delete effectlist_menu;
554         delete assetlist_menu;
555         delete cliplist_menu;
556         delete labellist_menu;
557         delete folderlist_menu;
558         delete search_text;
559         delete temp_picon;
560         delete remove_plugin;
561
562         delete file_vframe;             delete file_icon;
563         delete folder_vframe;           delete folder_icon;
564         delete audio_vframe;            delete audio_icon;
565         delete video_vframe;            delete video_icon;
566         delete label_vframe;            delete label_icon;
567         delete clip_vframe;             delete clip_icon;
568         delete aeffect_folder_vframe;   delete aeffect_folder_icon;
569         delete atransition_folder_vframe; delete atransition_folder_icon;
570         delete veffect_folder_vframe;   delete veffect_folder_icon;
571         delete vtransition_folder_vframe; delete vtransition_folder_icon;
572         delete clip_folder_vframe;      delete clip_folder_icon;
573         delete label_folder_vframe;     delete label_folder_icon;
574         delete media_folder_vframe;     delete media_folder_icon;
575         delete proxy_folder_vframe;     delete proxy_folder_icon;
576         delete ladspa_vframe;           delete ladspa_icon;
577         delete ff_aud_vframe;           delete ff_aud_icon;
578         delete ff_vid_vframe;           delete ff_vid_icon;
579         delete atransition_vframe;      delete atransition_icon;
580         delete vtransition_vframe;      delete vtransition_icon;
581         delete aeffect_vframe;          delete aeffect_icon;
582         delete veffect_vframe;          delete veffect_icon;
583 }
584
585 bool AWindowGUI::protected_pixmap(BC_Pixmap *icon)
586 {
587         return  icon == file_icon ||
588                 icon == folder_icon ||
589                 icon == audio_icon ||
590                 icon == video_icon ||
591                 icon == clip_icon ||
592                 icon == label_icon ||
593                 icon == vtransition_icon ||
594                 icon == atransition_icon ||
595                 icon == veffect_icon ||
596                 icon == aeffect_icon ||
597                 icon == ladspa_icon ||
598                 icon == ff_aud_icon ||
599                 icon == ff_vid_icon ||
600                 icon == aeffect_folder_icon ||
601                 icon == veffect_folder_icon ||
602                 icon == atransition_folder_icon ||
603                 icon == vtransition_folder_icon ||
604                 icon == label_folder_icon ||
605                 icon == clip_folder_icon ||
606                 icon == media_folder_icon ||
607                 icon == proxy_folder_icon;
608 }
609
610 VFrame *AWindowGUI::get_picon(const char *name, const char *plugin_icons)
611 {
612         char png_path[BCTEXTLEN];
613         char *pp = png_path, *ep = pp + sizeof(png_path)-1;
614         snprintf(pp, ep-pp, "%s/picon/%s/%s.png",
615                 File::get_plugin_path(), plugin_icons, name);
616         if( access(png_path, R_OK) ) return 0;
617         return VFramePng::vframe_png(png_path,0,0);
618 }
619
620 VFrame *AWindowGUI::get_picon(const char *name)
621 {
622         VFrame *vframe = get_picon(name, mwindow->preferences->plugin_icons);
623         if( !vframe ) {
624                 char png_name[BCSTRLEN], *pp = png_name, *ep = pp + sizeof(png_name)-1;
625                 snprintf(pp, ep-pp, "%s.png", name);
626                 unsigned char *data = mwindow->theme->get_image_data(png_name);
627                 if( data ) vframe = new VFramePng(data, 0.);
628         }
629         return vframe;
630 }
631
632 void AWindowGUI::resource_icon(VFrame *&vfrm, BC_Pixmap *&icon, const char *fn, int idx)
633 {
634         vfrm = get_picon(fn);
635         if( !vfrm ) vfrm = BC_WindowBase::get_resources()->type_to_icon[idx];
636         icon = new BC_Pixmap(this, vfrm, PIXMAP_ALPHA);
637 }
638 void AWindowGUI::theme_icon(VFrame *&vfrm, BC_Pixmap *&icon, const char *fn)
639 {
640         vfrm = get_picon(fn);
641         if( !vfrm ) vfrm = mwindow->theme->get_image(fn);
642         icon = new BC_Pixmap(this, vfrm, PIXMAP_ALPHA);
643 }
644 void AWindowGUI::plugin_icon(VFrame *&vfrm, BC_Pixmap *&icon, const char *fn, unsigned char *png)
645 {
646         vfrm = get_picon(fn);
647         if( !vfrm ) vfrm = new VFramePng(png);
648         icon = new BC_Pixmap(this, vfrm, PIXMAP_ALPHA);
649 }
650
651 void AWindowGUI::create_objects()
652 {
653         lock_window("AWindowGUI::create_objects");
654         asset_titles[0] = C_("Title");
655         asset_titles[1] = _("Comments");
656
657         set_icon(mwindow->theme->get_image("awindow_icon"));
658
659         resource_icon(file_vframe,   file_icon,   "film_icon",   ICON_UNKNOWN);
660         resource_icon(folder_vframe, folder_icon, "folder_icon", ICON_FOLDER);
661         resource_icon(audio_vframe,  audio_icon,  "audio_icon",  ICON_SOUND);
662         resource_icon(video_vframe,  video_icon,  "video_icon",  ICON_FILM);
663         resource_icon(label_vframe,  label_icon,  "label_icon",  ICON_LABEL);
664
665         theme_icon(aeffect_folder_vframe,      aeffect_folder_icon,     "aeffect_folder");
666         theme_icon(atransition_folder_vframe,  atransition_folder_icon, "atransition_folder");
667         theme_icon(clip_folder_vframe,         clip_folder_icon,        "clip_folder");
668         theme_icon(label_folder_vframe,        label_folder_icon,       "label_folder");
669         theme_icon(media_folder_vframe,        media_folder_icon,       "media_folder");
670         theme_icon(proxy_folder_vframe,        proxy_folder_icon,       "proxy_folder");
671         theme_icon(veffect_folder_vframe,      veffect_folder_icon,     "veffect_folder");
672         theme_icon(vtransition_folder_vframe,  vtransition_folder_icon, "vtransition_folder");
673
674         folder_icons[AW_AEFFECT_FOLDER] = aeffect_folder_icon;
675         folder_icons[AW_VEFFECT_FOLDER] = veffect_folder_icon;
676         folder_icons[AW_ATRANSITION_FOLDER] = atransition_folder_icon;
677         folder_icons[AW_VTRANSITION_FOLDER] = vtransition_folder_icon;
678         folder_icons[AW_LABEL_FOLDER] = label_folder_icon;
679         folder_icons[AW_CLIP_FOLDER] = clip_folder_icon;
680         folder_icons[AW_MEDIA_FOLDER] = media_folder_icon;
681         folder_icons[AW_PROXY_FOLDER] = proxy_folder_icon;
682
683         theme_icon(clip_vframe,        clip_icon,        "clip_icon");
684         theme_icon(atransition_vframe, atransition_icon, "atransition_icon");
685         theme_icon(vtransition_vframe, vtransition_icon, "vtransition_icon");
686         theme_icon(aeffect_vframe,     aeffect_icon,     "aeffect_icon");
687         theme_icon(veffect_vframe,     veffect_icon,     "veffect_icon");
688
689         plugin_icon(ladspa_vframe, ladspa_icon, "lad_picon", lad_picon_png);
690         plugin_icon(ff_aud_vframe, ff_aud_icon, "ff_audio",  ff_audio_png);
691         plugin_icon(ff_vid_vframe, ff_vid_icon, "ff_video",  ff_video_png);
692
693 // Mandatory folders
694         folders.append(new AssetPicon(mwindow, this, AW_AEFFECT_FOLDER, 1));
695         folders.append(new AssetPicon(mwindow, this, AW_VEFFECT_FOLDER, 1));
696         folders.append(new AssetPicon(mwindow, this, AW_ATRANSITION_FOLDER, 1));
697         folders.append(new AssetPicon(mwindow, this, AW_VTRANSITION_FOLDER, 1));
698         folders.append(new AssetPicon(mwindow, this, AW_LABEL_FOLDER, 1));
699         folders.append(new AssetPicon(mwindow, this, AW_CLIP_FOLDER, 1));
700         folders.append(new AssetPicon(mwindow, this, AW_PROXY_FOLDER, 1));
701         folders.append(new AssetPicon(mwindow, this, AW_MEDIA_FOLDER, 1));
702
703         create_label_folder();
704
705         mwindow->theme->get_awindow_sizes(this);
706         load_defaults(mwindow->defaults);
707
708         int x1 = mwindow->theme->alist_x, y1 = mwindow->theme->alist_y;
709         int w1 = mwindow->theme->alist_w, h1 = mwindow->theme->alist_h;
710         search_text = new AWindowSearchText(mwindow, this, x1, y1+5);
711         search_text->create_objects();
712         int dy = search_text->get_h() + 10;
713         y1 += dy;  h1 -= dy;
714         add_subwindow(asset_list = new AWindowAssets(mwindow, this, x1, y1, w1, h1));
715
716         vicon_thread = new VIconThread(asset_list);
717         vicon_thread->start();
718
719         add_subwindow(divider = new AWindowDivider(mwindow, this,
720                 mwindow->theme->adivider_x, mwindow->theme->adivider_y,
721                 mwindow->theme->adivider_w, mwindow->theme->adivider_h));
722
723         divider->set_cursor(HSEPARATE_CURSOR, 0, 0);
724
725         int fx = mwindow->theme->afolders_x, fy = mwindow->theme->afolders_y;
726         int fw = mwindow->theme->afolders_w, fh = mwindow->theme->afolders_h;
727         VFrame **images = mwindow->theme->get_image_set("playpatch_data");
728         AVIconDrawing::calculate_geometry(this, images, &avicon_w, &avicon_h);
729         add_subwindow(avicon_drawing = new AVIconDrawing(this, fw-avicon_w, fy, images));
730         add_subwindow(add_tools = new AddTools(mwindow, this, fx, fy, _("Visibility")));
731         add_tools->create_objects();
732         fy += add_tools->get_h();  fh -= add_tools->get_h();
733         add_subwindow(folder_list = new AWindowFolders(mwindow,
734                 this, fx, fy, fw, fh));
735         update_effects();
736
737         //int x = mwindow->theme->abuttons_x;
738         //int y = mwindow->theme->abuttons_y;
739
740
741         newfolder_thread = new NewFolderThread(mwindow, this);
742
743         add_subwindow(asset_menu = new AssetPopup(mwindow, this));
744         asset_menu->create_objects();
745         add_subwindow(clip_menu = new ClipPopup(mwindow, this));
746         clip_menu->create_objects();
747         add_subwindow(label_menu = new LabelPopup(mwindow, this));
748         label_menu->create_objects();
749
750         add_subwindow(effectlist_menu = new EffectListMenu(mwindow, this));
751         effectlist_menu->create_objects();
752         add_subwindow(assetlist_menu = new AssetListMenu(mwindow, this));
753         assetlist_menu->create_objects();
754         add_subwindow(cliplist_menu = new ClipListMenu(mwindow, this));
755         cliplist_menu->create_objects();
756         add_subwindow(labellist_menu = new LabelListMenu(mwindow, this));
757         labellist_menu->create_objects();
758
759         add_subwindow(folderlist_menu = new FolderListMenu(mwindow, this));
760         folderlist_menu->create_objects();
761
762         create_custom_xatoms();
763         unlock_window();
764 }
765
766 int AWindowGUI::resize_event(int w, int h)
767 {
768         mwindow->session->awindow_x = get_x();
769         mwindow->session->awindow_y = get_y();
770         mwindow->session->awindow_w = w;
771         mwindow->session->awindow_h = h;
772
773         mwindow->theme->get_awindow_sizes(this);
774         mwindow->theme->draw_awindow_bg(this);
775         reposition_objects();
776
777 //      int x = mwindow->theme->abuttons_x;
778 //      int y = mwindow->theme->abuttons_y;
779 //      new_bin->reposition_window(x, y);
780 //      x += new_bin->get_w();
781 //      delete_bin->reposition_window(x, y);
782 //      x += delete_bin->get_w();
783 //      rename_bin->reposition_window(x, y);
784 //      x += rename_bin->get_w();
785 //      delete_disk->reposition_window(x, y);
786 //      x += delete_disk->get_w();
787 //      delete_project->reposition_window(x, y);
788 //      x += delete_project->get_w();
789 //      info->reposition_window(x, y);
790 //      x += info->get_w();
791 //      redraw_index->reposition_window(x, y);
792 //      x += redraw_index->get_w();
793 //      paste->reposition_window(x, y);
794 //      x += paste->get_w();
795 //      append->reposition_window(x, y);
796 //      x += append->get_w();
797 //      view->reposition_window(x, y);
798
799         BC_WindowBase::resize_event(w, h);
800         return 1;
801 }
802
803 int AWindowGUI::translation_event()
804 {
805         mwindow->session->awindow_x = get_x();
806         mwindow->session->awindow_y = get_y();
807         return 0;
808 }
809
810 void AWindowGUI::reposition_objects()
811 {
812         int x1 = mwindow->theme->alist_x, y1 = mwindow->theme->alist_y;
813         int w1 = mwindow->theme->alist_w, h1 = mwindow->theme->alist_h;
814         search_text->reposition_window(x1, y1+5, w1);
815         int dy = search_text->get_h() + 10;
816         y1 += dy;  h1 -= dy;
817         asset_list->reposition_window(x1, y1, w1, h1);
818         divider->reposition_window(
819                 mwindow->theme->adivider_x, mwindow->theme->adivider_y,
820                 mwindow->theme->adivider_w, mwindow->theme->adivider_h);
821         int fx = mwindow->theme->afolders_x, fy = mwindow->theme->afolders_y;
822         int fw = mwindow->theme->afolders_w, fh = mwindow->theme->afolders_h;
823         add_tools->resize_event(fw-avicon_w, add_tools->get_h());
824         avicon_drawing->reposition_window(fw-avicon_w, fy);
825         fy += add_tools->get_h();  fh -= add_tools->get_h();
826         folder_list->reposition_window(fx, fy, fw, fh);
827 }
828
829 int AWindowGUI::save_defaults(BC_Hash *defaults)
830 {
831         defaults->update("PLUGIN_VISIBILTY", plugin_visibility);
832         defaults->update("VICON_DRAWING", vicon_drawing);
833         return 0;
834 }
835
836 int AWindowGUI::load_defaults(BC_Hash *defaults)
837 {
838         plugin_visibility = defaults->get("PLUGIN_VISIBILTY", plugin_visibility);
839         vicon_drawing = defaults->get("VICON_DRAWING", vicon_drawing);
840         return 0;
841 }
842
843 int AWindowGUI::close_event()
844 {
845         hide_window();
846         mwindow->session->show_awindow = 0;
847         unlock_window();
848
849         mwindow->gui->lock_window("AWindowGUI::close_event");
850         mwindow->gui->mainmenu->show_awindow->set_checked(0);
851         mwindow->gui->unlock_window();
852
853         lock_window("AWindowGUI::close_event");
854         save_defaults(mwindow->defaults);
855         mwindow->save_defaults();
856         return 1;
857 }
858
859 void AWindowGUI::start_vicon_drawing()
860 {
861         if( !vicon_drawing ) return;
862         if( mwindow->edl->session->awindow_folder != AW_MEDIA_FOLDER ) return;
863         if( mwindow->edl->session->assetlist_format != ASSETS_ICONS ) return;
864         vicon_thread->start_drawing();
865 }
866
867 void AWindowGUI::stop_vicon_drawing()
868 {
869         vicon_thread->stop_drawing();
870 }
871
872 AWindowRemovePluginGUI::
873 AWindowRemovePluginGUI(AWindow *awindow, AWindowRemovePlugin *thread,
874         int x, int y, PluginServer *plugin)
875  : BC_Window(_(PROGRAM_NAME ": Remove plugin"), x,y, 500,200, 50, 50, 1, 0, 1, -1, "", 1)
876 {
877         this->awindow = awindow;
878         this->thread = thread;
879         this->plugin = plugin;
880         VFrame *vframe = plugin->get_picon();
881         icon = vframe ? create_pixmap(vframe) : 0;
882         plugin_list.append(new BC_ListBoxItem(plugin->title, icon));
883 }
884
885 AWindowRemovePluginGUI::
886 ~AWindowRemovePluginGUI()
887 {
888         if( !awindow->gui->protected_pixmap(icon) )
889                 delete icon;
890         plugin_list.remove_all();
891 }
892
893 void AWindowRemovePluginGUI::create_objects()
894 {
895         BC_Button *ok_button = new BC_OKButton(this);
896         add_subwindow(ok_button);
897         BC_Button *cancel_button = new BC_CancelButton(this);
898         add_subwindow(cancel_button);
899         int x = 10, y = 10;
900         BC_Title *title = new BC_Title(x, y, _("remove plugin?"));
901         add_subwindow(title);
902         y += title->get_h() + 5;
903         list = new BC_ListBox(x, y,
904                 get_w() - 20, ok_button->get_y() - y - 5, LISTBOX_TEXT, &plugin_list,
905                 0, 0, 1, 0, 0, LISTBOX_SINGLE, ICON_LEFT, 0);
906         add_subwindow(list);
907         show_window();
908 }
909
910 int AWindowRemovePlugin::remove_plugin(PluginServer *plugin, ArrayList<BC_ListBoxItem*> &folder)
911 {
912         int ret = 0;
913         for( int i=0; i<folder.size(); ) {
914                 AssetPicon *picon = (AssetPicon *)folder[i];
915                 if( picon->plugin == plugin ) {
916                         folder.remove_object_number(i);
917                         ++ret;
918                         continue;
919                 }
920                 ++i;
921         }
922         return ret;
923 }
924
925 void AWindowRemovePlugin::handle_close_event(int result)
926 {
927         if( !result ) {
928                 printf(_("remove %s\n"), plugin->path);
929                 awindow->gui->lock_window("AWindowRemovePlugin::handle_close_event");
930                 ArrayList<BC_ListBoxItem*> *folder =
931                         plugin->audio ? plugin->transition ?
932                                 &awindow->gui->atransitions :
933                                 &awindow->gui->aeffects :
934                         plugin->video ?  plugin->transition ?
935                                 &awindow->gui->vtransitions :
936                                 &awindow->gui->veffects :
937                         0;
938                 if( folder ) remove_plugin(plugin, *folder);
939                 MWindow *mwindow = awindow->mwindow;
940                 awindow->gui->unlock_window();
941                 char plugin_path[BCTEXTLEN];
942                 strcpy(plugin_path, plugin->path);
943                 mwindow->plugindb->remove(plugin);
944                 remove(plugin_path);
945                 char index_path[BCTEXTLEN];
946                 mwindow->create_defaults_path(index_path, PLUGIN_FILE);
947                 remove(index_path);
948                 char picon_path[BCTEXTLEN];
949                 FileSystem fs;
950                 snprintf(picon_path, sizeof(picon_path), "%s/picon",
951                         File::get_plugin_path());
952                 char png_name[BCSTRLEN], png_path[BCTEXTLEN];
953                 plugin->get_plugin_png_name(png_name);
954                 fs.update(picon_path);
955                 for( int i=0; i<fs.dir_list.total; ++i ) {
956                         char *fs_path = fs.dir_list[i]->path;
957                         if( !fs.is_dir(fs_path) ) continue;
958                         snprintf(png_path, sizeof(picon_path), "%s/%s",
959                                 fs_path, png_name);
960                         remove(png_path);
961                 }
962                 delete plugin;  plugin = 0;
963                 awindow->gui->async_update_assets();
964         }
965 }
966
967 AWindowRemovePlugin::
968 AWindowRemovePlugin(AWindow *awindow, PluginServer *plugin)
969  : BC_DialogThread()
970 {
971         this->awindow = awindow;
972         this->plugin = plugin;
973 }
974
975 AWindowRemovePlugin::
976 ~AWindowRemovePlugin()
977 {
978         close_window();
979 }
980
981 BC_Window* AWindowRemovePlugin::new_gui()
982 {
983         int x = awindow->gui->get_abs_cursor_x(0);
984         int y = awindow->gui->get_abs_cursor_y(0);
985         AWindowRemovePluginGUI *gui = new AWindowRemovePluginGUI(awindow, this, x, y, plugin);
986         gui->create_objects();
987         return gui;
988 }
989
990 int AWindowGUI::keypress_event()
991 {
992         switch( get_keypress() ) {
993         case 'w': case 'W':
994                 if( ctrl_down() ) {
995                         close_event();
996                         return 1;
997                 }
998                 break;
999         case DELETE:
1000                 if( shift_down() ) {
1001                         PluginServer* plugin = selected_plugin();
1002                         if( !plugin ) break;
1003                         remove_plugin = new AWindowRemovePlugin(awindow, plugin);
1004                         unlock_window();
1005                         remove_plugin->start();
1006                         lock_window();
1007                 }
1008         }
1009         return 0;
1010 }
1011
1012
1013
1014 int AWindowGUI::create_custom_xatoms()
1015 {
1016         UpdateAssetsXAtom = create_xatom("CWINDOWGUI_UPDATE_ASSETS");
1017         return 0;
1018 }
1019 int AWindowGUI::recieve_custom_xatoms(xatom_event *event)
1020 {
1021         if( event->message_type == UpdateAssetsXAtom ) {
1022                 update_assets();
1023                 return 1;
1024         }
1025         return 0;
1026 }
1027
1028 void AWindowGUI::async_update_assets()
1029 {
1030         xatom_event event;
1031         event.message_type = UpdateAssetsXAtom;
1032         send_custom_xatom(&event);
1033 }
1034
1035
1036 void AWindowGUI::update_folder_list()
1037 {
1038         for( int i = 0; i < folders.total; i++ ) {
1039                 AssetPicon *picon = (AssetPicon*)folders.values[i];
1040                 picon->in_use = 0;
1041         }
1042
1043 // Search assets for folders
1044         for( int i = 0; i < mwindow->edl->folders.total; i++ ) {
1045                 const char *folder = mwindow->edl->folders.values[i];
1046                 int exists = 0;
1047
1048                 for( int j = 0; j < folders.total; j++ ) {
1049                         AssetPicon *picon = (AssetPicon*)folders.values[j];
1050                         if( !strcasecmp(picon->get_text(), folder) ) {
1051                                 exists = 1;
1052                                 picon->in_use = 1;
1053                                 break;
1054                         }
1055                 }
1056
1057                 if( !exists ) {
1058                         int aw_folder = folder_number(folder);
1059                         if( aw_folder >= 0 ) {
1060                                 AssetPicon *picon = new AssetPicon(mwindow, this, aw_folder, 1);
1061                                 picon->create_objects();
1062                                 folders.append(picon);
1063                         }
1064                 }
1065         }
1066
1067 // Delete unused non-persistent folders
1068         for( int i=folders.total; --i>=0; ) {
1069                 AssetPicon *picon = (AssetPicon*)folders.values[i];
1070                 if( !picon->in_use && !picon->persistent ) {
1071                         delete picon;
1072                         folders.remove_number(i);
1073                 }
1074         }
1075 }
1076
1077 void AWindowGUI::create_persistent_folder(ArrayList<BC_ListBoxItem*> *output,
1078         int do_audio, int do_video, int is_realtime, int is_transition)
1079 {
1080         ArrayList<PluginServer*> plugin_list;
1081 // Get pointers to plugindb entries
1082         mwindow->search_plugindb(do_audio, do_video, is_realtime, is_transition,
1083                         0, plugin_list);
1084
1085         for( int i = 0; i < plugin_list.total; i++ ) {
1086                 PluginServer *server = plugin_list.values[i];
1087                 int visible = plugin_visibility & (1<<server->dir_idx);
1088                 if( !visible ) continue;
1089 // Create new listitem
1090                 AssetPicon *picon = new AssetPicon(mwindow, this, server);
1091                 picon->create_objects();
1092                 output->append(picon);
1093         }
1094 }
1095
1096 void AWindowGUI::create_label_folder()
1097 {
1098         Label *current;
1099         for( current = mwindow->edl->labels->first; current; current = NEXT ) {
1100                 AssetPicon *picon = new AssetPicon(mwindow, this, current);
1101                 picon->create_objects();
1102                 labellist.append(picon);
1103         }
1104 }
1105
1106
1107 void AWindowGUI::update_asset_list()
1108 {
1109         for( int i = 0; i < assets.total; i++ ) {
1110                 AssetPicon *picon = (AssetPicon*)assets.values[i];
1111                 picon->in_use = 0;
1112         }
1113
1114 // Synchronize EDL clips
1115         for( int i = 0; i < mwindow->edl->clips.total; i++ ) {
1116                 int exists = 0;
1117
1118 // Look for clip in existing listitems
1119                 for( int j = 0; j < assets.total && !exists; j++ ) {
1120                         AssetPicon *picon = (AssetPicon*)assets.values[j];
1121
1122                         if( picon->id == mwindow->edl->clips.values[i]->id ) {
1123                                 picon->edl = mwindow->edl->clips.values[i];
1124                                 picon->set_text(mwindow->edl->clips.values[i]->local_session->clip_title);
1125                                 exists = 1;
1126                                 picon->in_use = 1;
1127                         }
1128                 }
1129
1130 // Create new listitem
1131                 if( !exists ) {
1132                         AssetPicon *picon = new AssetPicon(mwindow,
1133                                 this, mwindow->edl->clips.values[i]);
1134                         picon->create_objects();
1135                         assets.append(picon);
1136                 }
1137         }
1138
1139 // Synchronize EDL assets
1140         for( Asset *current = mwindow->edl->assets->first;
1141                 current;
1142                 current = NEXT ) {
1143                 int exists = 0;
1144
1145 // Look for asset in existing listitems
1146                 for( int j = 0; j < assets.total && !exists; j++ ) {
1147                         AssetPicon *picon = (AssetPicon*)assets.values[j];
1148
1149                         if( picon->id == current->id ) {
1150                                 picon->indexable = current;
1151                                 exists = 1;
1152                                 picon->in_use = 1;
1153                                 break;
1154                         }
1155                 }
1156
1157 // Create new listitem
1158                 if( !exists ) {
1159                         AssetPicon *picon = new AssetPicon(mwindow,
1160                                 this, current);
1161                         picon->create_objects();
1162                         assets.append(picon);
1163                 }
1164         }
1165
1166         mwindow->gui->lock_window("AWindowGUI::update_asset_list");
1167         mwindow->gui->default_message();
1168         mwindow->gui->unlock_window();
1169
1170 // Synchronize nested EDLs
1171         for( int i = 0; i < mwindow->edl->nested_edls->size(); i++ ) {
1172                 int exists = 0;
1173                 Indexable *indexable = mwindow->edl->nested_edls->get(i);
1174
1175 // Look for asset in existing listitems
1176                 for( int j = 0; j < assets.total && !exists; j++ ) {
1177                         AssetPicon *picon = (AssetPicon*)assets.values[j];
1178
1179                         if( picon->id == indexable->id ) {
1180                                 picon->indexable = indexable;
1181                                 exists = 1;
1182                                 picon->in_use = 1;
1183                                 break;
1184                         }
1185                 }
1186
1187 // Create new listitem
1188                 if( !exists ) {
1189                         AssetPicon *picon = new AssetPicon(mwindow,
1190                                 this, indexable);
1191                         picon->create_objects();
1192                         assets.append(picon);
1193                 }
1194         }
1195
1196         for( int i = assets.size() - 1; i >= 0; i-- ) {
1197                 AssetPicon *picon = (AssetPicon*)assets.get(i);
1198                 if( !picon->in_use ) {
1199                         delete picon;
1200                         assets.remove_number(i);
1201                         continue;
1202                 }
1203                 if( !picon->indexable || !picon->indexable->is_asset ) continue;
1204                 struct stat st;
1205                 picon->mtime = !stat(picon->indexable->path, &st) ? st.st_mtime : 0;
1206         }
1207 }
1208
1209 void AWindowGUI::update_picon(Indexable *indexable)
1210 {
1211         VIcon *vicon = 0;
1212         for( int i = 0; i < assets.total; i++ ) {
1213                 AssetPicon *picon = (AssetPicon*)assets.values[i];
1214                 if( picon->indexable == indexable ||
1215                     picon->edl == (EDL *)indexable ) {
1216                         char name[BCTEXTLEN];
1217                         FileSystem fs;
1218                         fs.extract_name(name, indexable->path);
1219                         picon->set_text(name);
1220                         vicon = picon->vicon;
1221                         break;
1222                 }
1223         }
1224         if( vicon ) {
1225                 stop_vicon_drawing();
1226                 vicon->clear_images();
1227                 vicon->reset(indexable->get_frame_rate());
1228                 start_vicon_drawing();
1229         }
1230 }
1231
1232 void AWindowGUI::sort_assets(int use_mtime)
1233 {
1234         switch( mwindow->edl->session->awindow_folder ) {
1235         case AW_AEFFECT_FOLDER:
1236                 sort_picons(&aeffects);
1237                 break;
1238         case AW_VEFFECT_FOLDER:
1239                 sort_picons(&veffects);
1240                 break;
1241         case AW_ATRANSITION_FOLDER:
1242                 sort_picons(&atransitions);
1243                 break;
1244         case AW_VTRANSITION_FOLDER:
1245                 sort_picons(&vtransitions);
1246                 break;
1247         case AW_LABEL_FOLDER:
1248                 sort_picons(&labellist);
1249                 break;
1250         default:
1251                 sort_picons(&assets, use_mtime);
1252         }
1253 // reset xyposition
1254         asset_list->update_format(asset_list->get_format(), 0);
1255         update_assets();
1256 }
1257
1258 void AWindowGUI::sort_folders()
1259 {
1260         sort_picons(&folders);
1261         folder_list->update_format(folder_list->get_format(), 0);
1262         update_assets();
1263 }
1264
1265 void AWindowGUI::collect_assets()
1266 {
1267         int i = 0;
1268         mwindow->session->drag_assets->remove_all();
1269         mwindow->session->drag_clips->remove_all();
1270         while(1)
1271         {
1272                 AssetPicon *result = (AssetPicon*)asset_list->get_selection(0, i++);
1273                 if( !result ) break;
1274
1275                 if( result->indexable ) mwindow->session->drag_assets->append(result->indexable);
1276                 if( result->edl ) mwindow->session->drag_clips->append(result->edl);
1277         }
1278 }
1279
1280 void AWindowGUI::copy_picons(ArrayList<BC_ListBoxItem*> *dst,
1281         ArrayList<BC_ListBoxItem*> *src, int folder)
1282 {
1283 // Remove current pointers
1284         dst[0].remove_all();
1285         dst[1].remove_all_objects();
1286
1287 // Create new pointers
1288         for( int i = 0; i < src->total; i++ ) {
1289                 AssetPicon *picon = (AssetPicon*)src->values[i];
1290                 if( folder < 0 ||
1291                     (picon->indexable && picon->indexable->awindow_folder == folder) ||
1292                     (picon->edl && picon->edl->local_session->awindow_folder == folder) ) {
1293                         const char *text = search_text->get_text();
1294                         int hidden = text && text[0] && !bstrcasestr(picon->get_text(), text);
1295                         if( picon->vicon ) picon->vicon->hidden = hidden;
1296                         if( hidden ) continue;
1297                         BC_ListBoxItem *item2, *item1;
1298                         dst[0].append(item1 = picon);
1299                         if( picon->edl )
1300                                 dst[1].append(item2 = new BC_ListBoxItem(picon->edl->local_session->clip_notes));
1301                         else
1302                         if( picon->label && picon->label->textstr )
1303                                 dst[1].append(item2 = new BC_ListBoxItem(picon->label->textstr));
1304                         else if( picon->mtime ) {
1305                                 char date_time[BCSTRLEN];
1306                                 struct tm stm;  localtime_r(&picon->mtime, &stm);
1307                                 sprintf(date_time,"%04d.%02d.%02d %02d:%02d:%02d",
1308                                          stm.tm_year+1900, stm.tm_mon+1, stm.tm_mday,
1309                                          stm.tm_hour, stm.tm_min, stm.tm_sec);
1310                                 dst[1].append(item2 = new BC_ListBoxItem(date_time));
1311                         }
1312                         else
1313                                 dst[1].append(item2 = new BC_ListBoxItem(""));
1314                         item1->set_autoplace_text(1);  item1->set_autoplace_icon(1);
1315                         item2->set_autoplace_text(1);  item2->set_autoplace_icon(1);
1316                 }
1317         }
1318 }
1319
1320 void AWindowGUI::sort_picons(ArrayList<BC_ListBoxItem*> *src, int use_mtime)
1321 {
1322         int done = 0, changed = 0;
1323         while( !done ) {
1324                 done = 1;
1325                 for( int i=0; i<src->total-1; ++i ) {
1326                         AssetPicon *item1 = (AssetPicon *)src->values[i];
1327                         AssetPicon *item2 = (AssetPicon *)src->values[i + 1];
1328                         if( use_mtime ? item1->mtime > item2->mtime :
1329                             strcmp(item1->get_text(), item2->get_text()) > 0 ) {
1330                                 src->values[i + 1] = item1;
1331                                 src->values[i] = item2;
1332                                 done = 0;  changed = 1;
1333                         }
1334                 }
1335         }
1336         if( changed ) {
1337                 for( int i=0; i<src->total; ++i ) {
1338                         AssetPicon *item = (AssetPicon *)src->values[i];
1339                         item->set_autoplace_icon(1);
1340                         item->set_autoplace_text(1);
1341                 }
1342         }
1343 }
1344
1345
1346 void AWindowGUI::filter_displayed_assets()
1347 {
1348         //allow_iconlisting = 1;
1349         asset_titles[0] = C_("Title");
1350         asset_titles[1] = _("Comments");
1351
1352         switch( mwindow->edl->session->awindow_folder ) {
1353         case AW_AEFFECT_FOLDER:
1354                 copy_picons(displayed_assets, &aeffects, AW_NO_FOLDER);
1355                 break;
1356         case AW_VEFFECT_FOLDER:
1357                 copy_picons(displayed_assets, &veffects, AW_NO_FOLDER);
1358                 break;
1359         case AW_ATRANSITION_FOLDER:
1360                 copy_picons(displayed_assets, &atransitions, AW_NO_FOLDER);
1361                 break;
1362         case AW_VTRANSITION_FOLDER:
1363                 copy_picons(displayed_assets, &vtransitions, AW_NO_FOLDER);
1364                 break;
1365         case AW_LABEL_FOLDER:
1366                 copy_picons(displayed_assets, &labellist, AW_NO_FOLDER);
1367                 asset_titles[0] = _("Time Stamps");
1368                 asset_titles[1] = C_("Title");
1369                 //allow_iconlisting = 0;
1370                 break;
1371         default:
1372                 copy_picons(displayed_assets, &assets, mwindow->edl->session->awindow_folder);
1373                 break;
1374         }
1375
1376         // Ensure the current folder icon is highlighted
1377         int selected_folder = mwindow->edl->session->awindow_folder;
1378         for( int i = 0; i < folders.total; i++ ) {
1379                 AssetPicon *folder_item = (AssetPicon *)folders.values[i];
1380                 int selected = folder_item->foldernum == selected_folder ? 1 : 0;
1381                 folder_item->set_selected(selected);
1382         }
1383 }
1384
1385
1386 void AWindowGUI::update_assets()
1387 {
1388         stop_vicon_drawing();
1389         update_folder_list();
1390         update_asset_list();
1391         labellist.remove_all_objects();
1392         create_label_folder();
1393
1394         if( displayed_folder != mwindow->edl->session->awindow_folder )
1395                 search_text->clear();
1396         filter_displayed_assets();
1397
1398         if( mwindow->edl->session->folderlist_format != folder_list->get_format() ) {
1399                 folder_list->update_format(mwindow->edl->session->folderlist_format, 0);
1400         }
1401         int folder_xposition = folder_list->get_xposition();
1402         int folder_yposition = folder_list->get_yposition();
1403         folder_list->update(&folders, 0, 0, 1, folder_xposition, folder_yposition, -1);
1404
1405         if( mwindow->edl->session->assetlist_format != asset_list->get_format() ) {
1406                 asset_list->update_format(mwindow->edl->session->assetlist_format, 0);
1407         }
1408         int asset_xposition = asset_list->get_xposition();
1409         int asset_yposition = asset_list->get_yposition();
1410         if( displayed_folder != mwindow->edl->session->awindow_folder ) {
1411                 displayed_folder = mwindow->edl->session->awindow_folder;
1412                 asset_xposition = asset_yposition = 0;
1413         }
1414         asset_list->update(displayed_assets, asset_titles,
1415                 mwindow->edl->session->asset_columns, ASSET_COLUMNS,
1416                 asset_xposition, asset_yposition, -1, 0);
1417         asset_list->center_selection();
1418
1419         flush();
1420         start_vicon_drawing();
1421         return;
1422 }
1423
1424 void AWindowGUI::update_effects()
1425 {
1426         aeffects.remove_all_objects();
1427         create_persistent_folder(&aeffects, 1, 0, 1, 0);
1428         veffects.remove_all_objects();
1429         create_persistent_folder(&veffects, 0, 1, 1, 0);
1430         atransitions.remove_all_objects();
1431         create_persistent_folder(&atransitions, 1, 0, 0, 1);
1432         vtransitions.remove_all_objects();
1433         create_persistent_folder(&vtransitions, 0, 1, 0, 1);
1434 }
1435
1436 int AWindowGUI::folder_number(const char *name)
1437 {
1438         for( int i = 0; i < AWINDOW_FOLDERS; i++ ) {
1439                 if( !strcasecmp(name, folder_names[i]) ) return i;
1440         }
1441         return AW_NO_FOLDER;
1442 }
1443
1444 int AWindowGUI::drag_motion()
1445 {
1446         if( get_hidden() ) return 0;
1447
1448         int result = 0;
1449         return result;
1450 }
1451
1452 int AWindowGUI::drag_stop()
1453 {
1454         if( get_hidden() ) return 0;
1455
1456         return 0;
1457 }
1458
1459 Indexable* AWindowGUI::selected_asset()
1460 {
1461         AssetPicon *picon = (AssetPicon*)asset_list->get_selection(0, 0);
1462         return picon ? picon->indexable : 0;
1463 }
1464
1465 PluginServer* AWindowGUI::selected_plugin()
1466 {
1467         AssetPicon *picon = (AssetPicon*)asset_list->get_selection(0, 0);
1468         return picon ? picon->plugin : 0;
1469 }
1470
1471 AssetPicon* AWindowGUI::selected_folder()
1472 {
1473         AssetPicon *picon = (AssetPicon*)folder_list->get_selection(0, 0);
1474         return picon;
1475 }
1476
1477
1478
1479
1480
1481
1482
1483
1484 AWindowDivider::AWindowDivider(MWindow *mwindow, AWindowGUI *gui, int x, int y, int w, int h)
1485  : BC_SubWindow(x, y, w, h)
1486 {
1487         this->mwindow = mwindow;
1488         this->gui = gui;
1489 }
1490 AWindowDivider::~AWindowDivider()
1491 {
1492 }
1493
1494 int AWindowDivider::button_press_event()
1495 {
1496         if( is_event_win() && cursor_inside() ) {
1497                 mwindow->session->current_operation = DRAG_PARTITION;
1498                 return 1;
1499         }
1500         return 0;
1501 }
1502
1503 int AWindowDivider::cursor_motion_event()
1504 {
1505         if( mwindow->session->current_operation == DRAG_PARTITION ) {
1506                 int wmin = 25;
1507                 int wmax = mwindow->session->awindow_w - mwindow->theme->adivider_w - wmin;
1508                 int fw = gui->get_relative_cursor_x();
1509                 if( fw > wmax ) fw = wmax;
1510                 if( fw < wmin ) fw = wmin;
1511                 mwindow->session->afolders_w = fw;
1512                 mwindow->theme->get_awindow_sizes(gui);
1513                 gui->reposition_objects();
1514                 gui->flush();
1515         }
1516         return 0;
1517 }
1518
1519 int AWindowDivider::button_release_event()
1520 {
1521         if( mwindow->session->current_operation == DRAG_PARTITION ) {
1522                 mwindow->session->current_operation = NO_OPERATION;
1523                 return 1;
1524         }
1525         return 0;
1526 }
1527
1528
1529
1530
1531
1532
1533 AWindowFolders::AWindowFolders(MWindow *mwindow, AWindowGUI *gui, int x, int y, int w, int h)
1534  : BC_ListBox(x, y, w, h,
1535                 mwindow->edl->session->folderlist_format == ASSETS_ICONS ?
1536                         LISTBOX_ICONS : LISTBOX_TEXT,
1537                 &gui->folders,    // Each column has an ArrayList of BC_ListBoxItems.
1538                 0,                // Titles for columns.  Set to 0 for no titles
1539                 0,                // width of each column
1540                 1,                // Total columns.
1541                 0,                // Pixel of top of window.
1542                 0,                // If this listbox is a popup window
1543                 LISTBOX_SINGLE,   // Select one item or multiple items
1544                 ICON_TOP,         // Position of icon relative to text of each item
1545                 1)                // Allow drags
1546 {
1547         this->mwindow = mwindow;
1548         this->gui = gui;
1549         set_drag_scroll(0);
1550 }
1551
1552 AWindowFolders::~AWindowFolders()
1553 {
1554 }
1555
1556 int AWindowFolders::selection_changed()
1557 {
1558         AssetPicon *picon = (AssetPicon*)get_selection(0, 0);
1559         if( picon ) {
1560                 gui->stop_vicon_drawing();
1561
1562                 if( get_button_down() && get_buttonpress() == 3 ) {
1563                         gui->folderlist_menu->update_titles();
1564                         gui->folderlist_menu->activate_menu();
1565                 }
1566
1567                 mwindow->edl->session->awindow_folder = picon->foldernum;
1568                 gui->asset_list->draw_background();
1569                 gui->async_update_assets();
1570
1571                 gui->start_vicon_drawing();
1572         }
1573         return 1;
1574 }
1575
1576 int AWindowFolders::button_press_event()
1577 {
1578         int result = 0;
1579
1580         result = BC_ListBox::button_press_event();
1581
1582         if( !result ) {
1583                 if( get_buttonpress() == 3 && is_event_win() && cursor_inside() ) {
1584                         gui->folderlist_menu->update_titles();
1585                         gui->folderlist_menu->activate_menu();
1586                         result = 1;
1587                 }
1588         }
1589
1590
1591         return result;
1592 }
1593
1594
1595
1596
1597
1598
1599
1600 AWindowAssets::AWindowAssets(MWindow *mwindow, AWindowGUI *gui, int x, int y, int w, int h)
1601  : BC_ListBox(x, y, w, h,
1602                 (mwindow->edl->session->assetlist_format == ASSETS_ICONS && gui->allow_iconlisting ) ?
1603                         LISTBOX_ICONS : LISTBOX_TEXT,
1604                 &gui->assets,     // Each column has an ArrayList of BC_ListBoxItems.
1605                 gui->asset_titles,// Titles for columns.  Set to 0 for no titles
1606                 mwindow->edl->session->asset_columns, // width of each column
1607                 1,                // Total columns.
1608                 0,                // Pixel of top of window.
1609                 0,                // If this listbox is a popup window
1610                 LISTBOX_MULTIPLE, // Select one item or multiple items
1611                 ICON_TOP,         // Position of icon relative to text of each item
1612                 -1)               // Allow drags, require shift for scrolling
1613 {
1614         this->mwindow = mwindow;
1615         this->gui = gui;
1616         set_drag_scroll(0);
1617         set_scroll_stretch(1, 1);
1618 }
1619
1620 AWindowAssets::~AWindowAssets()
1621 {
1622 }
1623
1624 int AWindowAssets::button_press_event()
1625 {
1626         int result = 0;
1627
1628         result = BC_ListBox::button_press_event();
1629
1630         if( !result && get_buttonpress() == 3 && is_event_win() && cursor_inside() ) {
1631                 BC_ListBox::deactivate_selection();
1632                 int folder = mwindow->edl->session->awindow_folder;
1633                 switch( folder ) {
1634                 case AW_AEFFECT_FOLDER:
1635                 case AW_VEFFECT_FOLDER:
1636                 case AW_ATRANSITION_FOLDER:
1637                 case AW_VTRANSITION_FOLDER:
1638                         gui->effectlist_menu->update();
1639                         gui->effectlist_menu->activate_menu();
1640                         break;
1641                 case AW_LABEL_FOLDER:
1642                         gui->labellist_menu->update();
1643                         gui->labellist_menu->activate_menu();
1644                         break;
1645                 case AW_CLIP_FOLDER:
1646                         gui->cliplist_menu->update();
1647                         gui->cliplist_menu->activate_menu();
1648                         break;
1649                 case AW_MEDIA_FOLDER:
1650                 case AW_PROXY_FOLDER:
1651                         gui->assetlist_menu->update_titles(folder==AW_MEDIA_FOLDER);
1652                         gui->assetlist_menu->activate_menu();
1653                         break;
1654                 }
1655                 result = 1;
1656         }
1657
1658         return result;
1659 }
1660
1661
1662 int AWindowAssets::handle_event()
1663 {
1664         AssetPicon *asset_picon = (AssetPicon *)get_selection(0, 0);
1665         if( !asset_picon ) return 0;
1666         switch( mwindow->edl->session->awindow_folder ) {
1667         case AW_AEFFECT_FOLDER:
1668         case AW_VEFFECT_FOLDER:
1669         case AW_ATRANSITION_FOLDER:
1670         case AW_VTRANSITION_FOLDER: return 1;
1671         }
1672         VWindow *vwindow = mwindow->vwindows.size() > DEFAULT_VWINDOW ?
1673                 mwindow->vwindows.get(DEFAULT_VWINDOW) : 0;
1674         if( !vwindow || !vwindow->is_running() ) return 1;
1675
1676         vwindow->gui->lock_window("AWindowAssets::handle_event");
1677         if( asset_picon->indexable )
1678                 vwindow->change_source(asset_picon->indexable);
1679         else if( asset_picon->edl )
1680                 vwindow->change_source(asset_picon->edl);
1681         vwindow->gui->unlock_window();
1682         return 1;
1683 }
1684
1685 int AWindowAssets::selection_changed()
1686 {
1687 // Show popup window
1688         AssetPicon *item;
1689         if( get_button_down() && get_buttonpress() == 3 &&
1690             (item = (AssetPicon*)get_selection(0, 0)) ) {
1691                 int folder = mwindow->edl->session->awindow_folder;
1692                 switch( folder ) {
1693                 case AW_AEFFECT_FOLDER:
1694                 case AW_VEFFECT_FOLDER:
1695                 case AW_ATRANSITION_FOLDER:
1696                 case AW_VTRANSITION_FOLDER:
1697                         gui->effectlist_menu->update();
1698                         gui->effectlist_menu->activate_menu();
1699                         break;
1700                 case AW_LABEL_FOLDER:
1701                         if( !item->label ) break;
1702                         gui->label_menu->activate_menu();
1703                         break;
1704                 case AW_CLIP_FOLDER:
1705                         if( !item->indexable && !item->edl ) break;
1706                         gui->clip_menu->update();
1707                         gui->clip_menu->activate_menu();
1708                         break;
1709                 default:
1710                         if( !item->indexable && !item->edl ) break;
1711                         gui->asset_menu->update();
1712                         gui->asset_menu->activate_menu();
1713                         break;
1714                 }
1715
1716                 BC_ListBox::deactivate_selection();
1717                 return 1;
1718         }
1719         else if( get_button_down() && get_buttonpress() == 1 &&
1720                  (item = (AssetPicon*)get_selection(0, 0)) ) {
1721                 VIcon *vicon = 0;
1722                 if( !gui->vicon_thread->viewing ) {
1723                         vicon = item->vicon;
1724                 }
1725                 gui->vicon_thread->set_view_popup(vicon);
1726
1727         }
1728         return 0;
1729 }
1730
1731 void AWindowAssets::draw_background()
1732 {
1733         clear_box(0,0,get_w(),get_h(),get_bg_surface());
1734         set_color(BC_WindowBase::get_resources()->audiovideo_color);
1735         set_font(LARGEFONT);
1736         int aw_folder = mwindow->edl->session->awindow_folder;
1737         if( aw_folder < 0 ) return;
1738         const char *aw_name = _(AWindowGUI::folder_names[aw_folder]);
1739         draw_text(get_w() - get_text_width(LARGEFONT, aw_name) - 4, 30,
1740                 aw_name, -1, get_bg_surface());
1741 }
1742
1743 int AWindowAssets::drag_start_event()
1744 {
1745         int collect_pluginservers = 0;
1746         int collect_assets = 0;
1747
1748         if( BC_ListBox::drag_start_event() ) {
1749                 switch( mwindow->edl->session->awindow_folder ) {
1750                 case AW_AEFFECT_FOLDER:
1751                         mwindow->session->current_operation = DRAG_AEFFECT;
1752                         collect_pluginservers = 1;
1753                         break;
1754                 case AW_VEFFECT_FOLDER:
1755                         mwindow->session->current_operation = DRAG_VEFFECT;
1756                         collect_pluginservers = 1;
1757                         break;
1758                 case AW_ATRANSITION_FOLDER:
1759                         mwindow->session->current_operation = DRAG_ATRANSITION;
1760                         collect_pluginservers = 1;
1761                         break;
1762                 case AW_VTRANSITION_FOLDER:
1763                         mwindow->session->current_operation = DRAG_VTRANSITION;
1764                         collect_pluginservers = 1;
1765                         break;
1766                 case AW_LABEL_FOLDER:
1767                         // do nothing!
1768                         break;
1769                 default:
1770                         mwindow->session->current_operation = DRAG_ASSET;
1771                         collect_assets = 1;
1772                         break;
1773                 }
1774
1775                 if( collect_pluginservers ) {
1776                         int i = 0;
1777                         mwindow->session->drag_pluginservers->remove_all();
1778                         while(1)
1779                         {
1780                                 AssetPicon *result = (AssetPicon*)get_selection(0, i++);
1781                                 if( !result ) break;
1782
1783                                 mwindow->session->drag_pluginservers->append(result->plugin);
1784                         }
1785                 }
1786
1787                 if( collect_assets ) {
1788                         gui->collect_assets();
1789                 }
1790
1791                 return 1;
1792         }
1793         return 0;
1794 }
1795
1796 int AWindowAssets::drag_motion_event()
1797 {
1798         BC_ListBox::drag_motion_event();
1799         unlock_window();
1800
1801         mwindow->gui->lock_window("AWindowAssets::drag_motion_event");
1802         mwindow->gui->drag_motion();
1803         mwindow->gui->unlock_window();
1804
1805         for( int i = 0; i < mwindow->vwindows.size(); i++ ) {
1806                 VWindow *vwindow = mwindow->vwindows.get(i);
1807                 if( !vwindow->is_running() ) continue;
1808                 vwindow->gui->lock_window("AWindowAssets::drag_motion_event");
1809                 vwindow->gui->drag_motion();
1810                 vwindow->gui->unlock_window();
1811         }
1812
1813         mwindow->cwindow->gui->lock_window("AWindowAssets::drag_motion_event");
1814         mwindow->cwindow->gui->drag_motion();
1815         mwindow->cwindow->gui->unlock_window();
1816
1817         lock_window("AWindowAssets::drag_motion_event");
1818         return 0;
1819 }
1820
1821 int AWindowAssets::drag_stop_event()
1822 {
1823         int result = 0;
1824
1825         result = gui->drag_stop();
1826
1827         unlock_window();
1828
1829         if( !result ) {
1830                 mwindow->gui->lock_window("AWindowAssets::drag_stop_event");
1831                 result = mwindow->gui->drag_stop();
1832                 mwindow->gui->unlock_window();
1833         }
1834
1835         if( !result ) {
1836                 for( int i = 0; !result && i < mwindow->vwindows.size(); i++ ) {
1837                         VWindow *vwindow = mwindow->vwindows.get(i);
1838                         if( !vwindow ) continue;
1839                         if( !vwindow->is_running() ) continue;
1840                         if( vwindow->gui->is_hidden() ) continue;
1841                         vwindow->gui->lock_window("AWindowAssets::drag_stop_event");
1842                         if( vwindow->gui->cursor_above() &&
1843                             vwindow->gui->get_cursor_over_window() ) {
1844                                 result = vwindow->gui->drag_stop();
1845                         }
1846                         vwindow->gui->unlock_window();
1847                 }
1848         }
1849
1850         if( !result ) {
1851                 mwindow->cwindow->gui->lock_window("AWindowAssets::drag_stop_event");
1852                 result = mwindow->cwindow->gui->drag_stop();
1853                 mwindow->cwindow->gui->unlock_window();
1854         }
1855
1856         lock_window("AWindowAssets::drag_stop_event");
1857
1858         if( result )
1859                 get_drag_popup()->set_animation(0);
1860
1861         BC_ListBox::drag_stop_event();
1862 // since NO_OPERATION is also defined in listbox, we have to reach for global scope...
1863         mwindow->session->current_operation = ::NO_OPERATION;
1864         return 1;
1865 }
1866
1867 int AWindowAssets::column_resize_event()
1868 {
1869         mwindow->edl->session->asset_columns[0] = get_column_width(0);
1870         mwindow->edl->session->asset_columns[1] = get_column_width(1);
1871         return 1;
1872 }
1873
1874 int AWindowAssets::focus_in_event()
1875 {
1876         gui->start_vicon_drawing();
1877         return 0;
1878 }
1879
1880 int AWindowAssets::focus_out_event()
1881 {
1882         gui->stop_vicon_drawing();
1883         return BC_ListBox::focus_out_event();
1884 }
1885
1886 AWindowSearchTextBox::AWindowSearchTextBox(AWindowSearchText *search_text, int x, int y, int w)
1887  : BC_TextBox(x, y, w, 1, "")
1888 {
1889         this->search_text = search_text;
1890 }
1891
1892 int AWindowSearchTextBox::handle_event()
1893 {
1894         return search_text->handle_event();
1895 }
1896
1897 AWindowSearchText::AWindowSearchText(MWindow *mwindow, AWindowGUI *gui, int x, int y)
1898 {
1899         this->mwindow = mwindow;
1900         this->gui = gui;
1901         this->x = x;
1902         this->y = y;
1903 }
1904
1905 void AWindowSearchText::create_objects()
1906 {
1907         int x1 = x, y1 = y, margin = 10;
1908         gui->add_subwindow(text_title = new BC_Title(x1, y1, _("Search:")));
1909         x1 += text_title->get_w() + margin;
1910         int w1 = gui->get_w() - x1 - 2*margin;
1911         gui->add_subwindow(text_box = new AWindowSearchTextBox(this, x1, y1, w1));
1912 }
1913
1914 int AWindowSearchText::handle_event()
1915 {
1916         gui->async_update_assets();
1917         return 1;
1918 }
1919
1920 int AWindowSearchText::get_w()
1921 {
1922         return text_box->get_w() + text_title->get_w() + 10;
1923 }
1924
1925 int AWindowSearchText::get_h()
1926 {
1927         return bmax(text_box->get_h(),text_title->get_h());
1928 }
1929
1930 void AWindowSearchText::reposition_window(int x, int y, int w)
1931 {
1932         int x1 = x, y1 = y, margin = 10;
1933         text_title->reposition_window(x1, y1);
1934         x1 += text_title->get_w() + margin;
1935         int w1 = gui->get_w() - x1 - 2*margin;
1936         text_box->reposition_window(x1, y1, w1);
1937 }
1938
1939 const char *AWindowSearchText::get_text()
1940 {
1941         return text_box->get_text();
1942 }
1943
1944 void AWindowSearchText::clear()
1945 {
1946         text_box->update("");
1947 }
1948
1949 AWindowNewFolder::AWindowNewFolder(MWindow *mwindow, AWindowGUI *gui, int x, int y)
1950  : BC_Button(x, y, mwindow->theme->newbin_data)
1951 {
1952         this->mwindow = mwindow;
1953         this->gui = gui;
1954         set_tooltip(_("New bin"));
1955 }
1956
1957 int AWindowNewFolder::handle_event()
1958 {
1959         gui->newfolder_thread->start_new_folder();
1960         return 1;
1961 }
1962
1963 AWindowDeleteFolder::AWindowDeleteFolder(MWindow *mwindow, AWindowGUI *gui, int x, int y)
1964  : BC_Button(x, y, mwindow->theme->deletebin_data)
1965 {
1966         this->mwindow = mwindow;
1967         this->gui = gui;
1968         set_tooltip(_("Delete bin"));
1969 }
1970
1971 int AWindowDeleteFolder::handle_event()
1972 {
1973         if( gui->folder_list->get_selection(0, 0) ) {
1974                 BC_ListBoxItem *folder = gui->folder_list->get_selection(0, 0);
1975                 mwindow->delete_folder(folder->get_text());
1976         }
1977         return 1;
1978 }
1979
1980 AWindowRenameFolder::AWindowRenameFolder(MWindow *mwindow, AWindowGUI *gui, int x, int y)
1981  : BC_Button(x, y, mwindow->theme->renamebin_data)
1982 {
1983         this->mwindow = mwindow;
1984         this->gui = gui;
1985         set_tooltip(_("Rename bin"));
1986 }
1987
1988 int AWindowRenameFolder::handle_event()
1989 {
1990         return 1;
1991 }
1992
1993 AWindowDeleteDisk::AWindowDeleteDisk(MWindow *mwindow, AWindowGUI *gui, int x, int y)
1994  : BC_Button(x, y, mwindow->theme->deletedisk_data)
1995 {
1996         this->mwindow = mwindow;
1997         this->gui = gui;
1998         set_tooltip(_("Delete asset from disk"));
1999 }
2000
2001 int AWindowDeleteDisk::handle_event()
2002 {
2003         return 1;
2004 }
2005
2006 AWindowDeleteProject::AWindowDeleteProject(MWindow *mwindow, AWindowGUI *gui, int x, int y)
2007  : BC_Button(x, y, mwindow->theme->deleteproject_data)
2008 {
2009         this->mwindow = mwindow;
2010         this->gui = gui;
2011         set_tooltip(_("Delete asset from project"));
2012 }
2013
2014 int AWindowDeleteProject::handle_event()
2015 {
2016         return 1;
2017 }
2018
2019 // AWindowInfo::AWindowInfo(MWindow *mwindow, AWindowGUI *gui, int x, int y)
2020 //  : BC_Button(x, y, mwindow->theme->infoasset_data)
2021 // {
2022 //      this->mwindow = mwindow;
2023 //      this->gui = gui;
2024 //      set_tooltip(_("Edit information on asset"));
2025 // }
2026 // 
2027 // int AWindowInfo::handle_event()
2028 // {
2029 //      int cur_x, cur_y;
2030 //      gui->get_abs_cursor(cur_x, cur_y, 0);
2031 //      gui->awindow->asset_edit->edit_asset(gui->selected_asset(), cur_x, cur_y);
2032 //      return 1;
2033 // }
2034
2035 AWindowRedrawIndex::AWindowRedrawIndex(MWindow *mwindow, AWindowGUI *gui, int x, int y)
2036  : BC_Button(x, y, mwindow->theme->redrawindex_data)
2037 {
2038         this->mwindow = mwindow;
2039         this->gui = gui;
2040         set_tooltip(_("Redraw index"));
2041 }
2042
2043 int AWindowRedrawIndex::handle_event()
2044 {
2045         return 1;
2046 }
2047
2048 AWindowPaste::AWindowPaste(MWindow *mwindow, AWindowGUI *gui, int x, int y)
2049  : BC_Button(x, y, mwindow->theme->pasteasset_data)
2050 {
2051         this->mwindow = mwindow;
2052         this->gui = gui;
2053         set_tooltip(_("Paste asset on recordable tracks"));
2054 }
2055
2056 int AWindowPaste::handle_event()
2057 {
2058         return 1;
2059 }
2060
2061 AWindowAppend::AWindowAppend(MWindow *mwindow, AWindowGUI *gui, int x, int y)
2062  : BC_Button(x, y, mwindow->theme->appendasset_data)
2063 {
2064         this->mwindow = mwindow;
2065         this->gui = gui;
2066         set_tooltip(_("Append asset in new tracks"));
2067 }
2068
2069 int AWindowAppend::handle_event()
2070 {
2071         return 1;
2072 }
2073
2074 AWindowView::AWindowView(MWindow *mwindow, AWindowGUI *gui, int x, int y)
2075  : BC_Button(x, y, mwindow->theme->viewasset_data)
2076 {
2077         this->mwindow = mwindow;
2078         this->gui = gui;
2079         set_tooltip(_("View asset"));
2080 }
2081
2082 int AWindowView::handle_event()
2083 {
2084         return 1;
2085 }
2086
2087 AddTools::AddTools(MWindow *mwindow, AWindowGUI *gui, int x, int y, const char *title)
2088  : BC_PopupMenu(x, y, BC_Title::calculate_w(gui, title, MEDIUMFONT)+8, title, -1, 0, 4)
2089 {
2090         this->mwindow = mwindow;
2091         this->gui = gui;
2092 }
2093
2094 void AddTools::create_objects()
2095 {
2096         uint64_t vis = 0;
2097         add_item(new AddPluginItem(this, "ladspa", PLUGIN_LADSPA_ID));
2098         vis |= 1 << PLUGIN_LADSPA_ID;
2099         add_item(new AddPluginItem(this, "ffmpeg", PLUGIN_FFMPEG_ID));
2100         vis |= 1 << PLUGIN_FFMPEG_ID;
2101         for( int i=0; i<MWindow::plugindb->size(); ++i ) {
2102                 PluginServer *plugin = MWindow::plugindb->get(i);
2103                 if( !plugin->audio && !plugin->video ) continue;
2104                 int idx = plugin->dir_idx;
2105                 uint32_t msk = 1 << idx;
2106                 if( (msk & vis) != 0 ) continue;
2107                 vis |= msk;
2108                 char parent[BCTEXTLEN];
2109                 strcpy(parent, plugin->path);
2110                 char *bp = strrchr(parent, '/');
2111                 if( bp ) { *bp = 0;  bp = strrchr(parent, '/'); }
2112                 if( !bp ) bp = parent; else ++bp;
2113                 add_item(new AddPluginItem(this, bp, idx));
2114         }
2115 }
2116
2117 #if 0
2118 // plugin_dirs list from toplevel makefile include plugin_defs
2119 N_("ladspa")
2120 N_("ffmpeg")
2121 N_("audio_tools")
2122 N_("audio_transitions")
2123 N_("blending")
2124 N_("colors")
2125 N_("exotic")
2126 N_("transforms")
2127 N_("tv_effects")
2128 N_("video_tools")
2129 N_("video_transitions")
2130 #endif
2131
2132 AddPluginItem::AddPluginItem(AddTools *menu, char const *text, int idx)
2133  : BC_MenuItem(_(text))
2134 {
2135         this->menu = menu;
2136         this->idx = idx;
2137         uint64_t msk = (uint64_t)1 << idx, vis = menu->gui->plugin_visibility;
2138         int chk = (msk & vis) ? 1 : 0;
2139         set_checked(chk);
2140 }
2141
2142 int AddPluginItem::handle_event()
2143 {
2144         int chk = get_checked() ^ 1;
2145         set_checked(chk);
2146         uint64_t msk = (uint64_t)1 << idx, vis = menu->gui->plugin_visibility;
2147         menu->gui->plugin_visibility = chk ? vis | msk : vis & ~msk;
2148         menu->gui->update_effects();
2149         menu->gui->save_defaults(menu->mwindow->defaults);
2150         menu->gui->async_update_assets();
2151         return 1;
2152 }
2153
2154 AVIconDrawing::AVIconDrawing(AWindowGUI *agui, int x, int y, VFrame **images)
2155  : BC_Toggle(x, y, images, agui->vicon_drawing)
2156 {
2157         this->agui = agui;
2158         set_tooltip(_("draw vicons"));
2159 }
2160
2161 void AVIconDrawing::calculate_geometry(AWindowGUI *agui, VFrame **images, int *ww, int *hh)
2162 {
2163         int text_line = -1, toggle_x = -1, toggle_y = -1;
2164         int text_x = -1, text_y = -1, text_w = -1, text_h = -1;
2165         BC_Toggle::calculate_extents(agui, images, 1,
2166                 &text_line, ww, hh, &toggle_x, &toggle_y,
2167                 &text_x, &text_y, &text_w, &text_h, "", MEDIUMFONT);
2168 }
2169
2170 AVIconDrawing::~AVIconDrawing()
2171 {
2172 }
2173
2174 int AVIconDrawing::handle_event()
2175 {
2176         agui->vicon_drawing = get_value();
2177         if( agui->vicon_drawing )
2178                 agui->start_vicon_drawing();
2179         else
2180                 agui->stop_vicon_drawing();
2181         return 1;
2182 }
2183
2184
2185 AWindowListFormat::AWindowListFormat(MWindow *mwindow, AWindowGUI *gui)
2186  : BC_MenuItem("")
2187 {
2188         this->mwindow = mwindow;
2189         this->gui = gui;
2190 }
2191
2192 int AWindowListFormat::handle_event()
2193 {
2194         gui->stop_vicon_drawing();
2195
2196         EDLSession *session = mwindow->edl->session;
2197         switch( session->assetlist_format ) {
2198         case ASSETS_TEXT:
2199                 session->assetlist_format = ASSETS_ICONS;
2200                 break;
2201         case ASSETS_ICONS:
2202                 session->assetlist_format = ASSETS_TEXT;
2203                 break;
2204         }
2205
2206         gui->asset_list->update_format(session->assetlist_format, 1);
2207         if( !mwindow->awindow->gui->allow_iconlisting ) {
2208                 mwindow->edl->session->assetlist_format = ASSETS_TEXT;
2209         }
2210
2211         gui->start_vicon_drawing();
2212         return 1;
2213 }
2214
2215 void AWindowListFormat::update()
2216 {
2217         set_text(mwindow->edl->session->assetlist_format == ASSETS_TEXT ?
2218                 (char*)_("Display icons") : (char*)_("Display text"));
2219 }
2220
2221 AWindowListSort::AWindowListSort(MWindow *mwindow, AWindowGUI *gui)
2222  : BC_MenuItem(_("Sort items"))
2223 {
2224         this->mwindow = mwindow;
2225         this->gui = gui;
2226 }
2227
2228 int AWindowListSort::handle_event()
2229 {
2230         gui->sort_assets(0);
2231         return 1;
2232 }
2233