no longer need ffmpeg patch0 which was for Termux
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / assetedit.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2010 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 "awindow.h"
25 #include "awindowgui.h"
26 #include "bcprogressbox.h"
27 #include "bcsignals.h"
28 #include "bitspopup.h"
29 #include "cache.h"
30 #include "clip.h"
31 #include "cplayback.h"
32 #include "cwindow.h"
33 #include "edl.h"
34 #include "edlsession.h"
35 #include "file.h"
36 #include "filempeg.h"
37 #include "fileffmpeg.h"
38 #include "filesystem.h"
39 #include "indexable.h"
40 #include "indexfile.h"
41 #include "indexstate.h"
42 #include "language.h"
43 #include "mainindexes.h"
44 #include "mwindow.h"
45 #include "mwindowgui.h"
46 #include "theme.h"
47 #include "new.h"
48 #include "preferences.h"
49 #include "resizetrackthread.h"
50 #include "removefile.h"
51 #include "theme.h"
52 #include "transportque.h"
53 #include "interlacemodes.h"
54 #include "edl.h"
55 #include "edlsession.h"
56
57 #include <string.h>
58
59
60
61 AssetEdit::AssetEdit(MWindow *mwindow)
62  : BC_DialogThread()
63 {
64         this->mwindow = mwindow;
65         indexable = 0;
66         window = 0;
67         changed_params = new Asset;
68         //set_synchronous(0);
69 }
70
71
72 AssetEdit::~AssetEdit()
73 {
74         close_window();
75         changed_params->remove_user();
76 }
77
78
79 void AssetEdit::edit_asset(Indexable *indexable, int x, int y)
80 {
81         close_window();
82         this->indexable = indexable;
83         this->indexable->add_user();
84         this->x = x;  this->y = y;
85
86 // Copy asset parameters into temporary storage for editing.
87         if( indexable->is_asset ) {
88                 changed_params->copy_from((Asset*)indexable, 0);
89         }
90         else {
91                 EDL *nested_edl = (EDL*)indexable;
92                 strcpy(changed_params->path, nested_edl->path);
93                 changed_params->sample_rate = nested_edl->session->sample_rate;
94                 changed_params->channels = nested_edl->session->audio_channels;
95
96 //printf("AssetEdit::edit_asset %d %f\n", __LINE__, nested_edl->session->frame_rate);
97                 changed_params->frame_rate = nested_edl->session->frame_rate;
98                 changed_params->width = nested_edl->session->output_w;
99                 changed_params->height = nested_edl->session->output_h;
100         }
101
102         BC_DialogThread::start();
103 }
104
105 void AssetEdit::handle_done_event(int result)
106 {
107         if( !result && changed_params->timecode >= 0 ) {
108                 double rate = indexable->get_frame_rate();
109                 changed_params->timecode =
110                         atoi(window->tc_hrs->get_text()) * 3600 +
111                         atoi(window->tc_mins->get_text()) * 60 +
112                         atoi(window->tc_secs->get_text()) +
113                         atoi(window->tc_rest->get_text()) / rate;
114         }
115 }
116
117 void AssetEdit::handle_close_event(int result)
118 {
119         if( !result ) {
120                 int changed = 0;
121                 Asset *asset = 0;
122                 EDL *nested_edl = 0;
123
124                 if( indexable->is_asset ) {
125                         asset = (Asset*)indexable;
126                         if( !changed_params->equivalent(*asset, 1, 1, mwindow->edl) )
127                                 changed = 1;
128                 }
129                 else {
130                         nested_edl = (EDL*)indexable;
131                         if( strcmp(changed_params->path, nested_edl->path)
132 //                              || changed_params->sample_rate != nested_edl->session->sample_rate
133 //                              || !EQUIV(changed_params->frame_rate, nested_edl->session->frame_rate
134                         )
135                                 changed = 1;
136                 }
137                 if( changed ) {
138                         mwindow->gui->lock_window();
139 //printf("AssetEdit::handle_close_event %d\n", __LINE__);
140
141 // Omit index status from copy since an index rebuild may have been
142 // happening when new_asset was created but not be happening anymore.
143                         if( asset ) {
144                                 mwindow->remove_from_caches(asset);
145 //printf("AssetEdit::handle_close_event %d %f\n", __LINE__, asset->get_frame_rate());
146                                 asset->copy_from(changed_params, 0);
147 //printf("AssetEdit::handle_close_event %d %d %d\n", __LINE__, changed_params->bits, asset->bits);
148                         }
149                         else {
150                                 strcpy(nested_edl->path, changed_params->path);
151 // Other parameters can't be changed because they're defined in the other EDL
152 //              nested_edl->session->frame_rate = changed_params->frame_rate;
153 //              nested_edl->session->sample_rate = changed_params->sample_rate;
154                         }
155 //printf("AssetEdit::handle_close_event %d\n", __LINE__);
156
157                         mwindow->gui->update(0, FORCE_REDRAW, 0, 0, 0, 0, 0);
158 //printf("AssetEdit::handle_close_event %d\n", __LINE__);
159
160 // Start index rebuilding
161                         if( (asset && asset->audio_data) || nested_edl) {
162                                 char source_filename[BCTEXTLEN];
163                                 char index_filename[BCTEXTLEN];
164                                 IndexFile::get_index_filename(source_filename,
165                                         mwindow->preferences->index_directory,
166                                         index_filename,
167                                         indexable->path);
168                                 remove_file(index_filename);
169                                 indexable->index_state->index_status = INDEX_NOTTESTED;
170                                 mwindow->mainindexes->add_indexable(indexable);
171                                 mwindow->mainindexes->start_build();
172                         }
173                         mwindow->gui->unlock_window();
174 //printf("AssetEdit::handle_close_event %d\n", __LINE__);
175                         mwindow->awindow->gui->update_picon(indexable);
176                         mwindow->awindow->gui->async_update_assets();
177
178                         mwindow->restart_brender();
179                         mwindow->sync_parameters(CHANGE_ALL);
180 //printf("AssetEdit::handle_close_event %d\n", __LINE__);
181                 }
182         }
183
184         this->indexable->remove_user();
185         this->indexable = 0;
186 //printf("AssetEdit::handle_close_event %d\n", __LINE__);
187 }
188
189 BC_Window* AssetEdit::new_gui()
190 {
191         window = new AssetEditWindow(mwindow, this);
192         window->create_objects();
193         return window;
194 }
195
196 int AssetEdit::window_height()
197 {
198         int h = yS(128 + 64);
199         if( indexable->have_audio() ) h += yS(200);
200         if( indexable->have_video() ) {
201                 h += yS(160);
202                 if( indexable->is_asset ) {
203                         Asset *asset = (Asset *)indexable;
204                         if( File::can_scale_input(asset) )
205                                 h += yS(42);
206                         if( asset->timecode >= 0 )
207                                 h += yS(32);
208                 }
209         }
210         return yS(h);
211 }
212
213 #define AEW_W xS(450)
214
215 AssetEditWindow::AssetEditWindow(MWindow *mwindow, AssetEdit *asset_edit)
216  : BC_Window(_(PROGRAM_NAME ": Asset Info"),
217         asset_edit->x - AEW_W/2, asset_edit->y - asset_edit->window_height()/2,
218         AEW_W, asset_edit->window_height(), 0, 0, 1)
219 {
220         this->mwindow = mwindow;
221         this->asset_edit = asset_edit;
222         bitspopup = 0;
223         path_text = 0;
224         path_button = 0;
225         hilo = 0;
226         lohi = 0;
227         allow_edits = 0;
228         detail_dialog = 0;
229         win_width = 0;
230         win_height = 0;
231 // *** CONTEXT_HELP ***
232         context_help_set_keyword("Info Asset Details");
233 }
234
235
236
237
238
239 AssetEditWindow::~AssetEditWindow()
240 {
241         lock_window("AssetEditWindow::~AssetEditWindow");
242         delete bitspopup;
243         delete detail_dialog;
244         unlock_window();
245 }
246
247
248
249
250 void AssetEditWindow::create_objects()
251 {
252         int xpad10 = xS(10);
253         int ypad5 = yS(5), ypad10 = yS(10), ypad20 = yS(20), ypad30 = yS(30);
254         int y = ypad10, x = xpad10, x1 = xpad10, x2 = xS(190);
255         char string[BCTEXTLEN];
256         FileSystem fs;
257         BC_Title *title;
258         Asset *asset = 0;
259         EDL *nested_edl = 0;
260
261         if( asset_edit->indexable->is_asset )
262                 asset = (Asset*)asset_edit->indexable;
263         else
264                 nested_edl = (EDL*)asset_edit->indexable;
265
266         allow_edits = asset && asset->format == FILE_PCM ? 1 : 0;
267         int vmargin = yS(allow_edits ? 30 : 20);
268         lock_window("AssetEditWindow::create_objects");
269
270         add_subwindow(path_text = new AssetEditPathText(this, y));
271         add_subwindow(path_button = new AssetEditPath(mwindow, this,
272                 path_text, y, asset_edit->indexable->path,
273                 _(PROGRAM_NAME ": Asset path"),
274                 _("Select a file for this asset:")));
275         y += yS(30);
276
277         if( asset ) {
278                 add_subwindow(new BC_Title(x, y, _("File format:")));
279                 x = x2;
280                 add_subwindow(new BC_Title(x, y, File::formattostr(asset->format),
281                         MEDIUMFONT,
282                         mwindow->theme->assetedit_color));
283                 x = x1;
284                 y += ypad20;
285
286                 int64_t bytes = fs.get_size(asset->path);
287                 add_subwindow(new BC_Title(x, y, _("Bytes:")));
288                 sprintf(string, "%jd", bytes);
289                 Units::punctuate(string);
290
291
292                 add_subwindow(new BC_Title(x2, y, string, MEDIUMFONT, mwindow->theme->assetedit_color));
293                 if( asset->format == FILE_MPEG || asset->format == FILE_FFMPEG ) {
294                         detail_dialog = new DetailAssetDialog(mwindow);
295                         BC_GenericButton *detail = new DetailAssetButton(this, x2+xS(120), y);
296                         add_subwindow(detail);
297                 }
298
299                 y += ypad20;
300                 x = x1;
301
302                 double length = 0.;
303                 y += ypad20;
304                 x = x1;
305
306                 if( asset->audio_length > 0 )
307                         length = (double)asset->audio_length / asset->sample_rate;
308                 if( asset->video_length > 0 )
309                         length = MAX(length, (double)asset->video_length / asset->frame_rate);
310                 int64_t bitrate;
311                 if( !EQUIV(length, 0) )
312                         bitrate = (int64_t)(bytes * 8 / length);
313                 else
314                         bitrate = bytes;
315                 add_subwindow(new BC_Title(x, y, _("Bitrate (bits/sec):")));
316                 sprintf(string, "%jd", bitrate);
317
318                 Units::punctuate(string);
319                 add_subwindow(new BC_Title(x2, y, string, MEDIUMFONT, mwindow->theme->assetedit_color));
320
321                 y += ypad30;
322                 x = x1;
323         }
324
325         if( (asset && asset->audio_data) || nested_edl ) {
326                 add_subwindow(new BC_Bar(x, y, get_w() - x * 2));
327                 y += ypad5;
328
329                 add_subwindow(new BC_Title(x, y, _("Audio:"), LARGEFONT, RED));
330
331                 y += ypad30;
332
333                 if( asset ) {
334                         if( asset->get_compression_text(1, 0) ) {
335                                 add_subwindow(new BC_Title(x, y, _("Compression:")));
336                                 x = x2;
337                                 add_subwindow(new BC_Title(x,
338                                         y,
339                                         asset->get_compression_text(1, 0),
340                                         MEDIUMFONT,
341                                         mwindow->theme->assetedit_color));
342                                 y += vmargin;
343                                 x = x1;
344                         }
345                 }
346
347                 add_subwindow(new BC_Title(x, y, _("Channels:")));
348                 sprintf(string, "%d", asset_edit->changed_params->channels);
349
350                 x = x2;
351                 if( allow_edits ) {
352                         BC_TumbleTextBox *textbox = new AssetEditChannels(this,
353                                 string,
354                                 x,
355                                 y);
356                         textbox->create_objects();
357                         y += vmargin;
358                 }
359                 else {
360                         add_subwindow(new BC_Title(x, y, string, MEDIUMFONT, mwindow->theme->assetedit_color));
361                         y += ypad20;
362                 }
363
364                 x = x1;
365                 add_subwindow(new BC_Title(x, y, _("Sample rate:")));
366                 sprintf(string, "%d", asset_edit->changed_params->sample_rate);
367
368                 x = x2;
369                 if( asset ) {
370                         BC_TextBox *textbox;
371                         add_subwindow(textbox = new AssetEditRate(this, string, x, y));
372                         x += textbox->get_w();
373                         add_subwindow(new SampleRatePulldown(mwindow, textbox, x, y));
374                 }
375                 else {
376                         add_subwindow(new BC_Title(x, y, string, MEDIUMFONT, mwindow->theme->assetedit_color));
377                 }
378
379                 y += ypad30;
380                 x = x1;
381
382                 if( asset ) {
383                         add_subwindow(new BC_Title(x, y, _("Bits:")));
384                         x = x2;
385                         if( allow_edits ) {
386                                 bitspopup = new BitsPopup(this, x, y,
387                                         &asset_edit->changed_params->bits,
388                                         1, 1, 1, 0, 1);
389                                 bitspopup->create_objects();
390                         }
391                         else
392                                 add_subwindow(new BC_Title(x, y, File::bitstostr(asset->bits), MEDIUMFONT, mwindow->theme->assetedit_color));
393
394
395                         x = x1;
396                         y += vmargin;
397                         add_subwindow(new BC_Title(x, y, _("Header length:")));
398                         sprintf(string, "%d", asset->header);
399
400                         x = x2;
401                         if( allow_edits )
402                                 add_subwindow(new AssetEditHeader(this, string, x, y));
403                         else
404                                 add_subwindow(new BC_Title(x, y, string, MEDIUMFONT, mwindow->theme->assetedit_color));
405
406                         y += vmargin;
407                         x = x1;
408
409                         add_subwindow(new BC_Title(x, y, _("Byte order:")));
410
411                         if( allow_edits )
412                         {
413                                 x = x2;
414
415                                 add_subwindow(lohi = new AssetEditByteOrderLOHI(this,
416                                         asset->byte_order, x, y));
417                                 x += xS(70);
418                                 add_subwindow(hilo = new AssetEditByteOrderHILO(this,
419                                         !asset->byte_order, x, y));
420                                 y += vmargin;
421                         }
422                         else {
423                                 x = x2;
424                                 if( asset->byte_order )
425                                         add_subwindow(new BC_Title(x, y, _("Lo-Hi"), MEDIUMFONT, mwindow->theme->assetedit_color));
426                                 else
427                                         add_subwindow(new BC_Title(x, y, _("Hi-Lo"), MEDIUMFONT, mwindow->theme->assetedit_color));
428                                 y += vmargin;
429                         }
430
431
432                         x = x1;
433                         if( allow_edits ) {
434         //                      add_subwindow(new BC_Title(x, y, _("Values are signed:")));
435                                 add_subwindow(new AssetEditSigned(this, asset->signed_, x, y));
436                         }
437                         else {
438                                 if( !asset->signed_ && asset->bits == 8 )
439                                         add_subwindow(new BC_Title(x, y, _("Values are unsigned")));
440                                 else
441                                         add_subwindow(new BC_Title(x, y, _("Values are signed")));
442                         }
443
444                         y += ypad30;
445                 }
446         }
447
448         x = x1;
449         if( (asset && asset->video_data) || nested_edl ) {
450                 add_subwindow(new BC_Bar(x, y, get_w() - x * 2));
451                 y += ypad5;
452
453                 add_subwindow(new BC_Title(x, y, _("Video:"), LARGEFONT, RED));
454                 y += ypad30;
455                 x = x1;
456
457
458                 if( asset && asset->get_compression_text(0,1) ) {
459                         add_subwindow(new BC_Title(x, y, _("Compression:")));
460                         x = x2;
461                         add_subwindow(new BC_Title(x,
462                                 y,
463                                 asset->get_compression_text(0,1),
464                                 MEDIUMFONT,
465                                 mwindow->theme->assetedit_color));
466                         y += vmargin;
467                         x = x1;
468                 }
469
470                 add_subwindow(new BC_Title(x, y, _("Frame rate:")));
471                 x = x2;
472                 sprintf(string, "%.4f", asset_edit->changed_params->frame_rate);
473
474 //printf("AssetEditWindow::create_objects %d %f\n", __LINE__, asset_edit->changed_params->frame_rate);
475                 if( asset ) {
476                         BC_TextBox *framerate;
477                         add_subwindow(framerate = new AssetEditFRate(this, string, x, y));
478                         x += framerate->get_w();
479                         add_subwindow(new FrameRatePulldown(mwindow, framerate, x, y));
480                 }
481                 else {
482                         add_subwindow(new BC_Title(x, y, string, MEDIUMFONT, mwindow->theme->assetedit_color));
483                 }
484
485                 y += ypad30;
486                 x = x1;
487                 add_subwindow(new BC_Title(x, y, _("Width:")));
488                 x = x2;
489                 sprintf(string, "%d", asset_edit->changed_params->width);
490                 win_width = new BC_Title(x, y, string, MEDIUMFONT, mwindow->theme->assetedit_color);
491                 add_subwindow(win_width);
492
493                 y += vmargin;
494                 x = x1;
495                 add_subwindow(new BC_Title(x, y, _("Height:")));
496                 x = x2;
497                 sprintf(string, "%d", asset_edit->changed_params->height);
498                 win_height = new BC_Title(x, y, string, MEDIUMFONT, mwindow->theme->assetedit_color);
499                 add_subwindow(win_height);
500                 y += win_height->get_h() + ypad5;
501
502                 if( asset && File::can_scale_input(asset) ) {
503                         y += ypad5;
504                         x = x1;
505                         add_subwindow(new BC_Title(x, y, _("Actual width:")));
506                         x = x2;
507                         sprintf(string, "%d", asset->actual_width);
508                         add_subwindow(new BC_Title(x, y, string, MEDIUMFONT, mwindow->theme->assetedit_color));
509
510                         BC_GenericButton *resize = new ResizeAssetButton(this, x+xS(64), y);
511                         add_subwindow(resize);
512
513                         y += vmargin;
514                         x = x1;
515                         add_subwindow(new BC_Title(x, y, _("Actual height:")));
516                         x = x2;
517                         sprintf(string, "%d", asset->actual_height);
518                         title = new BC_Title(x, y, string, MEDIUMFONT, mwindow->theme->assetedit_color);
519                         add_subwindow(title);
520                         y += title->get_h() + ypad5;
521                 }
522                 if( asset ) {
523                         add_subwindow(title = new BC_Title(x1, y, _("Asset's interlacing:")));
524                         ilacemode_to_text(string, asset->interlace_mode);
525                         AssetEditILacemode *edit_ilace_mode;
526                         add_subwindow(edit_ilace_mode = new AssetEditILacemode(this, string, x2, y, xS(160)));
527                         add_subwindow(new AssetEditInterlacemodePulldown(mwindow, edit_ilace_mode,
528                                 &asset_edit->changed_params->interlace_mode,
529                                 (ArrayList<BC_ListBoxItem*>*)&mwindow->interlace_asset_modes,
530                                 x2 + edit_ilace_mode->get_w(), y));
531                         y += title->get_h() + yS(15);
532                 }
533         }
534         if( asset && asset->timecode >= 0 ) {
535                 char text[BCSTRLEN], *tc = text;
536                 Units::totext(tc, asset->timecode, TIME_HMSF,
537                         asset->sample_rate, asset->frame_rate);
538                 const char *hrs  = tc;  tc = strchr(tc, ':');  *tc++ = 0;
539                 const char *mins = tc;  tc = strchr(tc, ':');  *tc++ = 0;
540                 const char *secs = tc;  tc = strchr(tc, ':');  *tc++ = 0;
541                 const char *rest = tc;
542                 int padw = BC_Title::calculate_w(this, ":", MEDIUMFONT);
543                 int fldw = BC_Title::calculate_w(this, "00", MEDIUMFONT) + 5;
544                 int hdrw = fldw + padw;  x = x2;
545                 add_subwindow(title = new BC_Title(x, y, _("hour"), SMALLFONT));  x += hdrw;
546                 add_subwindow(title = new BC_Title(x, y, _("min"),  SMALLFONT));  x += hdrw;
547                 add_subwindow(title = new BC_Title(x, y, _("sec"),  SMALLFONT));  x += hdrw;
548                 add_subwindow(title = new BC_Title(x, y, _("frms"), SMALLFONT));
549                 y += title->get_h() + xS(3);
550                 add_subwindow(title = new BC_Title(x1, y, _("Time Code Start:")));
551                 add_subwindow(tc_hrs = new BC_TextBox(x=x2, y, fldw, 1, hrs));
552                 add_subwindow(new BC_Title(x += tc_hrs->get_w(), y, ":"));
553                 add_subwindow(tc_mins = new BC_TextBox(x += padw, y, fldw, 1, mins));
554                 add_subwindow(new BC_Title(x += tc_mins->get_w(), y, ":"));
555                 add_subwindow(tc_secs = new BC_TextBox(x += padw, y , fldw, 1, secs));
556                 add_subwindow(new BC_Title(x += tc_secs->get_w(), y, ":"));
557                 add_subwindow(tc_rest = new BC_TextBox(x += 10, y, fldw, 1, rest));
558                 y += title->get_h() + ypad5;
559         }
560
561         add_subwindow(new BC_OKButton(this));
562         add_subwindow(new BC_CancelButton(this));
563         show_window();
564         unlock_window();
565 }
566
567 void AssetEditWindow::show_info_detail()
568 {
569         int cur_x, cur_y;
570         get_abs_cursor(cur_x, cur_y, 0);
571         detail_dialog->start((Asset*)asset_edit->indexable, cur_x, cur_y);
572 }
573
574
575 AssetEditChannels::AssetEditChannels(AssetEditWindow *fwindow,
576         char *text,
577         int x,
578         int y)
579  : BC_TumbleTextBox(fwindow, (int)atol(text), (int)1,
580                 (int)MAXCHANNELS, x, y, xS(50))
581 {
582         this->fwindow = fwindow;
583 }
584
585 int AssetEditChannels::handle_event()
586 {
587         Asset *asset = fwindow->asset_edit->changed_params;
588         asset->channels = atol(get_text());
589         return 1;
590 }
591
592 AssetEditRate::AssetEditRate(AssetEditWindow *fwindow, char *text, int x, int y)
593  : BC_TextBox(x, y, xS(100), 1, text)
594 {
595         this->fwindow = fwindow;
596 }
597
598 int AssetEditRate::handle_event()
599 {
600         Asset *asset = fwindow->asset_edit->changed_params;
601         asset->sample_rate = atol(get_text());
602         return 1;
603 }
604
605 AssetEditFRate::AssetEditFRate(AssetEditWindow *fwindow, char *text, int x, int y)
606  : BC_TextBox(x, y, xS(100), 1, text)
607 {
608         this->fwindow = fwindow;
609 }
610
611 int AssetEditFRate::handle_event()
612 {
613         Asset *asset = fwindow->asset_edit->changed_params;
614         asset->frame_rate = atof(get_text());
615         return 1;
616 }
617
618
619 AssetEditILacemode::AssetEditILacemode(AssetEditWindow *fwindow, const char *text, int x, int y, int w)
620  : BC_TextBox(x, y, w, 1, text)
621 {
622         this->fwindow = fwindow;
623 }
624
625 int AssetEditILacemode::handle_event()
626 {
627         Asset *asset = fwindow->asset_edit->changed_params;
628         asset->interlace_mode = ilacemode_from_text(get_text(), ILACE_ASSET_MODEDEFAULT);
629         return 1;
630 }
631
632 AssetEditInterlacemodePulldown::AssetEditInterlacemodePulldown(MWindow *mwindow,
633                 BC_TextBox *output_text, int *output_value,
634                 ArrayList<BC_ListBoxItem*> *data, int x, int y)
635  : BC_ListBox(x, y, xS(160), yS(80), LISTBOX_TEXT, data, 0, 0, 1, 0, 1)
636 {
637         this->mwindow = mwindow;
638         this->output_text = output_text;
639         this->output_value = output_value;
640         output_text->update(interlacemode_to_text());
641 }
642
643 int AssetEditInterlacemodePulldown::handle_event()
644 {
645         output_text->update(get_selection(0, 0)->get_text());
646         *output_value = ((InterlacemodeItem*)get_selection(0, 0))->value;
647         return 1;
648 }
649
650 char* AssetEditInterlacemodePulldown::interlacemode_to_text()
651 {
652         ilacemode_to_text(this->string,*output_value);
653         return (this->string);
654 }
655
656 AssetEditHeader::AssetEditHeader(AssetEditWindow *fwindow, char *text, int x, int y)
657  : BC_TextBox(x, y, xS(100), 1, text)
658 {
659         this->fwindow = fwindow;
660 }
661
662 int AssetEditHeader::handle_event()
663 {
664         Asset *asset = fwindow->asset_edit->changed_params;
665         asset->header = atol(get_text());
666         return 1;
667 }
668
669 AssetEditByteOrderLOHI::AssetEditByteOrderLOHI(AssetEditWindow *fwindow,
670         int value,
671         int x,
672         int y)
673  : BC_Radial(x, y, value, _("Lo-Hi"))
674 {
675         this->fwindow = fwindow;
676 }
677
678 int AssetEditByteOrderLOHI::handle_event()
679 {
680         Asset *asset = fwindow->asset_edit->changed_params;
681         asset->byte_order = 1;
682         fwindow->hilo->update(0);
683         update(1);
684         return 1;
685 }
686
687 AssetEditByteOrderHILO::AssetEditByteOrderHILO(AssetEditWindow *fwindow,
688         int value,
689         int x,
690         int y)
691  : BC_Radial(x, y, value, _("Hi-Lo"))
692 {
693         this->fwindow = fwindow;
694 }
695
696 int AssetEditByteOrderHILO::handle_event()
697 {
698         Asset *asset = fwindow->asset_edit->changed_params;
699         asset->byte_order = 0;
700         fwindow->lohi->update(0);
701         update(1);
702         return 1;
703 }
704
705 AssetEditSigned::AssetEditSigned(AssetEditWindow *fwindow,
706         int value,
707         int x,
708         int y)
709  : BC_CheckBox(x, y, value, _("Values are signed"))
710 {
711         this->fwindow = fwindow;
712 }
713
714 int AssetEditSigned::handle_event()
715 {
716         Asset *asset = fwindow->asset_edit->changed_params;
717         asset->signed_ = get_value();
718         return 1;
719 }
720
721
722
723
724
725
726
727 AssetEditPathText::AssetEditPathText(AssetEditWindow *fwindow, int y)
728  : BC_TextBox(5, y, xS(300), 1, fwindow->asset_edit->changed_params->path)
729 {
730         this->fwindow = fwindow;
731 }
732 AssetEditPathText::~AssetEditPathText()
733 {
734 }
735 int AssetEditPathText::handle_event()
736 {
737         strcpy(fwindow->asset_edit->changed_params->path, get_text());
738         return 1;
739 }
740
741 AssetEditPath::AssetEditPath(MWindow *mwindow, AssetEditWindow *fwindow,
742         BC_TextBox *textbox, int y, const char *text,
743         const char *window_title, const char *window_caption)
744  : BrowseButton(mwindow->theme, fwindow, textbox, yS(310), y, text,
745         window_title, window_caption, 0)
746 {
747         this->fwindow = fwindow;
748 }
749
750 AssetEditPath::~AssetEditPath() {}
751
752
753
754
755 DetailAssetButton::DetailAssetButton(AssetEditWindow *fwindow, int x, int y)
756  : BC_GenericButton(x, y, _("Detail"))
757 {
758         this->fwindow = fwindow;
759 }
760
761 DetailAssetButton::~DetailAssetButton()
762 {
763 }
764
765 int DetailAssetButton::handle_event()
766 {
767         fwindow->show_info_detail();
768         return 1;
769 }
770
771 #define DTL_W xS(600)
772 #define DTL_H yS(500)
773
774 DetailAssetWindow::DetailAssetWindow(MWindow *mwindow,
775         DetailAssetDialog *detail_dialog, Asset *asset)
776  : BC_Window(_("Asset Detail"),
777         detail_dialog->x - DTL_W/2, detail_dialog->y - DTL_H/2, DTL_W, DTL_H)
778 {
779         this->mwindow = mwindow;
780         this->detail_dialog = detail_dialog;
781         this->asset = asset;
782         asset->add_user();
783         info[0] = 0;
784         text = 0;
785 // *** CONTEXT_HELP ***
786         context_help_set_keyword("Info Asset Details");
787 }
788
789 DetailAssetWindow::~DetailAssetWindow()
790 {
791         asset->remove_user();
792         delete text;
793 }
794
795 DetailAssetDialog::DetailAssetDialog(MWindow *mwindow)
796  : BC_DialogThread()
797 {
798         this->mwindow = mwindow;
799         dwindow = 0;
800 }
801
802 DetailAssetDialog::~DetailAssetDialog()
803 {
804         close_window();
805 }
806
807 void DetailAssetWindow::create_objects()
808 {
809         int y = yS(10), x = xS(10);
810         char file_name[BCTEXTLEN];
811         int len = sizeof(info);
812         strncpy(info,_("no info available"),len);
813         if( !mwindow->preferences->get_asset_file_path(asset, file_name) ) {
814                 switch( asset->format ) {
815 #ifdef HAVE_LIBZMPEG
816                 case FILE_MPEG:
817                         FileMPEG::get_info(asset->path, file_name, &info[0],len);
818                         break;
819 #endif
820                 case FILE_FFMPEG:
821                         FileFFMPEG::get_info(asset->path, &info[0],len);
822                         break;
823                 }
824         }
825         lock_window("DetailAssetWindow::create_objects");
826         int text_h = get_h()-y - BC_OKButton::calculate_h() - yS(15);
827         int lines = BC_TextBox::pixels_to_rows(this, MEDIUMFONT, text_h);
828         text = new BC_ScrollTextBox(this, x, y, get_w()-xS(32), lines, info, -len);
829         text->create_objects();  text->set_text_row(0);
830         add_subwindow(new BC_OKButton(this));
831         show_window();
832         unlock_window();
833 }
834
835 void DetailAssetDialog::start(Asset *asset, int x, int y)
836 {
837         close_window();
838         this->asset = asset;
839         this->x = x;  this->y = y;
840         BC_DialogThread::start();
841 }
842
843 BC_Window *DetailAssetDialog::new_gui()
844 {
845         dwindow = new DetailAssetWindow(mwindow, this, asset);
846         dwindow->create_objects();
847         return dwindow;
848 }
849