3 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "awindowgui.h"
23 #include "binfolder.h"
28 #include "indexable.h"
30 #include "localsession.h"
31 #include "mainerror.h"
32 #include "mainsession.h"
38 const char *BinFolderEnabled::types[] = {
46 const char *BinFolderTarget::types[] = {
59 const char *BinFolderOp::types[] = {
71 const char *sfx, *sfxs;
74 { N_("min"), N_("mins"), 60, },
75 { N_("hour"), N_("hours"), 60*60, },
76 { N_("day"), N_("days"), 24*60*60, },
77 { N_("week"), N_("weeks"), 24*60*60*7, },
78 { N_("month"), N_("months"), 24*60*60*31, },
79 { N_("year"), N_("years"), 24*60*60*365.25, },
81 #define SCAN_RANGE_DAYS 2
82 #define DBL_INF 9007199254740991.
84 static int scan_inf(const char *cp, char *&bp)
87 const char *inf = _("inf");
88 const int linf = strlen(inf);
89 if( strncasecmp(cp,inf,linf) ) return 0;
90 bp = (char *)(cp + linf);
94 static double scan_no(const char *cp, char *&bp)
96 while( *cp == ' ' ) ++cp;
97 if( scan_inf(cp, bp) ) return DBL_INF;
98 if( *cp == '+' ) return 0;
99 double v = strtod(cp, &bp);
101 case 'T': v *= 1099511627776.; break;
102 case 't': v *= 1e12; break;
103 case 'G': v *= 1073741824.; break;
104 case 'g': v *= 1e9; break;
105 case 'M': v *= 1048576.; break;
106 case 'm': v *= 1e6; break;
107 case 'K': v *= 1024.; break;
108 case 'k': v *= 1e3; break;
115 static void scan_around(const char *cp, char *&bp, double &v, double &a)
118 double sv = scan_no(cp, bp);
119 if( bp > cp ) v = sv;
121 double sa = scan_no(cp=bp+1, bp);
122 if( bp > cp ) a = sa;
126 static void show_no(double v, char *&cp, char *ep, const char *fmt="%0.0f")
129 cp += snprintf(cp, ep-cp, "%s", _("inf"));
133 static const struct { double radix; const char *sfx; } sfxs[] = {
134 { 1024., "K" }, { 1e3, "k" },
135 { 1048576., "M" }, { 1e6, "m" },
136 { 1073741824., "G" }, { 1e9, "g" },
137 { 1099511627776., "T" }, { 1e12, "t" },
139 for( int i=sizeof(sfxs)/sizeof(sfxs[0]); --i>=0; ) {
140 if( v < sfxs[i].radix ) continue;
141 if( fmod(v, sfxs[i].radix) == 0 ) {
147 cp += snprintf(cp, ep-cp, fmt, v);
148 if( sfx ) cp += snprintf(cp, ep-cp, "%s", sfx);
151 static double scan_duration(const char *cp, char *&bp)
153 if( scan_inf(cp, bp) ) return DBL_INF;
156 double v = strtod(cp, &bp);
157 if( cp >= bp ) break;
158 int k = sizeof(scan_ranges)/sizeof(scan_ranges[0]);
160 const char *tsfx = _(scan_ranges[k].sfx);
161 int lsfx = strlen(tsfx), msfx = strncasecmp(bp, tsfx, lsfx);
162 const char *tsfxs = _(scan_ranges[k].sfxs);
163 int lsfxs = strlen(tsfxs), msfxs = strncasecmp(bp, tsfxs, lsfxs);
164 int len = !msfx && !msfxs ? (lsfx > lsfxs ? lsfx : lsfxs) :
165 !msfx ? lsfx : !msfxs ? lsfxs : -1;
167 secs += v * scan_ranges[k].radix;
173 int hour = 0, mins = 0;
174 if( *bp == ':' && v == (int)v ) {
176 v = strtod(cp=bp+1, &bp);
177 if( *bp == ':' && v == (int)v ) {
178 hour = mins; mins = v;
179 v = strtod(cp=bp+1, &bp);
182 secs += hour*3600 + mins*60 + v;
184 while( *bp && (*bp<'0' || *bp>'9') ) ++bp;
190 static void show_duration(double v, char *&cp, char *ep)
193 cp += snprintf(cp, ep-cp, "%s", _("inf"));
196 double secs = v; char *bp = cp;
197 int k = sizeof(scan_ranges)/sizeof(scan_ranges[0]);
198 while( --k >= SCAN_RANGE_DAYS ) {
199 if( secs >= scan_ranges[k].radix ) {
200 int v = secs/scan_ranges[k].radix;
201 secs -= v * scan_ranges[k].radix;
202 cp += snprintf(cp, ep-cp,"%d%s", v,
203 v > 1 ? _(scan_ranges[k].sfxs) : _(scan_ranges[k].sfx));
207 if( cp > bp && cp < ep ) *cp++ = ' ';
208 int64_t n = secs; int hour = n/3600, min = (n/60)%60, sec = n%60;
209 if( hour > 0 ) cp += snprintf(cp, ep-cp, "%d:", hour);
210 if( hour > 0 || min > 0 ) cp += snprintf(cp, ep-cp, "%02d:", min);
211 cp += snprintf(cp, ep-cp, n>=10 ? "%02d" : "%d", sec);
215 static int64_t scan_date(const char *cp, char *&bp)
217 double year=0, mon=1, day=1;
218 double hour=0, min=0;
220 while( *bp == ' ' ) ++bp;
221 if( *bp == '+' ) return 0;
222 double secs = strtod(cp=bp, &bp);
223 if( *bp == '/' && secs == (int)secs ) {
224 year = secs; secs = 0;
225 mon = strtod(cp=bp+1, &bp);
226 if( *bp == '/' && mon == (int)mon ) {
227 day = strtod(cp=bp+1, &bp);
228 while( *bp == ' ' ) ++bp;
229 secs = *bp != '+' ? strtod(cp=bp, &bp) : 0;
232 if( *bp == ':' && secs == (int)secs ) {
233 hour = secs; secs = 0;
234 min = strtod(cp=bp+1, &bp);
235 if( *bp == ':' && min == (int)min ) {
236 secs = strtod(cp=bp+1, &bp);
239 struct tm ttm; memset(&ttm, 0, sizeof(ttm));
240 ttm.tm_year = year-1900; ttm.tm_mon = mon-1; ttm.tm_mday = day;
241 ttm.tm_hour = hour; ttm.tm_min = min; ttm.tm_sec = secs;
242 time_t t = mktime(&ttm);
246 static void show_date(time_t t, char *&cp, char *ep)
248 struct tm tm; localtime_r(&t, &tm);
249 cp += snprintf(cp, ep-cp, "%04d/%02d/%02d %02d:%02d:%02d",
250 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
251 tm.tm_hour, tm.tm_min, tm.tm_sec);
254 double BinFolder::matches_indexable(Indexable *idxbl)
257 for( int i=0; i<filters.size(); ++i ) {
258 BinFolderFilter *filter = filters[i];
259 double ret = filter->op->test(filter->target, idxbl);
260 switch( filter->enabled->type ) {
261 case FOLDER_ENABLED_OR: {
262 if( result < 0 ) result = ret;
264 case FOLDER_ENABLED_AND: {
265 if( ret < 0 ) result = -1;
267 case FOLDER_ENABLED_OR_NOT: {
268 if( ret < 0 ) result = 1;
270 case FOLDER_ENABLED_AND_NOT: {
271 if( ret >= 0 ) result = -1;
279 BinFolder::BinFolder(int awindow_folder, int is_clips, const char *title)
281 this->awindow_folder = awindow_folder;
282 this->is_clips = is_clips;
283 char *bp = this->title;
284 int len = sizeof(this->title);
285 while( --len>0 && *title ) *bp++ = *title++;
289 BinFolder::BinFolder(BinFolder &that)
294 void BinFolder::copy_from(BinFolder *that)
296 strcpy(title, that->title);
297 awindow_folder = that->awindow_folder;
298 is_clips = that->is_clips;
299 filters.copy_from(&that->filters);
302 BinFolder::~BinFolder()
306 void BinFolder::save_xml(FileXML *file)
308 file->tag.set_title("FOLDER");
309 file->tag.set_property("TITLE", title);
310 file->tag.set_property("AWINDOW_FOLDER", awindow_folder);
311 file->tag.set_property("IS_CLIPS", is_clips);
313 file->append_newline();
314 for( int i=0; i<filters.size(); ++i )
315 filters[i]->save_xml(file);
316 file->tag.set_title("/FOLDER");
318 file->append_newline();
321 int BinFolder::load_xml(FileXML *file)
324 file->tag.get_property("TITLE", title);
325 awindow_folder = file->tag.get_property("AWINDOW_FOLDER", -1);
326 is_clips = file->tag.get_property("IS_CLIPS", 0);
327 filters.remove_all_objects();
330 while( !(ret=file->read_tag()) ) {
331 if( file->tag.title_is("/FOLDER") ) break;
332 if( file->tag.title_is("FILTER") ) {
333 BinFolderFilter *filter = new BinFolderFilter();
334 filter->load_xml(file);
335 filters.append(filter);
341 int BinFolder::add_patterns(ArrayList<Indexable*> *drag_idxbls, int use_basename)
343 int n = drag_idxbls->size();
347 for( int i=0; i<n; ++i ) {
348 idxbl = drag_idxbls->get(i);
349 if( !idxbl->is_asset &&
350 idxbl->folder_no == AW_PROXY_FOLDER )
353 const char *tp = idxbl->get_title();
354 if( use_basename && idxbl->is_asset ) {
355 const char *cp = strrchr(tp, '/');
356 if( cp ) tp = cp + 1;
357 len += 1; // "*" + fn
359 len += strlen(tp) + 1;
362 char *pats = new char[len+1], *bp = pats;
363 for( int i=0; i<n; ++i ) {
364 idxbl = drag_idxbls->get(i);
365 if( !idxbl->is_asset &&
366 idxbl->folder_no == AW_PROXY_FOLDER )
368 if( i > 0 ) *bp++ = '\n';
369 const char *tp = idxbl->get_title();
370 if( use_basename && idxbl->is_asset ) {
371 const char *cp = strrchr(tp, '/');
372 if( cp ) tp = cp + 1;
375 while( *tp ) *bp++ = *tp++;
378 // new pattern filter
379 BinFolderFilter *filter = new BinFolderFilter();
380 filter->update_enabled(FOLDER_ENABLED_OR);
381 filter->update_target(FOLDER_TARGET_PATTERNS);
382 filter->update_op(FOLDER_OP_MATCHES);
383 BinFolderTargetPatterns *patterns = (BinFolderTargetPatterns *)(filter->target);
384 patterns->update(pats);
385 filters.append(filter);
390 double BinFolders::matches_indexable(int folder, Indexable *idxbl)
393 BinFolder *bin_folder = 0;
394 while( --k>=0 && (bin_folder=get(k)) && bin_folder->awindow_folder!=folder );
395 if( k < 0 ) return -1;
396 if( bin_folder->is_clips && idxbl->folder_no != AW_CLIP_FOLDER ) return -1;
397 if( !bin_folder->is_clips && idxbl->folder_no != AW_MEDIA_FOLDER ) return -1;
398 return bin_folder->matches_indexable(idxbl);
401 void BinFolders::save_xml(FileXML *file)
403 file->tag.set_title("FOLDERS");
405 file->append_newline();
406 for( int i=0; i<size(); ++i )
407 get(i)->save_xml(file);
408 file->tag.set_title("/FOLDERS");
410 file->append_newline();
413 int BinFolders::load_xml(FileXML *file)
417 while( !(ret=file->read_tag()) ) {
418 if( file->tag.title_is("/FOLDERS") ) break;
419 if( file->tag.title_is("FOLDER") ) {
420 BinFolder *folder = new BinFolder(-1, -1, "folder");
421 folder->load_xml(file);
428 void BinFolders::copy_from(BinFolders *that)
431 for( int i=0; i<that->size(); ++i )
432 append(new BinFolder(*that->get(i)));
436 BinFolderFilter::BinFolderFilter()
443 BinFolderFilter::~BinFolderFilter()
451 void BinFolderFilter::update_enabled(int type)
454 enabled = new BinFolderEnabled(this, type);
456 enabled->update(type);
459 void BinFolderFilter::update_target(int type)
462 if( target->type == type ) return;
463 delete target; target = 0;
466 case FOLDER_TARGET_PATTERNS: target = new BinFolderTargetPatterns(this); break;
467 case FOLDER_TARGET_FILE_SIZE: target = new BinFolderTargetFileSize(this); break;
468 case FOLDER_TARGET_MOD_TIME: target = new BinFolderTargetTime(this); break;
469 case FOLDER_TARGET_TRACK_TYPE: target = new BinFolderTargetTrackType(this); break;
470 case FOLDER_TARGET_WIDTH: target = new BinFolderTargetWidth(this); break;
471 case FOLDER_TARGET_HEIGHT: target = new BinFolderTargetHeight(this); break;
472 case FOLDER_TARGET_FRAMERATE: target = new BinFolderTargetFramerate(this); break;
473 case FOLDER_TARGET_SAMPLERATE: target = new BinFolderTargetSamplerate(this); break;
474 case FOLDER_TARGET_CHANNELS: target = new BinFolderTargetChannels(this); break;
475 case FOLDER_TARGET_DURATION: target = new BinFolderTargetDuration(this); break;
479 void BinFolderFilter::update_op(int type)
482 if( op->type == type ) return;
486 case FOLDER_OP_AROUND: op = new BinFolderOpAround(this); break;
487 case FOLDER_OP_EQ: op = new BinFolderOpEQ(this); break;
488 case FOLDER_OP_GE: op = new BinFolderOpGE(this); break;
489 case FOLDER_OP_GT: op = new BinFolderOpGT(this); break;
490 case FOLDER_OP_NE: op = new BinFolderOpNE(this); break;
491 case FOLDER_OP_LE: op = new BinFolderOpLE(this); break;
492 case FOLDER_OP_LT: op = new BinFolderOpLT(this); break;
493 case FOLDER_OP_MATCHES: op = new BinFolderOpMatches(this); break;
497 void BinFolderFilter::update_value(const char *text)
500 value = new BinFolderValue(this, text);
505 void BinFolderFilter::save_xml(FileXML *file)
507 file->tag.set_title("FILTER");
508 file->tag.set_property("ENABLED", enabled->type);
509 file->tag.set_property("OP", op->type);
510 file->tag.set_property("TARGET", target->type);
511 target->save_xml(file);
513 if( target->type == FOLDER_TARGET_PATTERNS )
514 file->append_text(((BinFolderTargetPatterns *)target)->text);
515 file->tag.set_title("/FILTER");
517 file->append_newline();
520 int BinFolderFilter::load_xml(FileXML *file)
522 int enabled_type = file->tag.get_property("ENABLED", FOLDER_ENABLED_AND);
523 int op_type = file->tag.get_property("OP", FOLDER_OP_MATCHES);
524 int target_type = file->tag.get_property("TARGET", FOLDER_TARGET_PATTERNS);
526 file->read_text_until("/FILTER", &data, 0);
527 update_enabled(enabled_type);
528 update_target(target_type);
530 target->load_xml(file);
531 if( target->type == FOLDER_TARGET_PATTERNS )
532 ((BinFolderTargetPatterns *)target)->update(data.cstr());
536 void BinFolderFilters::copy_from(BinFolderFilters *that)
539 for( int i=0; i<that->size(); ++i ) {
540 BinFolderFilter *filter = new BinFolderFilter();
541 BinFolderFilter *tp = that->get(i);
542 filter->update_enabled(tp->enabled->type);
543 filter->update_target(tp->target->type);
544 filter->update_op(tp->op->type);
545 filter->target->copy_from(tp->target);
546 filter->op->copy_from(tp->op);
551 double BinFolderOp::around(double v, double a)
553 if( type != FOLDER_OP_AROUND ) return v;
555 return a>0 ? v/a : v;
558 // string theory: Feynman, Einstein and Schrodinger string compare
559 // Feynman: try all possible matches, weight the outcomes
560 // Schrodinger: it may be there several ways at the same time
561 // Einstein: the more matches there are, the heavier it is
562 double BinFolderOp::around(const char *ap, const char *bp)
564 int64_t v = 0, vmx = 0;
565 int alen = strlen(ap), blen = strlen(bp);
567 const char *cp = ap; ap = bp; bp = cp;
568 int clen = alen; alen = blen; blen = clen;
570 // 4 level loop (with strncmp), don't try long strings
571 for( int n=0; ++n<=alen; ) {
573 int an = alen-n+1, bn = blen-n+1;
574 for( int i=an; --i>=0; ) {
575 for( int j=bn; --j>=0; ) {
576 if( !strncmp(ap+i, bp+j, n) ) v += nn;
581 return !vmx ? -1 : 1 - v / (double)vmx;
585 double BinFolderOp::compare(BinFolderTarget *target, Indexable *idxbl)
588 switch( target->type ) {
589 case FOLDER_TARGET_PATTERNS: {
590 BinFolderTargetPatterns *tgt = (BinFolderTargetPatterns *)target;
592 case FOLDER_OP_AROUND: {
593 const char *cp = idxbl->path;
594 const char *bp = strrchr(cp, '/');
595 if( bp ) cp = bp + 1;
596 v = around(cp, tgt->text);
598 case FOLDER_OP_EQ: case FOLDER_OP_GT: case FOLDER_OP_GE:
599 case FOLDER_OP_NE: case FOLDER_OP_LT: case FOLDER_OP_LE: {
600 const char *cp = idxbl->path;
601 const char *bp = strrchr(cp, '/');
602 if( bp ) cp = bp + 1;
603 v = strcmp(cp, tgt->text);
605 case FOLDER_OP_MATCHES: {
607 char *cp = tgt->text;
608 while( v < 0 && *cp ) {
609 char pattern[BCTEXTLEN], *bp = pattern, ch;
610 while( *cp && (ch=*cp++)!='\n' ) *bp++ = ch;
612 if( !pattern[0] ) continue;
613 const char *title = idxbl->get_title();
614 if( !FileSystem::test_filter(title, pattern) )
620 case FOLDER_TARGET_FILE_SIZE: {
621 BinFolderTargetFileSize *tgt = (BinFolderTargetFileSize *)target;
622 int64_t file_size = !idxbl->is_asset ? -1 :
623 FileSystem::get_size(idxbl->path);
624 v = around(file_size - tgt->file_size, tgt->around);
626 case FOLDER_TARGET_MOD_TIME: {
627 BinFolderTargetTime *tgt = (BinFolderTargetTime *)target;
629 if( stat(idxbl->path, &st) ) break;
630 v = around(st.st_mtime - tgt->mtime, tgt->around);
632 case FOLDER_TARGET_TRACK_TYPE: {
633 BinFolderTargetTrackType *tgt = (BinFolderTargetTrackType *)target;
634 int want_audio = (tgt->data_types&(1<<TRACK_AUDIO)) ? 1 : 0;
635 int has_audio = idxbl->have_audio();
636 if( want_audio != has_audio ) break;
637 int want_video = (tgt->data_types&(1<<TRACK_VIDEO)) ? 1 : 0;
638 int has_video = idxbl->have_video();
639 if( want_video != has_video ) break;
642 case FOLDER_TARGET_WIDTH: {
643 BinFolderTargetWidth *tgt = (BinFolderTargetWidth *)target;
644 int w = idxbl->get_w();
645 v = around(w - tgt->width, tgt->around);
647 case FOLDER_TARGET_HEIGHT: {
648 BinFolderTargetHeight *tgt = (BinFolderTargetHeight *)target;
649 int h = idxbl->get_h();
650 v = around(h - tgt->height, tgt->around);
652 case FOLDER_TARGET_FRAMERATE: {
653 BinFolderTargetFramerate *tgt = (BinFolderTargetFramerate *)target;
654 double rate = idxbl->get_frame_rate();
655 v = around(rate - tgt->framerate, tgt->around);
657 case FOLDER_TARGET_SAMPLERATE: {
658 BinFolderTargetSamplerate *tgt = (BinFolderTargetSamplerate *)target;
659 double rate = idxbl->get_sample_rate();
660 v = around(rate - tgt->samplerate, tgt->around);
662 case FOLDER_TARGET_CHANNELS: {
663 BinFolderTargetChannels *tgt = (BinFolderTargetChannels *)target;
664 double chs = idxbl->get_audio_channels();
665 v = around(chs - tgt->channels, tgt->around);
667 case FOLDER_TARGET_DURATION: {
668 BinFolderTargetDuration *tgt = (BinFolderTargetDuration *)target;
670 double video_rate = !idxbl->have_video() ? 0 : idxbl->get_frame_rate();
671 if( video_rate > 0 ) {
672 double video_length = idxbl->get_video_frames() / video_rate;
673 if( video_length > len ) len = video_length;
675 double audio_rate = !idxbl->have_audio() ? 0 : idxbl->get_sample_rate();
676 if( audio_rate > 0 ) {
677 double audio_length = idxbl->get_audio_samples() / audio_rate;
678 if( audio_length > len ) len = audio_length;
680 v = around(len - tgt->duration, tgt->around);
687 BinFolderEnabled::BinFolderEnabled(BinFolderFilter *filter, int type)
688 : BC_ListBoxItem(_(types[type]))
690 this->filter = filter;
694 BinFolderEnabled::~BinFolderEnabled()
698 void BinFolderEnabled::update(int type)
701 set_text(_(types[type]));
704 BinFolderEnabledType::BinFolderEnabledType(int no)
705 : BC_MenuItem(_(BinFolderEnabled::types[no]))
709 BinFolderEnabledType::~BinFolderEnabledType()
713 int BinFolderEnabledType::handle_event()
715 BinFolderEnabledPopup *enabled_popup = (BinFolderEnabledPopup *)get_popup_menu();
716 BinFolderList *folder_list = enabled_popup->folder_list;
717 int i = folder_list->get_selection_number(FOLDER_COLUMN_ENABLE, 0);
719 BinFolder *folder = folder_list->folder;
720 BinFolderFilter *filter = folder->filters[i];
721 filter->update_enabled(no);
722 folder_list->create_list();
727 BinFolderEnabledPopup::BinFolderEnabledPopup(BinFolderList *folder_list)
728 : BC_PopupMenu(0, 0, 0, "", 0)
730 this->folder_list = folder_list;
734 void BinFolderEnabledPopup::create_objects()
736 add_item(new BinFolderEnabledType(FOLDER_ENABLED_OFF));
737 add_item(new BinFolderEnabledType(FOLDER_ENABLED_AND));
738 add_item(new BinFolderEnabledType(FOLDER_ENABLED_OR));
739 add_item(new BinFolderEnabledType(FOLDER_ENABLED_AND_NOT));
740 add_item(new BinFolderEnabledType(FOLDER_ENABLED_OR_NOT));
743 void BinFolderEnabledPopup::activate_menu(BC_ListBoxItem *item)
745 this->enabled = (BinFolderEnabled *)item;
746 BC_PopupMenu::activate_menu();
749 BinFolderTarget::BinFolderTarget(BinFolderFilter *filter, int type)
750 : BC_ListBoxItem(_(types[type]))
752 this->filter = filter;
757 BinFolderTarget::~BinFolderTarget()
761 BC_Window *BinFolderTarget::new_gui(ModifyTargetThread *thread)
763 ModifyTargetGUI *window = new ModifyTargetGUI(thread);
764 window->create_objects();
768 BinFolderTargetType::BinFolderTargetType(int no)
769 : BC_MenuItem(_(BinFolderTarget::types[no]))
773 BinFolderTargetType::~BinFolderTargetType()
777 int BinFolderTargetType::handle_event()
779 BinFolderTargetPopup *target_popup = (BinFolderTargetPopup *)get_popup_menu();
780 BinFolderList *folder_list = target_popup->folder_list;
781 int i = folder_list->get_selection_number(FOLDER_COLUMN_TARGET, 0);
783 BinFolder *folder = folder_list->folder;
784 BinFolderFilter *filter = folder->filters[i];
785 filter->update_target(no);
786 folder_list->create_list();
791 BinFolderTargetPopup::BinFolderTargetPopup(BinFolderList *folder_list)
792 : BC_PopupMenu(0, 0, 0, "", 0)
794 this->folder_list = folder_list;
798 void BinFolderTargetPopup::create_objects()
800 add_item(new BinFolderTargetType(FOLDER_TARGET_PATTERNS));
801 add_item(new BinFolderTargetType(FOLDER_TARGET_FILE_SIZE));
802 add_item(new BinFolderTargetType(FOLDER_TARGET_MOD_TIME));
803 add_item(new BinFolderTargetType(FOLDER_TARGET_TRACK_TYPE));
804 add_item(new BinFolderTargetType(FOLDER_TARGET_WIDTH));
805 add_item(new BinFolderTargetType(FOLDER_TARGET_HEIGHT));
806 add_item(new BinFolderTargetType(FOLDER_TARGET_FRAMERATE));
807 add_item(new BinFolderTargetType(FOLDER_TARGET_SAMPLERATE));
808 add_item(new BinFolderTargetType(FOLDER_TARGET_CHANNELS));
809 add_item(new BinFolderTargetType(FOLDER_TARGET_DURATION));
812 void BinFolderTargetPopup::activate_menu(BC_ListBoxItem *item)
814 this->target = (BinFolderTarget *)item;
815 BC_PopupMenu::activate_menu();
819 BinFolderTargetPatterns::BinFolderTargetPatterns(BinFolderFilter *filter)
820 : BinFolderTarget(filter, FOLDER_TARGET_PATTERNS)
825 BinFolderTargetPatterns::~BinFolderTargetPatterns()
830 void BinFolderTargetPatterns::save_xml(FileXML *file) {}
831 void BinFolderTargetPatterns::load_xml(FileXML *file) {}
833 void BinFolderTargetPatterns::copy_from(BinFolderTarget *that)
835 BinFolderTargetPatterns *tp = (BinFolderTargetPatterns*)that;
839 void BinFolderTargetPatterns::update(const char *text)
841 delete [] this->text;
842 this->text = cstrdup(text);
843 filter->update_value(text);
846 BC_Window *BinFolderTargetPatterns::new_gui(ModifyTargetThread *thread)
848 return new ModifyTargetPatternsGUI(thread);
852 BinFolderTargetFileSize::BinFolderTargetFileSize(BinFolderFilter *filter)
853 : BinFolderTarget(filter, FOLDER_TARGET_FILE_SIZE)
856 update(file_size, -1);
858 BinFolderTargetFileSize::~BinFolderTargetFileSize()
862 void BinFolderTargetFileSize::save_xml(FileXML *file)
864 file->tag.set_property("FILE_SIZE", file_size);
865 file->tag.set_property("AROUND", around);
868 void BinFolderTargetFileSize::load_xml(FileXML *file)
870 int64_t file_size = file->tag.get_property("FILE_SIZE", this->file_size);
871 double around = file->tag.get_property("AROUND", this->around);
872 update(file_size, around);
875 void BinFolderTargetFileSize::copy_from(BinFolderTarget *that)
877 BinFolderTargetFileSize *tp = (BinFolderTargetFileSize *)that;
878 update(tp->file_size, tp->around);
881 void BinFolderTargetFileSize::update(int64_t file_size, double around)
883 this->file_size = file_size;
884 this->around = around;
885 char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
886 show_no(file_size, cp, ep);
887 if( around >= 0 && filter->op->type == FOLDER_OP_AROUND ) {
888 if( cp < ep ) *cp++ = '+';
889 show_no(around, cp, ep);
892 filter->update_value(txt);
895 BC_Window *BinFolderTargetFileSize::new_gui(ModifyTargetThread *thread)
897 return new ModifyTargetFileSizeGUI(thread);
901 BinFolderTargetTime::BinFolderTargetTime(BinFolderFilter *filter)
902 : BinFolderTarget(filter, FOLDER_TARGET_MOD_TIME)
908 BinFolderTargetTime::~BinFolderTargetTime()
912 void BinFolderTargetTime::save_xml(FileXML *file)
914 file->tag.set_property("MTIME", mtime);
915 file->tag.set_property("AROUND", around);
918 void BinFolderTargetTime::load_xml(FileXML *file)
920 int64_t mtime = file->tag.get_property("MTIME", this->mtime);
921 double around = file->tag.get_property("AROUND", this->around);
922 update(mtime, around);
925 void BinFolderTargetTime::copy_from(BinFolderTarget *that)
927 BinFolderTargetTime *tp = (BinFolderTargetTime *)that;
928 update(tp->mtime, tp->around);
931 void BinFolderTargetTime::update(int64_t mtime, double around)
934 this->around = around;
935 char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
936 show_date(mtime, cp, ep);
937 if( around >= 0 && filter->op->type == FOLDER_OP_AROUND ) {
938 if( cp < ep ) *cp++ = '+';
939 show_duration(around, cp, ep);
942 filter->update_value(txt);
945 BC_Window *BinFolderTargetTime::new_gui(ModifyTargetThread *thread)
947 return new ModifyTargetTimeGUI(thread);
951 BinFolderTargetTrackType::BinFolderTargetTrackType(BinFolderFilter *filter)
952 : BinFolderTarget(filter, FOLDER_TARGET_TRACK_TYPE)
954 data_types = (1<<TRACK_AUDIO);
957 BinFolderTargetTrackType::~BinFolderTargetTrackType()
961 void BinFolderTargetTrackType::save_xml(FileXML *file)
963 file->tag.set_property("DATA_TYPES", data_types);
966 void BinFolderTargetTrackType::load_xml(FileXML *file)
968 int data_types = file->tag.get_property("DATA_TYPES", this->data_types);
972 void BinFolderTargetTrackType::copy_from(BinFolderTarget *that)
974 BinFolderTargetTrackType *tp = (BinFolderTargetTrackType *)that;
975 update(tp->data_types);
978 void BinFolderTargetTrackType::update(int data_types)
980 this->data_types = data_types;
982 char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
983 if( data_types & (1<<TRACK_AUDIO) ) {
984 if( cp > txt && cp < ep ) *cp++ = ' ';
985 cp += snprintf(cp, ep-cp, "%s",_("audio"));
987 if( data_types & (1<<TRACK_VIDEO) ) {
988 if( cp > txt && cp < ep ) *cp++ = ' ';
989 cp += snprintf(cp, ep-cp, "%s",_("video"));
992 filter->update_value(txt);
995 BC_Window *BinFolderTargetTrackType::new_gui(ModifyTargetThread *thread)
997 return new ModifyTargetTrackTypeGUI(thread);
1001 BinFolderTargetWidth::BinFolderTargetWidth(BinFolderFilter *filter)
1002 : BinFolderTarget(filter, FOLDER_TARGET_WIDTH)
1007 BinFolderTargetWidth::~BinFolderTargetWidth()
1011 void BinFolderTargetWidth::save_xml(FileXML *file)
1013 file->tag.set_property("WIDTH", width);
1014 file->tag.set_property("AROUND", around);
1016 void BinFolderTargetWidth::load_xml(FileXML *file)
1018 int width = file->tag.get_property("WIDTH", this->width);
1019 double around = file->tag.get_property("AROUND", this->around);
1020 update(width, around);
1023 void BinFolderTargetWidth::copy_from(BinFolderTarget *that)
1025 BinFolderTargetWidth *tp = (BinFolderTargetWidth *)that;
1026 update(tp->width, tp->around);
1029 void BinFolderTargetWidth::update(int width, double around)
1031 this->width = width;
1032 this->around = around;
1033 char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
1034 show_no(width, cp, ep);
1035 if( around >= 0 && filter->op->type == FOLDER_OP_AROUND ) {
1036 if( cp < ep ) *cp++ = '+';
1037 show_no(around, cp, ep);
1040 filter->update_value(txt);
1043 BC_Window *BinFolderTargetWidth::new_gui(ModifyTargetThread *thread)
1045 return new ModifyTargetWidthGUI(thread);
1049 BinFolderTargetHeight::BinFolderTargetHeight(BinFolderFilter *filter)
1050 : BinFolderTarget(filter, FOLDER_TARGET_HEIGHT)
1055 BinFolderTargetHeight::~BinFolderTargetHeight()
1059 void BinFolderTargetHeight::save_xml(FileXML *file)
1061 file->tag.set_property("HEIGHT", height);
1062 file->tag.set_property("AROUND", around);
1064 void BinFolderTargetHeight::load_xml(FileXML *file)
1066 int height = file->tag.get_property("HEIGHT", this->height);
1067 double around = file->tag.get_property("AROUND", this->around);
1068 update(height, around);
1071 void BinFolderTargetHeight::copy_from(BinFolderTarget *that)
1073 BinFolderTargetHeight *tp = (BinFolderTargetHeight *)that;
1074 update(tp->height, tp->around);
1077 void BinFolderTargetHeight::update(int height, double around)
1079 this->height = height;
1080 this->around = around;
1081 char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
1082 show_no(height, cp, ep);
1083 if( around >= 0 && filter->op->type == FOLDER_OP_AROUND ) {
1084 if( cp < ep ) *cp++ = '+';
1085 show_no(around, cp, ep);
1088 filter->update_value(txt);
1091 BC_Window *BinFolderTargetHeight::new_gui(ModifyTargetThread *thread)
1093 return new ModifyTargetHeightGUI(thread);
1097 BinFolderTargetFramerate::BinFolderTargetFramerate(BinFolderFilter *filter)
1098 : BinFolderTarget(filter, FOLDER_TARGET_FRAMERATE)
1101 update(framerate, -1);
1103 BinFolderTargetFramerate::~BinFolderTargetFramerate()
1107 void BinFolderTargetFramerate::save_xml(FileXML *file)
1109 file->tag.set_property("FRAMERATE", framerate);
1110 file->tag.set_property("AROUND", around);
1113 void BinFolderTargetFramerate::load_xml(FileXML *file)
1115 double framerate = file->tag.get_property("FRAMERATE", this->framerate);
1116 double around = file->tag.get_property("AROUND", this->around);
1117 update(framerate, around);
1120 void BinFolderTargetFramerate::copy_from(BinFolderTarget *that)
1122 BinFolderTargetFramerate *tp = (BinFolderTargetFramerate *)that;
1123 update(tp->framerate, tp->around);
1126 void BinFolderTargetFramerate::update(double framerate, double around)
1128 this->framerate = framerate;
1129 this->around = around;
1130 char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
1131 show_no(framerate, cp, ep, "%0.3f");
1132 if( around >= 0 && filter->op->type == FOLDER_OP_AROUND ) {
1133 if( cp < ep ) *cp++ = '+';
1134 show_no(around, cp, ep, "%0.3f");
1137 filter->update_value(txt);
1140 BC_Window *BinFolderTargetFramerate::new_gui(ModifyTargetThread *thread)
1142 return new ModifyTargetFramerateGUI(thread);
1146 BinFolderTargetSamplerate::BinFolderTargetSamplerate(BinFolderFilter *filter)
1147 : BinFolderTarget(filter, FOLDER_TARGET_SAMPLERATE)
1150 update(samplerate, -1);
1153 BinFolderTargetSamplerate::~BinFolderTargetSamplerate()
1157 void BinFolderTargetSamplerate::save_xml(FileXML *file)
1159 file->tag.set_property("SAMPLERATE", samplerate);
1160 file->tag.set_property("AROUND", around);
1163 void BinFolderTargetSamplerate::load_xml(FileXML *file)
1165 double samplerate = file->tag.get_property("SAMPLERATE", this->samplerate);
1166 double around = file->tag.get_property("AROUND", this->around);
1167 update(samplerate, around);
1170 void BinFolderTargetSamplerate::copy_from(BinFolderTarget *that)
1172 BinFolderTargetSamplerate *tp = (BinFolderTargetSamplerate *)that;
1173 update(tp->samplerate, tp->around);
1176 void BinFolderTargetSamplerate::update(int samplerate, double around)
1178 this->samplerate = samplerate;
1179 this->around = around;
1180 char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
1181 show_no(samplerate, cp, ep);
1182 if( around >= 0 && filter->op->type == FOLDER_OP_AROUND ) {
1183 if( cp < ep ) *cp++ = '+';
1184 show_no(around, cp, ep);
1187 filter->update_value(txt);
1190 BC_Window *BinFolderTargetSamplerate::new_gui(ModifyTargetThread *thread)
1192 return new ModifyTargetSamplerateGUI(thread);
1196 BinFolderTargetChannels::BinFolderTargetChannels(BinFolderFilter *filter)
1197 : BinFolderTarget(filter, FOLDER_TARGET_CHANNELS)
1200 update(channels, -1);
1202 BinFolderTargetChannels::~BinFolderTargetChannels()
1206 void BinFolderTargetChannels::save_xml(FileXML *file)
1208 file->tag.set_property("CHANNELS", channels);
1209 file->tag.set_property("AROUND", around);
1212 void BinFolderTargetChannels::load_xml(FileXML *file)
1214 int channels = file->tag.get_property("CHANNELS", this->channels);
1215 double around = file->tag.get_property("AROUND", this->around);
1216 update(channels, around);
1219 void BinFolderTargetChannels::copy_from(BinFolderTarget *that)
1221 BinFolderTargetChannels *tp = (BinFolderTargetChannels *)that;
1222 update(tp->channels, tp->around);
1225 void BinFolderTargetChannels::update(int channels, double around)
1227 this->channels = channels;
1228 this->around = around;
1229 char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
1230 show_no(channels, cp, ep);
1231 if( around >= 0 && filter->op->type == FOLDER_OP_AROUND ) {
1232 if( cp < ep ) *cp++ = '+';
1233 show_no(around, cp, ep);
1236 filter->update_value(txt);
1239 BC_Window *BinFolderTargetChannels::new_gui(ModifyTargetThread *thread)
1241 return new ModifyTargetChannelsGUI(thread);
1245 BinFolderTargetDuration::BinFolderTargetDuration(BinFolderFilter *filter)
1246 : BinFolderTarget(filter, FOLDER_TARGET_DURATION)
1249 update(duration, -1);
1251 BinFolderTargetDuration::~BinFolderTargetDuration()
1255 void BinFolderTargetDuration::save_xml(FileXML *file)
1257 file->tag.set_property("DURATION", duration);
1258 file->tag.set_property("AROUND", around);
1261 void BinFolderTargetDuration::load_xml(FileXML *file)
1263 int64_t duration = file->tag.get_property("DURATION", this->duration);
1264 double around = file->tag.get_property("AROUND", this->around);
1265 update(duration, around);
1268 void BinFolderTargetDuration::copy_from(BinFolderTarget *that)
1270 BinFolderTargetDuration *tp = (BinFolderTargetDuration *)that;
1271 update(tp->duration, tp->around);
1274 void BinFolderTargetDuration::update(int64_t duration, double around)
1276 this->duration = duration;
1277 this->around = around;
1278 char txt[BCSTRLEN], *cp = txt, *ep = cp + sizeof(txt)-1;
1279 show_duration(duration, cp, ep);
1280 if( around >= 0 && filter->op->type == FOLDER_OP_AROUND ) {
1281 if( cp < ep ) *cp++ = '+';
1282 show_duration(around, cp, ep);
1285 filter->update_value(txt);
1288 BC_Window *BinFolderTargetDuration::new_gui(ModifyTargetThread *thread)
1290 return new ModifyTargetDurationGUI(thread);
1294 BinFolderOp::BinFolderOp(BinFolderFilter *filter, int type)
1295 : BC_ListBoxItem(_(types[type]))
1297 this->filter = filter;
1301 BinFolderOp::~BinFolderOp()
1305 void BinFolderOp::copy_from(BinFolderOp *that)
1310 BinFolderOpType::BinFolderOpType(int no)
1311 : BC_MenuItem(_(BinFolderOp::types[no]))
1315 BinFolderOpType::~BinFolderOpType()
1319 int BinFolderOpType::handle_event()
1321 BinFolderOpPopup *op_popup = (BinFolderOpPopup *)get_popup_menu();
1322 BinFolderList *folder_list = op_popup->folder_list;
1323 int i = folder_list->get_selection_number(FOLDER_COLUMN_OP, 0);
1325 BinFolder *folder = folder_list->folder;
1326 BinFolderFilter *filter = folder->filters[i];
1327 filter->update_op(no);
1328 folder_list->create_list();
1333 BinFolderOpPopup::BinFolderOpPopup(BinFolderList *folder_list)
1334 : BC_PopupMenu(0, 0, 0, "", 0)
1336 this->folder_list = folder_list;
1340 void BinFolderOpPopup::create_objects()
1342 add_item(new BinFolderOpType(FOLDER_OP_AROUND));
1343 add_item(new BinFolderOpType(FOLDER_OP_EQ));
1344 add_item(new BinFolderOpType(FOLDER_OP_GE));
1345 add_item(new BinFolderOpType(FOLDER_OP_GT));
1346 add_item(new BinFolderOpType(FOLDER_OP_NE));
1347 add_item(new BinFolderOpType(FOLDER_OP_LE));
1348 add_item(new BinFolderOpType(FOLDER_OP_LT));
1349 add_item(new BinFolderOpType(FOLDER_OP_MATCHES));
1352 void BinFolderOpPopup::activate_menu(BC_ListBoxItem *item)
1354 this->op = (BinFolderOp *)item;
1355 BC_PopupMenu::activate_menu();
1358 double BinFolderOp::test(BinFolderTarget *target, Indexable *idxbl)
1363 double BinFolderOpEQ::test(BinFolderTarget *target, Indexable *idxbl)
1365 double v = compare(target, idxbl);
1366 return v == 0 ? 1 : -1;
1369 double BinFolderOpGT::test(BinFolderTarget *target, Indexable *idxbl)
1371 double v = compare(target, idxbl);
1372 return v > 0 ? 1 : -1;
1375 double BinFolderOpGE::test(BinFolderTarget *target, Indexable *idxbl)
1377 double v = compare(target, idxbl);
1378 return v >= 0 ? 1 : -1;
1381 double BinFolderOpNE::test(BinFolderTarget *target, Indexable *idxbl)
1383 double v = compare(target, idxbl);
1384 return v != 0 ? 1 : -1;
1387 double BinFolderOpLT::test(BinFolderTarget *target, Indexable *idxbl)
1389 double v = compare(target, idxbl);
1390 return v < 0 ? 1 : -1;
1393 double BinFolderOpLE::test(BinFolderTarget *target, Indexable *idxbl)
1395 double v = compare(target, idxbl);
1396 return v <= 0 ? 1 : -1;
1399 double BinFolderOpMatches::test(BinFolderTarget *target, Indexable *idxbl)
1401 double v = compare(target, idxbl);
1405 double BinFolderOpAround::test(BinFolderTarget *target, Indexable *idxbl)
1407 double v = compare(target, idxbl);
1411 BinFolderValue::BinFolderValue(BinFolderFilter *filter, const char *text)
1414 this->filter = filter;
1418 BinFolderValue::~BinFolderValue()
1423 void BinFolderValue::update(const char *text)
1425 const char *cp = text;
1426 char txt[BCSTRLEN], *tp = txt;
1427 for( int i=sizeof(txt); --i>0 && *cp!=0 && *cp!='\n'; ++tp,++cp ) *tp = *cp;
1433 BinFolderList::BinFolderList(BinFolder *folder, MWindow *mwindow,
1434 ModifyFolderGUI *window, int x, int y, int w, int h)
1435 : BC_ListBox(x, y, w, h, LISTBOX_TEXT, 0,
1436 0, 0, 1, 0, 0, LISTBOX_SINGLE, ICON_LEFT, 1)
1438 this->folder = folder;
1439 this->mwindow = mwindow;
1440 this->window = window;
1442 set_process_drag(1);
1449 BinFolderList::~BinFolderList()
1451 save_defaults(mwindow->defaults);
1452 delete modify_target;
1455 void BinFolderList::create_objects()
1457 list_titles[FOLDER_COLUMN_ENABLE] = _("Enable");
1458 list_titles[FOLDER_COLUMN_TARGET] = _("Target");
1459 list_titles[FOLDER_COLUMN_OP] = _("Op");
1460 list_titles[FOLDER_COLUMN_VALUE] = _("Value");
1461 list_width[FOLDER_COLUMN_ENABLE] = xS(80);
1462 list_width[FOLDER_COLUMN_TARGET] = xS(80);
1463 list_width[FOLDER_COLUMN_OP] = xS(50);
1464 list_width[FOLDER_COLUMN_VALUE] = xS(180);
1465 load_defaults(mwindow->defaults);
1467 add_subwindow(enabled_popup = new BinFolderEnabledPopup(this));
1468 enabled_popup->create_objects();
1469 add_subwindow(op_popup = new BinFolderOpPopup(this));
1470 op_popup->create_objects();
1471 add_subwindow(target_popup = new BinFolderTargetPopup(this));
1472 target_popup->create_objects();
1474 modify_target = new ModifyTargetThread(this);
1477 void BinFolderList::create_list()
1479 for( int i=0; i<FOLDER_COLUMNS; ++i )
1480 list_items[i].remove_all();
1481 for( int i=0; i<folder->filters.size(); ++i ) {
1482 BinFolderFilter *filter = folder->filters[i];
1483 list_items[FOLDER_COLUMN_ENABLE].append(filter->enabled);
1484 list_items[FOLDER_COLUMN_TARGET].append(filter->target);
1485 list_items[FOLDER_COLUMN_OP].append(filter->op);
1486 list_items[FOLDER_COLUMN_VALUE].append(filter->value);
1488 update(list_items, list_titles, list_width, FOLDER_COLUMNS,
1489 get_xposition(), get_yposition(), get_highlighted_item(),
1493 int BinFolderList::handle_event()
1498 int BinFolderList::selection_changed()
1500 if( !cursor_above() ) return 0;
1501 int no = get_selection_number(0, 0);
1502 if( no < 0 ) return 0;
1503 BinFolderFilter *filter = folder->filters[no];
1504 if( get_button_down() && get_buttonpress() == 3 ) {
1505 int cx = get_cursor_x(), col = -1;
1506 for( int i=0; col<0 && i<FOLDER_COLUMNS; ++i ) {
1507 int ofs = get_column_offset(i);
1508 if( cx >= ofs && cx < ofs+get_column_width(i) ) {
1512 BC_ListBoxItem *item = col >= 0 ? get_selection(col, 0) : 0;
1514 deactivate_selection();
1516 case FOLDER_COLUMN_ENABLE:
1517 enabled_popup->activate_menu(item);
1519 case FOLDER_COLUMN_TARGET:
1520 target_popup->activate_menu(item);
1522 case FOLDER_COLUMN_OP:
1523 op_popup->activate_menu(item);
1525 case FOLDER_COLUMN_VALUE: {
1526 modify_target->close_window();
1527 int cw = xS(filter->target->type == FOLDER_TARGET_PATTERNS ? 400 : 320);
1528 int ch = yS(filter->target->type == FOLDER_TARGET_PATTERNS ? 300 : 120);
1529 int cx, cy; get_abs_cursor(cx, cy);
1530 if( (cx-=cw/2) < xS(50) ) cx = xS(50);
1531 if( (cy-=ch/2) < yS(50) ) cy = yS(50);
1532 modify_target->start(filter->target, cx, cy, cw, ch);
1540 int BinFolderList::column_resize_event()
1542 for( int i = 0; i < FOLDER_COLUMNS; i++ ) {
1543 list_width[i] = get_column_width(i);
1548 int BinFolderList::drag_start_event()
1550 if( BC_ListBox::drag_start_event() ) {
1558 int BinFolderList::drag_motion_event()
1560 if( BC_ListBox::drag_motion_event() ) {
1566 int BinFolderList::drag_stop_event()
1568 if( dragging_item ) {
1569 int src = get_selection_number(0, 0);
1570 int dst = get_highlighted_item();
1572 move_filter(src, dst);
1574 BC_ListBox::drag_stop_event();
1580 void BinFolderList::move_filter(int src, int dst)
1582 BinFolderFilters &filters = folder->filters;
1583 BinFolderFilter *src_filter = filters[src];
1584 if( dst < 0 ) dst = filters.size()-1;
1587 for( int i=src; i<filters.size()-1; ++i )
1588 filters[i] = filters[i+1];
1589 for( int i=filters.size(); --i>dst; )
1590 filters[i] = filters[i-1];
1591 filters[dst] = src_filter;
1595 void BinFolderList::save_defaults(BC_Hash *defaults)
1597 defaults->update("BIN_FOLDER_ENA", list_width[FOLDER_COLUMN_ENABLE]);
1598 defaults->update("BIN_FOLDER_TGT", list_width[FOLDER_COLUMN_TARGET]);
1599 defaults->update("BIN_FOLDER_OPR", list_width[FOLDER_COLUMN_OP]);
1600 defaults->update("BIN_FOLDER_VAL", list_width[FOLDER_COLUMN_VALUE]);
1602 void BinFolderList::load_defaults(BC_Hash *defaults)
1604 list_width[FOLDER_COLUMN_ENABLE] = defaults->get("BIN_FOLDER_ENA", list_width[FOLDER_COLUMN_ENABLE]);
1605 list_width[FOLDER_COLUMN_TARGET] = defaults->get("BIN_FOLDER_TGT", list_width[FOLDER_COLUMN_TARGET]);
1606 list_width[FOLDER_COLUMN_OP] = defaults->get("BIN_FOLDER_OPR", list_width[FOLDER_COLUMN_OP]);
1607 list_width[FOLDER_COLUMN_VALUE] = defaults->get("BIN_FOLDER_VAL", list_width[FOLDER_COLUMN_VALUE]);
1610 BinFolderAddFilter::BinFolderAddFilter(BinFolderList *folder_list, int x, int y)
1611 : BC_GenericButton(x, y, _("Add"))
1613 this->folder_list = folder_list;
1615 BinFolderAddFilter::~BinFolderAddFilter()
1619 int BinFolderAddFilter::handle_event()
1621 folder_list->modify_target->close_window();
1622 // default new filter
1623 BinFolderFilter *filter = new BinFolderFilter();
1624 filter->update_enabled(FOLDER_ENABLED_OR);
1625 filter->update_target(FOLDER_TARGET_PATTERNS);
1626 filter->update_op(FOLDER_OP_MATCHES);
1627 BinFolderTargetPatterns *patterns = (BinFolderTargetPatterns *)(filter->target);
1628 filter->update_value(patterns->text);
1629 folder_list->folder->filters.append(filter);
1630 folder_list->create_list();
1634 BinFolderDelFilter::BinFolderDelFilter(BinFolderList *folder_list, int x, int y)
1635 : BC_GenericButton(x, y, _("Del"))
1637 this->folder_list = folder_list;
1639 BinFolderDelFilter::~BinFolderDelFilter()
1643 int BinFolderDelFilter::handle_event()
1645 folder_list->modify_target->close_window();
1646 int no = folder_list->get_selection_number(0, 0);
1648 folder_list->folder->filters.remove_object_number(no);
1649 folder_list->create_list();
1654 BinFolderApplyFilter::BinFolderApplyFilter(BinFolderList *folder_list, int x, int y)
1655 : BC_GenericButton(x, y, _("Apply"))
1657 this->folder_list = folder_list;
1659 BinFolderApplyFilter::~BinFolderApplyFilter()
1663 int BinFolderApplyFilter::handle_event()
1665 ModifyFolderThread *thread = folder_list->window->thread;
1666 thread->original->copy_from(thread->folder);
1667 thread->agui->async_update_assets();
1672 NewFolderGUI::NewFolderGUI(NewFolderThread *thread, int x, int y, int w, int h)
1673 : BC_Window(_(PROGRAM_NAME ": New folder"),
1674 x, y, xS(w), yS(h), -1, -1, 0, 0, 1)
1676 this->thread = thread;
1677 // *** CONTEXT_HELP ***
1678 context_help_set_keyword("User Folders");
1681 NewFolderGUI::~NewFolderGUI()
1685 void NewFolderGUI::create_objects()
1688 int ys5 = yS(5), ys10 = yS(10);
1689 lock_window("NewFolderGUI::create_objects");
1690 int x = xs10, y = ys10;
1692 add_subwindow(title = new BC_Title(x, y, _("Folder name:")));
1693 y += title->get_h() + ys5;
1694 const char *text = !thread->is_clips ? _("media bin") : _("clip bin");
1695 add_subwindow(text_box = new BC_TextBox(x, y, xS(300), 1, text));
1696 add_subwindow(new BC_OKButton(this));
1697 add_subwindow(new BC_CancelButton(this));
1702 const char* NewFolderGUI::get_text()
1704 return text_box->get_text();
1708 NewFolderThread::NewFolderThread(AWindowGUI *agui)
1715 NewFolderThread::~NewFolderThread()
1720 void NewFolderThread::start(int x, int y, int w, int h, int is_clips)
1723 this->is_clips = is_clips;
1724 this->wx = x; this->wy = y;
1725 this->ww = w; this->wh = h;
1729 BC_Window *NewFolderThread::new_gui()
1731 window = new NewFolderGUI(this, wx, wy, ww, wh);
1732 window->create_objects();
1736 void NewFolderThread::handle_done_event(int result)
1739 const char *text = window->get_text();
1740 agui->mwindow->new_folder(text, is_clips);
1744 void NewFolderThread::handle_close_event(int result)
1749 ModifyFolderGUI::ModifyFolderGUI(ModifyFolderThread *thread, int x, int y, int w, int h)
1750 : BC_Window(_(PROGRAM_NAME ": Modify folder"), x, y, w, h, xS(320), yS(200), 1, 0, 1)
1752 this->thread = thread;
1753 // *** CONTEXT_HELP ***
1754 context_help_set_keyword("User Folders");
1757 ModifyFolderGUI::~ModifyFolderGUI()
1761 int ModifyFolderGUI::receive_custom_xatoms(xatom_event *event)
1763 if( event->message_type == modify_folder_xatom ) {
1770 void ModifyFolderGUI::async_update_filters()
1773 event.message_type = modify_folder_xatom;
1774 send_custom_xatom(&event);
1778 void ModifyFolderGUI::create_objects()
1780 int xs10 = xS(10), xs15 = xS(15);
1781 int ys10 = yS(10), ys30 = yS(30);
1782 lock_window("ModifyFolderGUI::create_objects");
1783 modify_folder_xatom = create_xatom("CWINDOWGUI_UPDATE_FILTERS");
1784 int x = xs10, y = ys10;
1786 add_subwindow(title = new BC_Title(x, y, _("Enter the name of the folder:")));
1787 const char *text = !thread->folder->is_clips ? _("Media") : _("Clips");
1788 int tw = BC_Title::calculate_w(this, text, LARGEFONT);
1789 int x0 = get_w() - xS(50) - tw;
1790 add_subwindow(text_title = new BC_Title(x0, y, text, LARGEFONT, YELLOW));
1791 y += title->get_h() + ys10;
1792 add_subwindow(text_box = new BC_TextBox(x, y, xS(300), 1, thread->folder->title));
1793 y += text_box->get_h() + ys10;
1794 int lh = get_h() - y - BC_OKButton::calculate_h() - ys30;
1795 int lw = get_w() - x - xS(160);
1796 add_subwindow(folder_list =
1797 new BinFolderList(thread->folder, thread->agui->mwindow, this, x, y, lw, lh));
1798 folder_list->create_objects();
1799 int x1 = x + folder_list->get_w() + xs15, y1 = y;
1800 add_subwindow(add_filter = new BinFolderAddFilter(folder_list, x1, y1));
1801 y1 += add_filter->get_h() + ys10;
1802 add_subwindow(del_filter = new BinFolderDelFilter(folder_list, x1, y1));
1803 y1 += del_filter->get_h() + ys10;
1804 add_subwindow(apply_filter = new BinFolderApplyFilter(folder_list, x1, y1));
1805 add_subwindow(ok_button = new BC_OKButton(this));
1806 add_subwindow(cancel_button = new BC_CancelButton(this));
1811 int ModifyFolderGUI::resize_event(int w, int h)
1813 MWindow *mwindow = thread->agui->mwindow;
1814 mwindow->session->bwindow_w = w;
1815 mwindow->session->bwindow_h = h;
1816 int tx = text_title->get_x() + w - get_w();
1817 int ty = text_title->get_y();
1818 text_title->reposition_window(tx, ty);
1819 int lx = folder_list->get_x();
1820 int ly = folder_list->get_y();
1821 int lh = h - ly - BC_OKButton::calculate_h() - yS(30);
1822 int lw = w - lx - xS(160);
1823 folder_list->reposition_window(lx, ly, lw, lh);
1824 int x1 = lx + lw + xS(15);
1825 add_filter->reposition_window(x1, add_filter->get_y());
1826 del_filter->reposition_window(x1, del_filter->get_y());
1827 apply_filter->reposition_window(x1,apply_filter->get_y());
1828 ok_button->resize_event(w, h);
1829 cancel_button->resize_event(w, h);
1833 const char* ModifyFolderGUI::get_text()
1835 return text_box->get_text();
1838 void ModifyFolderGUI::update_filters()
1840 folder_list->create_list();
1844 ModifyFolderThread::ModifyFolderThread(AWindowGUI *agui)
1853 ModifyFolderThread::~ModifyFolderThread()
1859 void ModifyFolderThread::start(BinFolder *folder, int x, int y, int w, int h)
1862 this->original = folder;
1863 this->modify_edl = agui->mwindow->edl;
1864 this->modify_edl->add_user();
1865 this->folder = new BinFolder(*folder);
1866 this->wx = x; this->wy = y;
1867 this->ww = w; this->wh = h;
1871 BC_Window *ModifyFolderThread::new_gui()
1873 window = new ModifyFolderGUI(this, wx, wy, ww, wh);
1874 window->create_objects();
1878 void ModifyFolderThread::handle_done_event(int result)
1881 const char *title = window->get_text();
1882 if( strcmp(folder->title, title) ) {
1883 if( agui->mwindow->edl->get_folder_number(title) >= 0 ) {
1884 eprintf("folder already exists: %s", title);
1888 strncpy(folder->title, title,sizeof(folder->title));
1892 original->copy_from(folder);
1893 agui->async_update_assets();
1895 delete folder; folder = 0;
1897 modify_edl->remove_user();
1900 void ModifyFolderThread::handle_close_event(int result)
1905 ModifyTargetThread::ModifyTargetThread(BinFolderList *folder_list)
1908 this->folder_list = folder_list;
1912 ModifyTargetThread::~ModifyTargetThread()
1917 void ModifyTargetThread::start(BinFolderTarget *target, int x, int y, int w, int h)
1919 this->target = target;
1925 BC_Window *ModifyTargetThread::new_gui()
1927 window = (ModifyTargetGUI *)target->new_gui(this);
1928 window->create_objects();
1932 void ModifyTargetThread::handle_done_event(int result)
1936 folder_list->window->async_update_filters();
1940 void ModifyTargetThread::handle_close_event(int result)
1945 ModifyTargetGUI::ModifyTargetGUI(ModifyTargetThread *thread, int allow_resize)
1946 : BC_Window(_(PROGRAM_NAME ": Modify target"),
1947 thread->wx, thread->wy, xS(thread->ww), yS(thread->wh),
1948 -1, -1, allow_resize, 0, 1)
1950 this->thread = thread;
1951 // *** CONTEXT_HELP ***
1952 context_help_set_keyword("User Folders");
1955 ModifyTargetGUI::~ModifyTargetGUI()
1959 void ModifyTargetGUI::create_objects(BC_TextBox *&text_box)
1961 int xs10 = xS(10), xs20 = xS(20);
1963 lock_window("ModifyTargetGUI::create_objects");
1964 int x = xs10, y = ys10;
1965 const char *text = thread->target->filter->value->get_text();
1966 add_subwindow(text_box = new BC_TextBox(x, y, get_w()-xs20, 1, text));
1967 add_subwindow(new BC_OKButton(this));
1968 add_subwindow(new BC_CancelButton(this));
1973 int ModifyTargetGUI::resize_event(int w, int h)
1975 return BC_WindowBase::resize_event(w, h);
1978 ModifyTargetPatternsGUI::ModifyTargetPatternsGUI(ModifyTargetThread *thread)
1979 : ModifyTargetGUI(thread, 1)
1981 this->thread = thread;
1982 scroll_text_box = 0;
1986 ModifyTargetPatternsGUI::~ModifyTargetPatternsGUI()
1988 delete scroll_text_box;
1991 void ModifyTargetPatternsGUI::create_objects()
1993 int xs10 = xS(10), xs20 = xS(20);
1994 int ys10 = yS(10), ys20 = yS(20);
1995 lock_window("ModifyTargetPatternsGUI::create_objects");
1996 BinFolderTargetPatterns *target = (BinFolderTargetPatterns *)thread->target;
1997 int x = xs10, y = ys10;
1998 int text_font = MEDIUMFONT;
1999 text_rowsz = get_text_ascent(text_font)+1 + get_text_descent(text_font)+1;
2000 int th = get_h() - y - BC_OKButton::calculate_h() - ys20;
2001 int rows = th / text_rowsz;
2002 int text_len = strlen(target->text);
2003 if( text_len < BCTEXTLEN ) text_len = BCTEXTLEN;
2004 scroll_text_box = new BC_ScrollTextBox(this, x, y, get_w()-xs20, rows,
2005 target->text, 2*text_len);
2006 scroll_text_box->create_objects();
2007 add_subwindow(ok_button = new BC_OKButton(this));
2008 add_subwindow(cancel_button = new BC_CancelButton(this));
2013 int ModifyTargetPatternsGUI::resize_event(int w, int h)
2017 int tx = scroll_text_box->get_x();
2018 int ty = scroll_text_box->get_y();
2019 int th = h - ty - BC_OKButton::calculate_h() - ys20;
2021 int rows = th / text_rowsz;
2022 scroll_text_box->reposition_window(tx, ty, tw, rows);
2023 ok_button->resize_event(w, h);
2024 cancel_button->resize_event(w, h);
2028 void ModifyTargetPatternsGUI::update()
2030 BinFolderTargetPatterns *target = (BinFolderTargetPatterns *)thread->target;
2031 const char *cp = scroll_text_box->get_text();
2036 ModifyTargetFileSizeGUI::ModifyTargetFileSizeGUI(ModifyTargetThread *thread)
2037 : ModifyTargetGUI(thread)
2041 ModifyTargetFileSizeGUI::~ModifyTargetFileSizeGUI()
2045 void ModifyTargetFileSizeGUI::create_objects()
2047 ModifyTargetGUI::create_objects(text_box);
2050 void ModifyTargetFileSizeGUI::update()
2052 BinFolderTargetFileSize *target = (BinFolderTargetFileSize *)thread->target;
2053 double file_size = target->file_size, around = target->around;
2054 const char *cp = text_box->get_text(); char *bp = 0;
2055 scan_around(cp, bp, file_size, around);
2056 target->update(file_size, around);
2060 ModifyTargetTimeGUI::ModifyTargetTimeGUI(ModifyTargetThread *thread)
2061 : ModifyTargetGUI(thread)
2065 ModifyTargetTimeGUI::~ModifyTargetTimeGUI()
2069 void ModifyTargetTimeGUI::create_objects()
2071 ModifyTargetGUI::create_objects(text_box);
2074 void ModifyTargetTimeGUI::update()
2076 BinFolderTargetTime *target = (BinFolderTargetTime *)thread->target;
2077 int64_t mtime = target->mtime; double around = target->around;
2078 const char *cp = text_box->get_text(); char *bp = 0;
2079 int64_t v = scan_date(cp, bp);
2083 v = scan_duration(cp=bp+1, bp);
2084 if( bp > cp ) around = v;
2087 target->update(mtime, around);
2091 ModifyTargetTrackTypeGUI::ModifyTargetTrackTypeGUI(ModifyTargetThread *thread)
2092 : ModifyTargetGUI(thread)
2096 ModifyTargetTrackTypeGUI::~ModifyTargetTrackTypeGUI()
2100 void ModifyTargetTrackTypeGUI::create_objects()
2102 ModifyTargetGUI::create_objects(text_box);
2105 void ModifyTargetTrackTypeGUI::update()
2107 BinFolderTargetTrackType *target = (BinFolderTargetTrackType *)thread->target;
2108 const char *cp = text_box->get_text();
2110 if( bstrcasestr(cp, _("audio")) ) data_types |= (1<<TRACK_AUDIO);
2111 if( bstrcasestr(cp, _("video")) ) data_types |= (1<<TRACK_VIDEO);
2112 target->update(data_types);
2116 ModifyTargetWidthGUI::ModifyTargetWidthGUI(ModifyTargetThread *thread)
2117 : ModifyTargetGUI(thread)
2121 ModifyTargetWidthGUI::~ModifyTargetWidthGUI()
2125 void ModifyTargetWidthGUI::create_objects()
2127 ModifyTargetGUI::create_objects(text_box);
2130 void ModifyTargetWidthGUI::update()
2132 BinFolderTargetWidth *target = (BinFolderTargetWidth *)thread->target;
2133 double width = target->width, around = target->around;
2134 const char *cp = text_box->get_text(); char *bp = 0;
2135 scan_around(cp, bp, width, around);
2136 target->update(width, around);
2140 ModifyTargetHeightGUI::ModifyTargetHeightGUI(ModifyTargetThread *thread)
2141 : ModifyTargetGUI(thread)
2145 ModifyTargetHeightGUI::~ModifyTargetHeightGUI()
2149 void ModifyTargetHeightGUI::create_objects()
2151 ModifyTargetGUI::create_objects(text_box);
2154 void ModifyTargetHeightGUI::update()
2156 BinFolderTargetHeight *target = (BinFolderTargetHeight *)thread->target;
2157 double height = target->height, around = target->around;
2158 const char *cp = text_box->get_text(); char *bp = 0;
2159 scan_around(cp, bp, height, around);
2160 target->update(height, around);
2164 ModifyTargetFramerateGUI::ModifyTargetFramerateGUI(ModifyTargetThread *thread)
2165 : ModifyTargetGUI(thread)
2169 ModifyTargetFramerateGUI::~ModifyTargetFramerateGUI()
2173 void ModifyTargetFramerateGUI::create_objects()
2175 ModifyTargetGUI::create_objects(text_box);
2178 void ModifyTargetFramerateGUI::update()
2180 BinFolderTargetFramerate *target = (BinFolderTargetFramerate *)thread->target;
2181 double framerate = target->framerate, around = target->around;
2182 const char *cp = text_box->get_text(); char *bp = 0;
2183 scan_around(cp, bp, framerate, around);
2184 target->update(framerate, around);
2188 ModifyTargetSamplerateGUI::ModifyTargetSamplerateGUI(ModifyTargetThread *thread)
2189 : ModifyTargetGUI(thread)
2193 ModifyTargetSamplerateGUI::~ModifyTargetSamplerateGUI()
2197 void ModifyTargetSamplerateGUI::create_objects()
2199 ModifyTargetGUI::create_objects(text_box);
2202 void ModifyTargetSamplerateGUI::update()
2204 BinFolderTargetSamplerate *target = (BinFolderTargetSamplerate *)thread->target;
2205 double samplerate = target->samplerate, around = target->around;
2206 const char *cp = text_box->get_text(); char *bp = 0;
2207 scan_around(cp, bp, samplerate, around);
2208 target->update(samplerate, around);
2212 ModifyTargetChannelsGUI::ModifyTargetChannelsGUI(ModifyTargetThread *thread)
2213 : ModifyTargetGUI(thread)
2217 ModifyTargetChannelsGUI::~ModifyTargetChannelsGUI()
2221 void ModifyTargetChannelsGUI::create_objects()
2223 ModifyTargetGUI::create_objects(text_box);
2226 void ModifyTargetChannelsGUI::update()
2228 BinFolderTargetChannels *target = (BinFolderTargetChannels *)thread->target;
2229 double channels = target->channels, around = target->around;
2230 const char *cp = text_box->get_text(); char *bp = 0;
2231 scan_around(cp, bp, channels, around);
2232 target->update(channels, around);
2236 ModifyTargetDurationGUI::ModifyTargetDurationGUI(ModifyTargetThread *thread)
2237 : ModifyTargetGUI(thread)
2241 ModifyTargetDurationGUI::~ModifyTargetDurationGUI()
2245 void ModifyTargetDurationGUI::create_objects()
2247 ModifyTargetGUI::create_objects(text_box);
2250 void ModifyTargetDurationGUI::update()
2252 BinFolderTargetDuration *target = (BinFolderTargetDuration *)thread->target;
2253 int64_t duration = target->duration, around = target->around;
2254 const char *cp = text_box->get_text(); char *bp = 0;
2255 int64_t v = scan_duration(cp, bp);
2259 v = scan_duration(cp=bp+1, bp);
2260 if( bp > cp ) around = v;
2263 target->update(duration, around);