dvd/bd scaling fixes, es/de .po file updates
[goodguy/history.git] / cinelerra-5.1 / cinelerra / dvdcreate.C
1 #include "asset.h"
2 #include "clip.h"
3 #include "dvdcreate.h"
4 #include "edl.h"
5 #include "edit.h"
6 #include "edits.h"
7 #include "edlsession.h"
8 #include "filexml.h"
9 #include "keyframe.h"
10 #include "labels.h"
11 #include "mainerror.h"
12 #include "mainundo.h"
13 #include "mwindow.h"
14 #include "mwindowgui.h"
15 #include "plugin.h"
16 #include "pluginset.h"
17 #include "track.h"
18 #include "tracks.h"
19
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <errno.h>
23 #include <sys/stat.h>
24 #include <sys/statfs.h>
25
26 // DVD Creation
27
28 #define HD_1920x1080_2997       0
29 #define HD_1920x1080_2500       1
30 #define HD_1280x720_5994p       2
31 #define HD_1280x720_5000p       3
32 #define HD_720x576_5000p        4
33 #define HD_720x576_2500         5
34 #define HD_720x480_5994p        6
35 #define HD_720x480_2997         7
36
37 static struct hd_format {
38         const char *name;
39         int w, h;
40         double framerate;
41 } hd_formats[] = {
42         { "1920x1080 29.97",      1920,1080, 29.97  },
43         { "1920x1080 25",         1920,1080, 25     },
44         { "1280x720 59.94p",      1280,720,  59.94  },
45         { "1280x720 50p",         1280,720,  50     },
46         { "720x576 50p(PAL)",      720,576,  50     },
47         { "720x576 25 (PAL)",      720,576,  25     },
48         { "720x480 59.94p(NTSC)",  720,480,  59.94  },
49         { "720x480 29.97 (NTSC)",  720,480,  29.97  },
50 };
51
52 const int64_t CreateDVD_Thread::DVD_SIZE = 4700000000;
53 const int CreateDVD_Thread::DVD_STREAMS = 1;
54 const int CreateDVD_Thread::DVD_WIDTH = 720;
55 const int CreateDVD_Thread::DVD_HEIGHT = 480;
56 const double CreateDVD_Thread::DVD_ASPECT_WIDTH = 4.;
57 const double CreateDVD_Thread::DVD_ASPECT_HEIGHT = 3.;
58 const double CreateDVD_Thread::DVD_WIDE_ASPECT_WIDTH = 16.;
59 const double CreateDVD_Thread::DVD_WIDE_ASPECT_HEIGHT = 9.;
60 const double CreateDVD_Thread::DVD_FRAMERATE = 30000. / 1001.;
61 const int CreateDVD_Thread::DVD_MAX_BITRATE = 8000000;
62 const int CreateDVD_Thread::DVD_CHANNELS = 2;
63 const int CreateDVD_Thread::DVD_WIDE_CHANNELS = 6;
64 const double CreateDVD_Thread::DVD_SAMPLERATE = 48000;
65 const double CreateDVD_Thread::DVD_KAUDIO_RATE = 224;
66
67
68 CreateDVD_MenuItem::CreateDVD_MenuItem(MWindow *mwindow)
69  : BC_MenuItem(_("DVD Render..."), _("Shift-D"), 'D')
70 {
71         set_shift(1); 
72         this->mwindow = mwindow;
73 }
74
75 int CreateDVD_MenuItem::handle_event()
76 {
77         mwindow->create_dvd->start();
78         return 1;
79 }
80
81
82 CreateDVD_Thread::CreateDVD_Thread(MWindow *mwindow)
83  : BC_DialogThread()
84 {
85         this->mwindow = mwindow;
86         this->gui = 0;
87         this->use_deinterlace = 0;
88         this->use_scale = 0;
89         this->use_histogram = 0;
90         this->use_inverse_telecine = 0;
91         this->use_wide_audio = 0;
92         this->use_wide_aspect = 0;
93         this->use_ffmpeg = 0;
94         this->use_resize_tracks = 0;
95         this->use_label_chapters = 0;
96
97         this->dvd_size = DVD_SIZE;
98         this->dvd_width = DVD_WIDTH;
99         this->dvd_height = DVD_HEIGHT;
100         this->dvd_aspect_width = DVD_ASPECT_WIDTH;
101         this->dvd_aspect_height = DVD_ASPECT_HEIGHT;
102         this->dvd_framerate = DVD_FRAMERATE;
103         this->dvd_samplerate = DVD_SAMPLERATE;
104         this->dvd_max_bitrate = DVD_MAX_BITRATE;
105         this->dvd_kaudio_rate = DVD_KAUDIO_RATE;
106         this->max_w = this->max_h = 0;
107 }
108
109 CreateDVD_Thread::~CreateDVD_Thread()
110 {
111         close_window();
112 }
113
114 int CreateDVD_Thread::create_dvd_jobs(ArrayList<BatchRenderJob*> *jobs,
115         const char *tmp_path, const char *asset_title)
116 {
117         EDL *edl = mwindow->edl;
118         if( !edl || !edl->session ) {
119                 char msg[BCTEXTLEN];
120                 sprintf(msg, _("No EDL/Session"));
121                 MainError::show_error(msg);
122                 return 1;
123         }
124         EDLSession *session = edl->session;
125
126         double total_length = edl->tracks->total_length();
127         if( total_length <= 0 ) {
128                 char msg[BCTEXTLEN];
129                 sprintf(msg, _("No content: %s"), asset_title);
130                 MainError::show_error(msg);
131                 return 1;
132         }
133
134         char asset_dir[BCTEXTLEN];
135         sprintf(asset_dir, "%s/%s", tmp_path, asset_title);
136
137         if( mkdir(asset_dir, 0777) ) {
138                 char err[BCTEXTLEN], msg[BCTEXTLEN];
139                 strerror_r(errno, err, sizeof(err));
140                 sprintf(msg, _("Unable to create directory: %s\n-- %s"), asset_dir, err);
141                 MainError::show_error(msg);
142                 return 1;
143         }
144
145         double old_samplerate = session->sample_rate;
146         double old_framerate = session->frame_rate;
147
148         session->video_channels = DVD_STREAMS;
149         session->video_tracks = DVD_STREAMS;
150         session->frame_rate = dvd_framerate;
151         session->output_w = dvd_width;
152         session->output_h = dvd_height;
153         session->aspect_w = dvd_aspect_width;
154         session->aspect_h = dvd_aspect_height;
155         session->sample_rate = dvd_samplerate;
156         session->audio_channels = session->audio_tracks =
157                 use_wide_audio ? DVD_WIDE_CHANNELS : DVD_CHANNELS;
158
159         char script_filename[BCTEXTLEN];
160         sprintf(script_filename, "%s/dvd.sh", asset_dir);
161         int fd = open(script_filename, O_WRONLY+O_CREAT+O_TRUNC, 0755);
162         FILE *fp = fdopen(fd, "w");
163         if( !fp ) {
164                 char err[BCTEXTLEN], msg[BCTEXTLEN];
165                 strerror_r(errno, err, sizeof(err));
166                 sprintf(msg, _("Unable to save: %s\n-- %s"), script_filename, err);
167                 MainError::show_error(msg);
168                 return 1;
169         }
170         fprintf(fp,"#!/bin/bash\n");
171         fprintf(fp,"echo \"running %s\" $# $*\n", script_filename);
172         fprintf(fp,"\n");
173         char exe_path[BCTEXTLEN];
174         get_exe_path(exe_path);
175         fprintf(fp,"PATH=$PATH:%s\n",exe_path);
176         if( !use_ffmpeg ) {
177                 fprintf(fp,"mplex -f 8 -o $1/dvd.mpg $1/dvd.m2v $1/dvd.ac3\n");
178                 fprintf(fp,"\n");
179         }
180         fprintf(fp,"rm -rf $1/iso\n");
181         fprintf(fp,"mkdir -p $1/iso\n");
182         fprintf(fp,"\n");
183         fprintf(fp,"dvdauthor -x - <<eof\n");
184         fprintf(fp,"<dvdauthor dest=\"$1/iso\">\n");
185         fprintf(fp,"  <vmgm>\n");
186         fprintf(fp,"    <fpc> jump title 1; </fpc>\n");
187         fprintf(fp,"  </vmgm>\n");
188         fprintf(fp,"  <titleset>\n");
189         fprintf(fp,"    <titles>\n");
190         fprintf(fp,"    <video format=\"ntsc\" aspect=\"%d:%d\" resolution=\"%dx%d\"/>\n",
191                 (int)session->aspect_w, (int)session->aspect_h,
192                 session->output_w, session->output_h);
193         fprintf(fp,"    <audio format=\"ac3\" lang=\"en\"/>\n");
194         fprintf(fp,"    <pgc>\n");
195         fprintf(fp,"      <vob file=\"$1/dvd.mpg\" chapters=\"");
196         if( use_label_chapters && edl->labels ) {
197                 Label *label = edl->labels->first;
198                 while( label ) {
199                         int secs = label->position;
200                         int mins = secs / 60;
201                         int frms = (label->position-secs) * session->frame_rate;
202                         fprintf(fp,"%d:%02d:%02d.%d", mins/60, mins%60, secs%60, frms);
203                         if( (label=label->next) != 0 ) fprintf(fp, ",");
204                 }
205         }
206         else {
207                 int mins = 0;
208                 for( int secs=0 ; secs<total_length; secs+=10*60 ) {
209                         mins = secs / 60;
210                         fprintf(fp,"%d:%02d:00,", mins/60, mins%60);
211                 }
212                 fprintf(fp,"%d:%02d:00", mins/60, mins%60);
213         }
214         fprintf(fp,"\"/>\n");
215         fprintf(fp,"    </pgc>\n");
216         fprintf(fp,"    </titles>\n");
217         fprintf(fp,"  </titleset>\n");
218         fprintf(fp,"</dvdauthor>\n");
219         fprintf(fp,"eof\n");
220         fprintf(fp,"\n");
221         fprintf(fp,"echo To burn dvd, load blank media and run:\n");
222         fprintf(fp,"echo growisofs -dvd-compat -Z /dev/dvd -dvd-video $1/iso\n");
223         fprintf(fp,"\n");
224         fclose(fp);
225
226         if( use_wide_audio ) {
227                 session->audio_channels = session->audio_tracks = DVD_WIDE_CHANNELS;
228                 session->achannel_positions[0] = 90;
229                 session->achannel_positions[1] = 150;
230                 session->achannel_positions[2] = 30;
231                 session->achannel_positions[3] = 210;
232                 session->achannel_positions[4] = 330;
233                 session->achannel_positions[5] = 270;
234                 if( edl->tracks->recordable_audio_tracks() == DVD_WIDE_CHANNELS )
235                         mwindow->remap_audio(MWindow::AUDIO_1_TO_1);
236         }
237         else {
238                 session->audio_channels = session->audio_tracks = DVD_CHANNELS;
239                 session->achannel_positions[0] = 180;
240                 session->achannel_positions[1] = 0;
241                 if( edl->tracks->recordable_audio_tracks() == DVD_WIDE_CHANNELS )
242                         mwindow->remap_audio(MWindow::AUDIO_5_1_TO_2);
243         }
244
245         double new_samplerate = session->sample_rate;
246         double new_framerate = session->frame_rate;
247         edl->rechannel();
248         edl->resample(old_samplerate, new_samplerate, TRACK_AUDIO);
249         edl->resample(old_framerate, new_framerate, TRACK_VIDEO);
250
251         int64_t aud_size = ((dvd_kaudio_rate * total_length)/8 + 1000-1) * 1000;
252         int64_t vid_size = dvd_size*0.96 - aud_size;
253         int64_t vid_bitrate = (vid_size * 8) / total_length;
254         vid_bitrate /= 1000;  vid_bitrate *= 1000;
255         if( vid_bitrate > dvd_max_bitrate )
256                 vid_bitrate = dvd_max_bitrate;
257
258         char xml_filename[BCTEXTLEN];
259         sprintf(xml_filename, "%s/dvd.xml", asset_dir);
260         FileXML xml_file;
261         edl->save_xml(&xml_file, xml_filename, 0, 0);
262         xml_file.terminate_string();
263         if( xml_file.write_to_file(xml_filename) ) {
264                 char msg[BCTEXTLEN];
265                 sprintf(msg, _("Unable to save: %s"), xml_filename);
266                 MainError::show_error(msg);
267                 return 1;
268         }
269
270         BatchRenderJob *job = new BatchRenderJob(mwindow->preferences);
271         jobs->append(job);
272         strcpy(&job->edl_path[0], xml_filename);
273         Asset *asset = job->asset;
274
275         asset->layers = DVD_STREAMS;
276         asset->frame_rate = session->frame_rate;
277         asset->width = session->output_w;
278         asset->height = session->output_h;
279         asset->aspect_ratio = session->aspect_w / session->aspect_h;
280
281         if( use_ffmpeg ) {
282                 char option_path[BCTEXTLEN];
283                 sprintf(&asset->path[0],"%s/dvd.mpg", asset_dir);
284                 asset->format = FILE_FFMPEG;
285                 strcpy(asset->fformat, "dvd");
286
287                 asset->audio_data = 1;
288                 strcpy(asset->acodec, "dvd.dvd");
289                 FFMPEG::set_option_path(option_path, "audio/%s", asset->acodec);
290                 FFMPEG::load_options(option_path, asset->ff_audio_options,
291                          sizeof(asset->ff_audio_options));
292                 asset->ff_audio_bitrate = dvd_kaudio_rate * 1000;
293
294                 asset->video_data = 1;
295                 strcpy(asset->vcodec, "dvd.dvd");
296                 FFMPEG::set_option_path(option_path, "video/%s", asset->vcodec);
297                 FFMPEG::load_options(option_path, asset->ff_video_options,
298                          sizeof(asset->ff_video_options));
299                 asset->ff_video_bitrate = vid_bitrate;
300                 asset->ff_video_quality = 0;
301         }
302         else {
303                 sprintf(&asset->path[0],"%s/dvd.m2v", asset_dir);
304                 asset->video_data = 1;
305                 asset->format = FILE_VMPEG;
306                 asset->vmpeg_cmodel = BC_YUV420P;
307                 asset->vmpeg_fix_bitrate = 1;
308                 asset->vmpeg_bitrate = vid_bitrate;
309                 asset->vmpeg_quantization = 15;
310                 asset->vmpeg_iframe_distance = 15;
311                 asset->vmpeg_progressive = 0;
312                 asset->vmpeg_denoise = 0;
313                 asset->vmpeg_seq_codes = 0;
314                 asset->vmpeg_derivative = 2;
315                 asset->vmpeg_preset = 8;
316                 asset->vmpeg_field_order = 0;
317                 asset->vmpeg_pframe_distance = 0;
318                 job = new BatchRenderJob(mwindow->preferences);
319                 jobs->append(job);
320                 strcpy(&job->edl_path[0], xml_filename);
321                 asset = job->asset;
322                 
323                 sprintf(&asset->path[0],"%s/dvd.ac3", asset_dir);
324                 asset->audio_data = 1;
325                 asset->format = FILE_AC3;
326                 asset->channels = session->audio_channels;
327                 asset->sample_rate = session->sample_rate;
328                 asset->bits = 16;
329                 asset->byte_order = 0;
330                 asset->signed_ = 1;
331                 asset->header = 0;
332                 asset->dither = 0;
333                 asset->ac3_bitrate = dvd_kaudio_rate;
334         }
335
336         job = new BatchRenderJob(mwindow->preferences);
337         jobs->append(job);
338         job->edl_path[0] = '@';
339         strcpy(&job->edl_path[1], script_filename);
340         strcpy(&job->asset->path[0], asset_dir);
341
342         return 0;
343 }
344
345 void CreateDVD_Thread::handle_close_event(int result)
346 {
347         if( result ) return;
348         mwindow->batch_render->load_defaults(mwindow->defaults);
349         mwindow->undo->update_undo_before();
350         KeyFrame keyframe;  char data[BCTEXTLEN];
351         if( use_deinterlace ) {
352                 sprintf(data,"<DEINTERLACE MODE=1>");
353                 keyframe.set_data(data);
354                 insert_video_plugin("Deinterlace", &keyframe);
355         }
356         if( use_inverse_telecine ) {
357                 sprintf(data,"<IVTC FRAME_OFFSET=0 FIRST_FIELD=0 "
358                         "AUTOMATIC=1 AUTO_THRESHOLD=2.0e+00 PATTERN=2>");
359                 keyframe.set_data(data);
360                 insert_video_plugin("Inverse Telecine", &keyframe);
361         }
362         if( use_scale ) {
363                 sprintf(data,"<SCALE TYPE=%d X_FACTOR=%f Y_FACTOR=%f "
364                         "WIDTH=%d HEIGHT=%d CONSTRAIN=0>",
365                         max_w >= dvd_width || max_h >= dvd_height ? 1 : 0,
366                         max_w > 0 ? (double)dvd_width/max_w : 1,
367                         max_h > 0 ? (double)dvd_height/max_h : 1,
368                         dvd_width, dvd_height);
369                 keyframe.set_data(data);
370                 insert_video_plugin("Scale", &keyframe);
371         }
372         if( use_resize_tracks )
373                 resize_tracks();
374         if( use_histogram ) {
375 #if 0
376                 sprintf(data, "<HISTOGRAM OUTPUT_MIN_0=0 OUTPUT_MAX_0=1 "
377                         "OUTPUT_MIN_1=0 OUTPUT_MAX_1=1 "
378                         "OUTPUT_MIN_2=0 OUTPUT_MAX_2=1 "
379                         "OUTPUT_MIN_3=0 OUTPUT_MAX_3=1 "
380                         "AUTOMATIC=0 THRESHOLD=9.0-01 PLOT=0 SPLIT=0>"
381                         "<POINTS></POINTS><POINTS></POINTS><POINTS></POINTS>"
382                         "<POINTS><POINT X=6.0e-02 Y=0>"
383                                 "<POINT X=9.4e-01 Y=1></POINTS>");
384 #else
385                 sprintf(data, "<HISTOGRAM AUTOMATIC=0 THRESHOLD=1.0e-01 "
386                         "PLOT=0 SPLIT=0 W=440 H=500 PARADE=0 MODE=3 "
387                         "LOW_OUTPUT_0=0 HIGH_OUTPUT_0=1 LOW_INPUT_0=0 HIGH_INPUT_0=1 GAMMA_0=1 "
388                         "LOW_OUTPUT_1=0 HIGH_OUTPUT_1=1 LOW_INPUT_1=0 HIGH_INPUT_1=1 GAMMA_1=1 "
389                         "LOW_OUTPUT_2=0 HIGH_OUTPUT_2=1 LOW_INPUT_2=0 HIGH_INPUT_2=1 GAMMA_2=1 "
390                         "LOW_OUTPUT_3=0 HIGH_OUTPUT_3=1 LOW_INPUT_3=0.044 HIGH_INPUT_3=0.956 "
391                         "GAMMA_3=1>");
392 #endif
393                 keyframe.set_data(data);
394                 insert_video_plugin("Histogram", &keyframe);
395         }
396         mwindow->batch_render->reset();
397         create_dvd_jobs(&mwindow->batch_render->jobs, tmp_path, asset_title);
398         mwindow->save_backup();
399         mwindow->undo->update_undo_after(_("create dvd"), LOAD_ALL);
400         mwindow->resync_guis();
401         mwindow->batch_render->handle_close_event(0);
402         mwindow->batch_render->start();
403 }
404
405 BC_Window* CreateDVD_Thread::new_gui()
406 {
407         memset(tmp_path,0,sizeof(tmp_path));
408         strcpy(tmp_path,"/tmp");
409         memset(asset_title,0,sizeof(asset_title));
410         time_t dt;  time(&dt);
411         struct tm dtm;  localtime_r(&dt, &dtm);
412         sprintf(asset_title, "dvd_%02d%02d%02d-%02d%02d%02d",
413                 dtm.tm_year+1900, dtm.tm_mon+1, dtm.tm_mday,
414                 dtm.tm_hour, dtm.tm_min, dtm.tm_sec);
415         use_deinterlace = 0;
416         use_scale = 0;
417         use_histogram = 0;
418         use_inverse_telecine = 0;
419         use_wide_audio = 0;
420         use_wide_aspect = 0;
421         use_ffmpeg = 0;
422         use_resize_tracks = 0;
423         use_label_chapters = 0;
424         use_standard = HD_720x480_2997;
425
426         dvd_size = DVD_SIZE;
427         dvd_width = DVD_WIDTH;
428         dvd_height = DVD_HEIGHT;
429         dvd_aspect_width = DVD_ASPECT_WIDTH;
430         dvd_aspect_height = DVD_ASPECT_HEIGHT;
431         dvd_framerate = DVD_FRAMERATE;
432         dvd_samplerate = DVD_SAMPLERATE;
433         dvd_max_bitrate = DVD_MAX_BITRATE;
434         dvd_kaudio_rate = DVD_KAUDIO_RATE;
435         max_w = 0; max_h = 0;
436
437         int has_standard = -1;
438         if( mwindow->edl ) {
439                 EDLSession *session = mwindow->edl->session;
440 // match the session to any known standard
441                 for( int i=0; i<(int)(sizeof(hd_formats)/sizeof(hd_formats[0])); ++i ) {
442                         if( !EQUIV(session->frame_rate, hd_formats[i].framerate) ) continue;
443                         if( session->output_w != hd_formats[i].w ) continue;
444                         if( session->output_h != hd_formats[i].h ) continue;
445                         has_standard = i;  break;
446                 }
447                 if( has_standard < 0 ) {
448 // or use the default standard
449                         if( !strcmp(mwindow->default_standard, "NTSC") ) has_standard = HD_720x480_2997;
450                         else if( !strcmp(mwindow->default_standard, "PAL") ) has_standard = HD_720x576_2500;
451                 }
452         }
453         use_standard = has_standard >= 0 ? has_standard : HD_720x480_2997;
454
455         option_presets();
456         int scr_x = mwindow->gui->get_screen_x(0, -1);
457         int scr_w = mwindow->gui->get_screen_w(0, -1);
458         int scr_h = mwindow->gui->get_screen_h(0, -1);
459         int w = 500, h = 280;
460         int x = scr_x + scr_w/2 - w/2, y = scr_h/2 - h/2;
461
462         gui = new CreateDVD_GUI(this, x, y, w, h);
463         gui->create_objects();
464         return gui;
465 }
466
467
468 CreateDVD_OK::CreateDVD_OK(CreateDVD_GUI *gui, int x, int y)
469  : BC_OKButton(x, y)
470 {
471         this->gui = gui;
472         set_tooltip(_("end setup, start batch render"));
473 }
474
475 CreateDVD_OK::~CreateDVD_OK()
476 {
477 }
478
479 int CreateDVD_OK::button_press_event()
480 {
481         if(get_buttonpress() == 1 && is_event_win() && cursor_inside()) {
482                 gui->set_done(0);
483                 return 1;
484         }
485         return 0;
486 }
487
488 int CreateDVD_OK::keypress_event()
489 {
490         return 0;
491 }
492
493
494 CreateDVD_Cancel::CreateDVD_Cancel(CreateDVD_GUI *gui, int x, int y)
495  : BC_CancelButton(x, y)
496 {
497         this->gui = gui;
498 }
499
500 CreateDVD_Cancel::~CreateDVD_Cancel()
501 {
502 }
503
504 int CreateDVD_Cancel::button_press_event()
505 {
506         if(get_buttonpress() == 1 && is_event_win() && cursor_inside()) {
507                 gui->set_done(1);
508                 return 1;
509         }
510         return 0;
511 }
512
513
514 CreateDVD_DiskSpace::CreateDVD_DiskSpace(CreateDVD_GUI *gui, int x, int y)
515  : BC_Title(x, y, "", MEDIUMFONT, GREEN)
516 {
517         this->gui = gui;
518 }
519
520 CreateDVD_DiskSpace::~CreateDVD_DiskSpace()
521 {
522 }
523
524 int64_t CreateDVD_DiskSpace::tmp_path_space()
525 {
526         const char *path = gui->tmp_path->get_text();
527         if( access(path,R_OK+W_OK) ) return 0;
528         struct statfs sfs;
529         if( statfs(path, &sfs) ) return 0;
530         return (int64_t)sfs.f_bsize * sfs.f_bfree;
531 }
532
533 void CreateDVD_DiskSpace::update()
534 {
535         static const char *suffix[] = { "", "KB", "MB", "GB", "TB", "PB" };
536         int64_t disk_space = tmp_path_space();
537         double media_size = 15e9, msz = 0, m = 1;
538         char sfx[BCSTRLEN];
539         if( sscanf(gui->media_size->get_text(), "%lf%s", &msz, sfx) == 2 ) {
540                 int i = sizeof(suffix)/sizeof(suffix[0]);
541                 while( --i >= 0 && strcmp(sfx, suffix[i]) );
542                 while( --i >= 0 ) m *= 1000;
543                 media_size = msz * m;
544         }
545         m = gui->thread->use_ffmpeg ? 2 : 3;
546         int color = disk_space < media_size*m ? RED : GREEN;
547         int i = 0;
548         for( int64_t space=disk_space; i<5 && (space/=1000)>0; disk_space=space, ++i );
549         char text[BCTEXTLEN];
550         sprintf(text, "%s%3jd%s", _("disk space: "), disk_space, suffix[i]);
551         gui->disk_space->BC_Title::update(text);
552         gui->disk_space->set_color(color);
553 }
554
555 CreateDVD_TmpPath::CreateDVD_TmpPath(CreateDVD_GUI *gui, int x, int y, int w)
556  : BC_TextBox(x, y, w, 1, -(int)sizeof(gui->thread->tmp_path),
557                 gui->thread->tmp_path, 1, MEDIUMFONT)
558 {
559         this->gui = gui;
560 }
561
562 CreateDVD_TmpPath::~CreateDVD_TmpPath()
563 {
564 }
565
566 int CreateDVD_TmpPath::handle_event()
567 {
568         gui->disk_space->update();
569         return 1;
570 }
571
572
573 CreateDVD_AssetTitle::CreateDVD_AssetTitle(CreateDVD_GUI *gui, int x, int y, int w)
574  : BC_TextBox(x, y, w, 1, 0, gui->thread->asset_title, 1, MEDIUMFONT)
575 {
576         this->gui = gui;
577 }
578
579 CreateDVD_AssetTitle::~CreateDVD_AssetTitle()
580 {
581 }
582
583
584 CreateDVD_Deinterlace::CreateDVD_Deinterlace(CreateDVD_GUI *gui, int x, int y)
585  : BC_CheckBox(x, y, &gui->thread->use_deinterlace, _("Deinterlace"))
586 {
587         this->gui = gui;
588 }
589
590 CreateDVD_Deinterlace::~CreateDVD_Deinterlace()
591 {
592 }
593
594 int CreateDVD_Deinterlace::handle_event()
595 {
596         if( get_value() ) {
597                 gui->need_inverse_telecine->set_value(0);
598                 gui->thread->use_inverse_telecine = 0;
599         }
600         return BC_CheckBox::handle_event();
601 }
602
603
604 CreateDVD_InverseTelecine::CreateDVD_InverseTelecine(CreateDVD_GUI *gui, int x, int y)
605  : BC_CheckBox(x, y, &gui->thread->use_inverse_telecine, _("Inverse Telecine"))
606 {
607         this->gui = gui;
608 }
609
610 CreateDVD_InverseTelecine::~CreateDVD_InverseTelecine()
611 {
612 }
613
614 int CreateDVD_InverseTelecine::handle_event()
615 {
616         if( get_value() ) {
617                 gui->need_deinterlace->set_value(0);
618                 gui->thread->use_deinterlace = 0;
619         }
620         return BC_CheckBox::handle_event();
621 }
622
623
624 CreateDVD_Scale::CreateDVD_Scale(CreateDVD_GUI *gui, int x, int y)
625  : BC_CheckBox(x, y, &gui->thread->use_scale, _("Scale"))
626 {
627         this->gui = gui;
628 }
629
630 CreateDVD_Scale::~CreateDVD_Scale()
631 {
632 }
633
634
635 CreateDVD_ResizeTracks::CreateDVD_ResizeTracks(CreateDVD_GUI *gui, int x, int y)
636  : BC_CheckBox(x, y, &gui->thread->use_resize_tracks, _("Resize Tracks"))
637 {
638         this->gui = gui;
639 }
640
641 CreateDVD_ResizeTracks::~CreateDVD_ResizeTracks()
642 {
643 }
644
645
646 CreateDVD_Histogram::CreateDVD_Histogram(CreateDVD_GUI *gui, int x, int y)
647  : BC_CheckBox(x, y, &gui->thread->use_histogram, _("Histogram"))
648 {
649         this->gui = gui;
650 }
651
652 CreateDVD_Histogram::~CreateDVD_Histogram()
653 {
654 }
655
656 CreateDVD_LabelChapters::CreateDVD_LabelChapters(CreateDVD_GUI *gui, int x, int y)
657  : BC_CheckBox(x, y, &gui->thread->use_label_chapters, _("Chapters at Labels"))
658 {
659         this->gui = gui;
660 }
661
662 CreateDVD_LabelChapters::~CreateDVD_LabelChapters()
663 {
664 }
665
666 CreateDVD_WideAudio::CreateDVD_WideAudio(CreateDVD_GUI *gui, int x, int y)
667  : BC_CheckBox(x, y, &gui->thread->use_wide_audio, _("Audio 5.1"))
668 {
669         this->gui = gui;
670 }
671
672 CreateDVD_WideAudio::~CreateDVD_WideAudio()
673 {
674 }
675
676 CreateDVD_WideAspect::CreateDVD_WideAspect(CreateDVD_GUI *gui, int x, int y)
677  : BC_CheckBox(x, y, &gui->thread->use_wide_aspect, _("Aspect 16x9"))
678 {
679         this->gui = gui;
680 }
681
682 CreateDVD_WideAspect::~CreateDVD_WideAspect()
683 {
684 }
685
686 CreateDVD_UseFFMpeg::CreateDVD_UseFFMpeg(CreateDVD_GUI *gui, int x, int y)
687  : BC_CheckBox(x, y, &gui->thread->use_ffmpeg, _("Use FFMPEG"))
688 {
689         this->gui = gui;
690 }
691
692 CreateDVD_UseFFMpeg::~CreateDVD_UseFFMpeg()
693 {
694 }
695
696
697
698
699 CreateDVD_GUI::CreateDVD_GUI(CreateDVD_Thread *thread, int x, int y, int w, int h)
700  : BC_Window(_(PROGRAM_NAME ": Create DVD"), x, y, w, h, 50, 50, 1, 0, 1)
701 {
702         this->thread = thread;
703         at_x = at_y = tmp_x = tmp_y = 0;
704         ok_x = ok_y = ok_w = ok_h = 0;
705         cancel_x = cancel_y = cancel_w = cancel_h = 0;
706         asset_title = 0;
707         tmp_path = 0;
708         disk_space = 0;
709         need_deinterlace = 0;
710         need_inverse_telecine = 0;
711         need_scale = 0;
712         need_resize_tracks = 0;
713         need_histogram = 0;
714         need_wide_audio = 0;
715         need_wide_aspect = 0;
716         need_label_chapters = 0;
717         ok = 0;
718         cancel = 0;
719 }
720
721 CreateDVD_GUI::~CreateDVD_GUI()
722 {
723 }
724
725 void CreateDVD_GUI::create_objects()
726 {
727         lock_window("CreateDVD_GUI::create_objects");
728         int pady = BC_TextBox::calculate_h(this, MEDIUMFONT, 0, 1) + 5;
729         int padx = BC_Title::calculate_w(this, (char*)"X", MEDIUMFONT);
730         int x = padx/2, y = pady/2;
731         BC_Title *title = new BC_Title(x, y, _("Title:"), MEDIUMFONT, YELLOW);
732         add_subwindow(title);
733         at_x = x + title->get_w();  at_y = y;
734         asset_title = new CreateDVD_AssetTitle(this, at_x, at_y, get_w()-at_x-10);
735         add_subwindow(asset_title);
736         y += title->get_h() + pady/2;
737         title = new BC_Title(x, y, _("tmp path:"), MEDIUMFONT, YELLOW);
738         add_subwindow(title);
739         tmp_x = x + title->get_w();  tmp_y = y;
740         tmp_path = new CreateDVD_TmpPath(this, tmp_x, tmp_y,  get_w()-tmp_x-10);
741         add_subwindow(tmp_path);
742         y += title->get_h() + pady/2;
743         disk_space = new CreateDVD_DiskSpace(this, x, y);
744         add_subwindow(disk_space);
745         int x0 = get_w() - 170;
746         title = new BC_Title(x0, y, _("Media:"), MEDIUMFONT, YELLOW);
747         add_subwindow(title);
748         x0 +=  title->get_w() + padx;
749         media_size = new CreateDVD_MediaSize(this, x0, y);
750         media_size->create_objects();
751         media_sizes.append(new BC_ListBoxItem("4.7GB"));
752         media_sizes.append(new BC_ListBoxItem("8.3GB"));
753         media_size->update_list(&media_sizes);
754         media_size->update(media_sizes[0]->get_text());
755         disk_space->update();
756         x0 = x;
757         y += disk_space->get_h() + pady/2;
758         title = new BC_Title(x0, y, _("Format:"), MEDIUMFONT, YELLOW);
759         add_subwindow(title);
760         x0 +=  title->get_w() + padx;
761         standard = new CreateDVD_Format(this, x0, y);
762         add_subwindow(standard);
763         standard->create_objects();
764         y += standard->get_h() + pady/2;
765         need_deinterlace = new CreateDVD_Deinterlace(this, x, y);
766         add_subwindow(need_deinterlace);
767         int x1 = x + 150, x2 = x1 + 150;
768         need_inverse_telecine = new CreateDVD_InverseTelecine(this, x1, y);
769         add_subwindow(need_inverse_telecine);
770         need_use_ffmpeg = new CreateDVD_UseFFMpeg(this, x2, y);
771         add_subwindow(need_use_ffmpeg);
772         y += need_deinterlace->get_h() + pady/2;
773         need_scale = new CreateDVD_Scale(this, x, y);
774         add_subwindow(need_scale);
775         need_wide_audio = new CreateDVD_WideAudio(this, x1, y);
776         add_subwindow(need_wide_audio);
777         need_resize_tracks = new CreateDVD_ResizeTracks(this, x2, y);
778         add_subwindow(need_resize_tracks);
779         y += need_scale->get_h() + pady/2;
780         need_histogram = new CreateDVD_Histogram(this, x, y);
781         add_subwindow(need_histogram);
782         need_wide_aspect = new CreateDVD_WideAspect(this, x1, y);
783         add_subwindow(need_wide_aspect);
784         need_label_chapters = new CreateDVD_LabelChapters(this, x2, y);
785         add_subwindow(need_label_chapters);
786         ok_w = BC_OKButton::calculate_w();
787         ok_h = BC_OKButton::calculate_h();
788         ok_x = 10;
789         ok_y = get_h() - ok_h - 10;
790         ok = new CreateDVD_OK(this, ok_x, ok_y);
791         add_subwindow(ok);
792         cancel_w = BC_CancelButton::calculate_w();
793         cancel_h = BC_CancelButton::calculate_h();
794         cancel_x = get_w() - cancel_w - 10,
795         cancel_y = get_h() - cancel_h - 10;
796         cancel = new CreateDVD_Cancel(this, cancel_x, cancel_y);
797         add_subwindow(cancel);
798         show_window();
799         unlock_window();
800 }
801
802 int CreateDVD_GUI::resize_event(int w, int h)
803 {
804         asset_title->reposition_window(at_x, at_y, get_w()-at_x-10);
805         tmp_path->reposition_window(tmp_x, tmp_y,  get_w()-tmp_x-10);
806         ok_y = h - ok_h - 10;
807         ok->reposition_window(ok_x, ok_y);
808         cancel_x = w - cancel_w - 10,
809         cancel_y = h - cancel_h - 10;
810         cancel->reposition_window(cancel_x, cancel_y);
811         return 0;
812 }
813
814 int CreateDVD_GUI::translation_event()
815 {
816         return 1;
817 }
818
819 int CreateDVD_GUI::close_event()
820 {
821         set_done(1);
822         return 1;
823 }
824
825 void CreateDVD_GUI::update()
826 {
827         need_deinterlace->set_value(thread->use_deinterlace);
828         need_inverse_telecine->set_value(thread->use_inverse_telecine);
829         need_scale->set_value(thread->use_scale);
830         need_use_ffmpeg->set_value(thread->use_ffmpeg);
831         need_resize_tracks->set_value(thread->use_resize_tracks);
832         need_histogram->set_value(thread->use_histogram);
833         need_wide_audio->set_value(thread->use_wide_audio);
834         need_wide_aspect->set_value(thread->use_wide_aspect);
835         need_label_chapters->set_value(thread->use_label_chapters);
836 }
837
838 int CreateDVD_Thread::
839 insert_video_plugin(const char *title, KeyFrame *default_keyframe)
840 {
841         Tracks *tracks = mwindow->edl->tracks;
842         for( Track *vtrk=tracks->first; vtrk; vtrk=vtrk->next ) {
843                 if( vtrk->data_type != TRACK_VIDEO ) continue;
844                 if( !vtrk->record ) continue;
845                 vtrk->expand_view = 1;
846                 PluginSet *plugin_set = new PluginSet(mwindow->edl, vtrk);
847                 vtrk->plugin_set.append(plugin_set);
848                 Edits *edits = vtrk->edits;
849                 for( Edit *edit=edits->first; edit; edit=edit->next ) {
850                         plugin_set->insert_plugin(_(title),
851                                 edit->startproject, edit->length,
852                                 PLUGIN_STANDALONE, 0, default_keyframe, 0);
853                 }
854                 vtrk->optimize();
855         }
856         return 0;
857 }
858
859 int CreateDVD_Thread::
860 resize_tracks()
861 {
862         Tracks *tracks = mwindow->edl->tracks;
863         int trk_w = max_w, trk_h = max_h;
864         if( trk_w < dvd_width ) trk_w = dvd_width;
865         if( trk_h < dvd_height ) trk_h = dvd_height;
866         for( Track *vtrk=tracks->first; vtrk; vtrk=vtrk->next ) {
867                 if( vtrk->data_type != TRACK_VIDEO ) continue;
868                 if( !vtrk->record ) continue;
869                 vtrk->track_w = trk_w;
870                 vtrk->track_h = trk_h;
871         }
872         return 0;
873 }
874
875 int CreateDVD_Thread::
876 option_presets()
877 {
878 // reset only probed options
879         use_deinterlace = 0;
880         use_scale = 0;
881         use_resize_tracks = 0;
882         use_wide_audio = 0;
883         use_wide_aspect = 0;
884         use_label_chapters = 0;
885
886         if( !mwindow->edl ) return 1;
887
888         dvd_width = hd_formats[use_standard].w;
889         dvd_height = hd_formats[use_standard].h;
890         dvd_framerate = hd_formats[use_standard].framerate;
891
892         Tracks *tracks = mwindow->edl->tracks;
893         max_w = 0;  max_h = 0;
894         int has_deinterlace = 0, has_scale = 0;
895         for( Track *trk=tracks->first; trk; trk=trk->next ) {
896                 if( !trk->record ) continue;
897                 Edits *edits = trk->edits;
898                 switch( trk->data_type ) {
899                 case TRACK_VIDEO:
900                         for( Edit *edit=edits->first; edit; edit=edit->next ) {
901                                 if( edit->silence() ) continue;
902                                 Indexable *indexable = edit->get_source();
903                                 int w = indexable->get_w();
904                                 if( w > max_w ) max_w = w;
905                                 if( w != dvd_width ) use_scale = 1;
906                                 int h = indexable->get_h();
907                                 if( h > max_h ) max_h = h;
908                                 if( h != dvd_height ) use_scale = 1;
909                         }
910                         for( int i=0; i<trk->plugin_set.size(); ++i ) {
911                                 for(Plugin *plugin = (Plugin*)trk->plugin_set[i]->first;
912                                                 plugin;
913                                                 plugin = (Plugin*)plugin->next) {
914                                         if( !strcmp(plugin->title, _("Deinterlace")) )
915                                                 has_deinterlace = 1;
916                                         if( !strcmp(plugin->title, _("Auto Scale")) ||
917                                             !strcmp(plugin->title, _("Scale")) )
918                                                 has_scale = 1;
919                                 }
920                         }
921                         break;
922                 }
923         }
924         if( has_scale )
925                 use_scale = 0;
926         if( use_scale ) {
927                 if( max_w != dvd_width ) use_resize_tracks = 1;
928                 if( max_h != dvd_height ) use_resize_tracks = 1;
929         }
930         for( Track *trk=tracks->first; trk && !use_resize_tracks; trk=trk->next ) {
931                 if( !trk->record ) continue;
932                 switch( trk->data_type ) {
933                 case TRACK_VIDEO:
934                         if( trk->track_w != max_w ) use_resize_tracks = 1;
935                         if( trk->track_h != max_h ) use_resize_tracks = 1;
936                         break;
937                 }
938         }
939         if( !has_deinterlace && max_h > 2*dvd_height ) use_deinterlace = 1;
940         Labels *labels = mwindow->edl->labels;
941         use_label_chapters = labels && labels->first ? 1 : 0;
942
943         float aw, ah;
944         MWindow::create_aspect_ratio(aw, ah, max_w, max_h);
945         if( aw == DVD_WIDE_ASPECT_WIDTH && ah == DVD_WIDE_ASPECT_HEIGHT )
946                 use_wide_aspect = 1;
947         dvd_aspect_width = use_wide_aspect ? DVD_WIDE_ASPECT_WIDTH : DVD_ASPECT_WIDTH;
948         dvd_aspect_height = use_wide_aspect ? DVD_WIDE_ASPECT_HEIGHT : DVD_ASPECT_HEIGHT;
949
950         if( tracks->recordable_audio_tracks() == DVD_WIDE_CHANNELS )
951                 use_wide_audio = 1;
952
953         return 0;
954 }
955
956
957
958 CreateDVD_FormatItem::CreateDVD_FormatItem(CreateDVD_Format *popup,
959                 int standard, const char *name)
960  : BC_MenuItem(name)
961 {
962         this->popup = popup;
963         this->standard = standard;
964 }
965
966 CreateDVD_FormatItem::~CreateDVD_FormatItem()
967 {
968 }
969
970 int CreateDVD_FormatItem::handle_event()
971 {
972         popup->set_text(get_text());
973         popup->gui->thread->use_standard = standard;
974         return popup->handle_event();
975 }
976
977
978 CreateDVD_Format::CreateDVD_Format(CreateDVD_GUI *gui, int x, int y)
979  : BC_PopupMenu(x, y, 180, hd_formats[gui->thread->use_standard].name, 1)
980 {
981         this->gui = gui;
982 }
983
984 CreateDVD_Format::~CreateDVD_Format()
985 {
986 }
987
988 void CreateDVD_Format::create_objects()
989 {
990         for( int i=0; i<(int)(sizeof(hd_formats)/sizeof(hd_formats[0])); ++i ) {
991                 add_item(new CreateDVD_FormatItem(this, i, hd_formats[i].name));
992         }
993 }
994
995 int CreateDVD_Format::handle_event()
996 {
997         gui->thread->option_presets();
998         gui->update();
999         return 1;
1000 }
1001
1002 CreateDVD_MediaSize::CreateDVD_MediaSize(CreateDVD_GUI *gui, int x, int y)
1003  : BC_PopupTextBox(gui, 0, 0, x, y, 70,50)
1004 {
1005         this->gui = gui;
1006 }
1007
1008 CreateDVD_MediaSize::~CreateDVD_MediaSize()
1009 {
1010 }
1011
1012 int CreateDVD_MediaSize::handle_event()
1013 {
1014         gui->disk_space->update();
1015         return 1;
1016 }
1017