4 * Copyright (C) 2010-2013 Adam Williams <broadcast at earthling dot net>
5 * Copyright (C) 2003-2016 Cinelerra CV contributors
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "bcsignals.h"
28 #include "filesystem.h"
29 #include "formattools.h"
35 #include "maxchannels.h"
37 #include "preferences.h"
39 #include "videodevice.inc"
45 FormatTools::FormatTools(MWindow *mwindow,
46 BC_WindowBase *window,
49 this->mwindow = mwindow;
50 this->window = window;
75 prompt_audio_channels = 0;
77 prompt_video_compression = 0;
79 locked_compressor = 0;
83 FormatTools::~FormatTools()
94 if(aparams_button) delete aparams_button;
96 if(vparams_button) delete vparams_button;
98 if(aparams_thread) delete aparams_thread;
100 if(vparams_thread) delete vparams_thread;
104 void FormatTools::create_objects(
105 int &init_x, int &init_y,
106 int do_audio, int do_video, // Include support for audio, video
107 int prompt_audio, int prompt_video, // Include checkbox for audio, video
108 int prompt_audio_channels,
109 int prompt_video_compression,
110 const char *locked_compressor,
114 int horizontal_layout)
120 int margin = mwindow->theme->widget_border;
122 this->locked_compressor = locked_compressor;
123 this->recording = recording;
124 this->use_brender = brender;
125 this->do_audio = do_audio;
126 this->do_video = do_video;
127 this->prompt_audio = prompt_audio;
128 this->prompt_audio_channels = prompt_audio_channels;
129 this->prompt_video = prompt_video;
130 this->prompt_video_compression = prompt_video_compression;
131 this->file_per_label = file_per_label;
134 if(asset->format == FILE_UNKNOWN)
135 asset->format = FILE_FFMPEG;
136 //printf("FormatTools::create_objects 1\n");
141 window->add_subwindow(path_textbox = new FormatPathText(px, y, this));
142 path_textbox->context_help_set_keyword("File Format section");
143 px += path_textbox->get_w() + 5;
144 path_recent = new BC_RecentList("PATH", mwindow->defaults,
145 path_textbox, 10, px, y, xS(300), yS(100));
146 window->add_subwindow(path_recent);
147 path_recent->load_items(File::formattostr(asset->format));
148 path_recent->context_help_set_keyword("File Format section");
149 px += path_recent->get_w();
150 window->add_subwindow(path_button = new BrowseButton(
151 mwindow->theme, window, path_textbox, px, y, asset->path,
152 _("Output to file"), _("Select a file to write to:"), 0));
153 path_button->context_help_set_keyword("File Format section");
157 y += path_textbox->get_h() + ys10;
166 window->add_subwindow(format_title = new BC_Title(x, y, _("File Format:")));
167 format_title->context_help_set_keyword("File Format section");
168 x += format_title->get_w() + margin;
169 window->add_subwindow(format_text = new BC_TextBox(x, y, xS(160), 1,
170 File::formattostr(asset->format)));
171 format_text->context_help_set_keyword("File Format section");
172 x += format_text->get_w() + margin;
173 //printf("FormatTools::create_objects %d %p\n", __LINE__, window);
174 window->add_subwindow(format_button = new FormatFormat(x, y, this));
175 format_button->create_objects();
176 format_button->context_help_set_keyword("File Format section");
177 x += format_button->get_w() + 5;
178 window->add_subwindow(ffmpeg_type = new FFMpegType(x, y, xS(70), 1, asset->fformat));
179 FFMPEG::set_asset_format(asset, mwindow->edl, asset->fformat);
180 ffmpeg_type->context_help_set_keyword("File Format section");
181 x += ffmpeg_type->get_w();
182 window->add_subwindow(format_ffmpeg = new FormatFFMPEG(x, y, this));
183 format_ffmpeg->create_objects();
184 format_ffmpeg->context_help_set_keyword("File Format section");
186 y += format_button->get_h() + ys10;
188 window->add_subwindow(audio_title = new BC_Title(x, y, _("Audio:"), LARGEFONT,
189 BC_WindowBase::get_resources()->audiovideo_color));
190 audio_title->context_help_set_keyword("File Format section");
191 x += audio_title->get_w() + margin;
192 window->add_subwindow(aparams_button = new FormatAParams(mwindow, this, x, y));
193 aparams_button->context_help_set_keyword("File Format section");
194 x += aparams_button->get_w() + margin;
196 window->add_subwindow(audio_switch = new FormatAudio(x, y, this, asset->audio_data));
197 audio_switch->context_help_set_keyword("File Format section");
201 y += aparams_button->get_h() + ys10;
203 //printf("FormatTools::create_objects 6\n");
204 aparams_thread = new FormatAThread(this);
207 //printf("FormatTools::create_objects 7\n");
209 if( horizontal_layout && do_audio ) {
214 //printf("FormatTools::create_objects 8\n");
215 window->add_subwindow(video_title = new BC_Title(x, y, _("Video:"), LARGEFONT,
216 BC_WindowBase::get_resources()->audiovideo_color));
217 video_title->context_help_set_keyword("File Format section");
218 x += video_title->get_w() + margin;
219 if(prompt_video_compression) {
220 window->add_subwindow(vparams_button = new FormatVParams(mwindow, this, x, y));
221 vparams_button->context_help_set_keyword("File Format section");
222 x += vparams_button->get_w() + margin;
225 //printf("FormatTools::create_objects 9\n");
227 window->add_subwindow(video_switch = new FormatVideo(x, y, this, asset->video_data));
228 video_switch->context_help_set_keyword("File Format section");
229 y += video_switch->get_h();
232 y += vparams_button->get_h();
235 //printf("FormatTools::create_objects 10\n");
237 vparams_thread = new FormatVThread(this);
240 //printf("FormatTools::create_objects 11\n");
243 if( file_per_label ) {
244 labeled_files = new FormatFilePerLabel(this, x, y, file_per_label);
245 window->add_subwindow(labeled_files);
246 labeled_files->context_help_set_keyword("File Format section");
247 y += labeled_files->get_h() + ys10;
250 //printf("FormatTools::create_objects 12\n");
256 void FormatTools::update_driver(int driver)
258 this->video_driver = driver;
260 locked_compressor = 0;
264 case VIDEO4LINUX2MPEG:
265 // Just give the user information about how the stream is going to be
266 // stored but don't change the asset.
267 // Want to be able to revert to user settings.
268 if(asset->format == FILE_MPEG) break;
269 asset->format = FILE_MPEG;
270 format_text->update(File::formattostr(asset->format));
271 asset->audio_data = 1;
272 asset->video_data = 1;
273 audio_switch->update(1);
274 video_switch->update(1);
277 case CAPTURE_IEC61883:
278 case CAPTURE_FIREWIRE:
279 case VIDEO4LINUX2JPEG:
280 case CAPTURE_JPEG_WEBCAM:
281 asset->format = FILE_FFMPEG;
282 format_text->update(File::formattostr(asset->format));
286 case CAPTURE_IEC61883:
287 case CAPTURE_FIREWIRE:
288 locked_compressor = (char*)CODEC_TAG_DVSD;
291 case VIDEO4LINUX2JPEG:
292 locked_compressor = (char*)CODEC_TAG_MJPEG;
295 case CAPTURE_JPEG_WEBCAM:
296 locked_compressor = (char*)CODEC_TAG_JPEG;
299 if( locked_compressor )
300 strcpy(asset->vcodec, locked_compressor);
302 audio_switch->update(asset->audio_data);
303 video_switch->update(asset->video_data);
307 format_text->update(File::formattostr(asset->format));
308 audio_switch->update(asset->audio_data);
309 video_switch->update(asset->video_data);
312 close_format_windows();
316 void FormatTools::update_format()
318 if( do_audio && prompt_audio && audio_switch ) {
319 audio_switch->update(asset->audio_data);
320 if( File::renders_audio(asset) )
321 audio_switch->enable();
323 audio_switch->disable();
325 if( do_video && prompt_video && video_switch ) {
326 video_switch->update(asset->video_data);
327 if( File::renders_video(asset) )
328 video_switch->enable();
330 video_switch->disable();
332 if( asset->format == FILE_FFMPEG ) {
334 format_ffmpeg->show();
338 format_ffmpeg->hide();
342 int FormatTools::handle_event()
347 Asset* FormatTools::get_asset()
352 void FormatTools::update_extension()
354 const char *extension = File::get_tag(asset->format);
355 // split multiple extensions
356 ArrayList<const char*> extensions;
357 int len = !extension ? -1 : strlen(extension);
358 const char *extension_ptr = extension;
359 for(int i = 0; i <= len; i++)
361 if(extension[i] == '/' || extension[i] == 0)
363 extensions.append(extension_ptr);
364 extension_ptr = extension + i + 1;
368 if(extensions.size())
370 char *ptr = strrchr(asset->path, '.');
373 ptr = asset->path + strlen(asset->path);
378 // test for equivalent extension
379 int need_extension = 1;
380 //int extension_len = 0;
381 for(int i = 0; i < extensions.size() && need_extension; i++)
384 extension_ptr = extensions.get(i);
387 while(*ptr1 != 0 && *extension_ptr != 0 && *extension_ptr != '/')
389 if(tolower(*ptr1) != tolower(*extension_ptr))
398 if( (!*ptr1 && (*extension_ptr && *extension_ptr != '/')) ||
399 (*ptr1 && (!*extension_ptr || *extension_ptr == '/')) )
403 //printf("FormatTools::update_extension %d %d\n", __LINE__, need_extension);
408 // change "qt" to "mov" since ffmpeg does not know qt
409 extension_ptr = asset->format != FILE_FFMPEG ? extensions.get(0) :
410 !strcmp(asset->fformat, "qt" ) ||
411 !strcmp(asset->fformat, "pro" ) ? "mov" : asset->fformat ;
412 while(*extension_ptr != 0 && *extension_ptr != '/')
413 *ptr1++ = *extension_ptr++;
417 int character1 = ptr - asset->path;
418 int character2 = strlen(asset->path);
419 // *(asset->path + character2) = 0;
422 path_textbox->update(asset->path);
423 path_textbox->set_selection(character1, character2, character2);
428 void FormatTools::update(Asset *asset, int *file_per_label)
431 this->file_per_label = file_per_label;
432 if( file_per_label ) labeled_files->update(file_per_label);
433 if( path_textbox ) path_textbox->update(asset->path);
434 format_text->update(File::formattostr(asset->format));
436 close_format_windows();
439 void FormatTools::close_format_windows()
441 // This is done in ~file
442 if( aparams_thread ) {
443 if( aparams_thread->running() )
444 aparams_thread->file->close_window();
445 aparams_thread->join();
447 if( vparams_thread ) {
448 if( vparams_thread->running() )
449 vparams_thread->file->close_window();
450 vparams_thread->join();
454 int FormatTools::get_w()
456 return asset->format != FILE_FFMPEG ? w :
457 format_ffmpeg->get_x() + format_ffmpeg->get_w();
460 void FormatTools::set_w(int w)
465 void FormatTools::reposition_window(int &init_x, int &init_y)
467 int xs10 = xS(10), xs80 = xS(80);
475 path_textbox->reposition_window(px, y);
476 px += path_textbox->get_w() + xS(5);
477 path_recent->reposition_window(px, y);
478 px += path_recent->get_w() + xS(8);
479 path_button->reposition_window(px, y);
480 y += path_textbox->get_h() + ys10;
483 format_title->reposition_window(x, y);
485 format_text->reposition_window(x, y);
486 x += format_text->get_w();
487 format_button->reposition_window(x, y);
488 x += format_button->get_w() + 5;
489 ffmpeg_type->reposition_window(x, y);
490 x += ffmpeg_type->get_w();
491 format_ffmpeg->reposition_window(x, y);
494 y += format_button->get_h() + ys10;
498 audio_title->reposition_window(x, y);
500 aparams_button->reposition_window(x, y);
501 x += aparams_button->get_w() + xs10;
502 if(prompt_audio) audio_switch->reposition_window(x, y);
505 y += aparams_button->get_h() + ys10;
511 video_title->reposition_window(x, y);
513 if(prompt_video_compression)
515 vparams_button->reposition_window(x, y);
516 x += vparams_button->get_w() + xs10;
521 video_switch->reposition_window(x, y);
522 y += video_switch->get_h();
526 y += vparams_button->get_h();
533 if( file_per_label ) {
534 labeled_files->reposition_window(x, y);
535 y += labeled_files->get_h() + ys10;
542 int FormatTools::set_audio_options()
544 // if(video_driver == CAPTURE_DVB)
549 if(!aparams_thread->running())
551 aparams_thread->start();
555 aparams_thread->file->raise_window();
560 int FormatTools::set_video_options()
562 // if(video_driver == CAPTURE_DVB)
567 if(!vparams_thread->running())
569 vparams_thread->start();
573 vparams_thread->file->raise_window();
583 FormatAParams::FormatAParams(MWindow *mwindow, FormatTools *format, int x, int y)
584 : BC_Button(x, y, mwindow->theme->get_image_set("wrench"))
586 this->format = format;
587 set_tooltip(_("Configure audio compression"));
590 FormatAParams::~FormatAParams()
594 int FormatAParams::handle_event()
596 format->set_audio_options();
597 format->handle_event();
605 FormatVParams::FormatVParams(MWindow *mwindow, FormatTools *format, int x, int y)
606 : BC_Button(x, y, mwindow->theme->get_image_set("wrench"))
608 this->format = format;
609 set_tooltip(_("Configure video compression"));
612 FormatVParams::~FormatVParams()
616 int FormatVParams::handle_event()
618 format->set_video_options();
619 format->handle_event();
627 FormatAThread::FormatAThread(FormatTools *format)
630 this->format = format;
635 FormatAThread::~FormatAThread()
637 delete file; file = 0;
641 void FormatAThread::start()
649 void FormatAThread::run()
651 file->get_options(format, 1, 0);
657 FormatVThread::FormatVThread(FormatTools *format)
660 this->format = format;
665 FormatVThread::~FormatVThread()
667 delete file; file = 0;
671 void FormatVThread::start()
678 void FormatVThread::run()
680 file->get_options(format, 0, 1);
687 FormatPathText::FormatPathText(int x, int y, FormatTools *format)
688 : BC_TextBox(x, y, format->w - x -
689 2*format->mwindow->theme->get_image_set("wrench")[0]->get_w() - xS(20), 1,
692 this->format = format;
695 FormatPathText::~FormatPathText()
698 int FormatPathText::handle_event()
700 calculate_suggestions();
701 strcpy(format->asset->path, get_text());
702 format->handle_event();
709 FormatAudio::FormatAudio(int x, int y, FormatTools *format, int default_)
713 (char*)(format->recording ? _("Record audio tracks") : _("Render audio tracks")))
715 this->format = format;
718 FormatAudio::~FormatAudio() {}
719 int FormatAudio::handle_event()
721 format->asset->audio_data = get_value();
722 format->handle_event();
727 FormatVideo::FormatVideo(int x, int y, FormatTools *format, int default_)
731 (char*)(format->recording ? _("Record video tracks") : _("Render video tracks")))
733 this->format = format;
736 FormatVideo::~FormatVideo() {}
737 int FormatVideo::handle_event()
739 format->asset->video_data = get_value();
740 format->handle_event();
747 FormatFormat::FormatFormat(int x, int y, FormatTools *format)
748 : FormatPopup(x, y, format->do_audio, format->do_video, format->use_brender)
750 this->format = format;
753 FormatFormat::~FormatFormat()
757 int FormatFormat::handle_event()
759 BC_ListBoxItem *selection = get_selection(0, 0);
761 int new_format = File::strtoformat(get_selection(0, 0)->get_text());
762 // if(new_format != format->asset->format)
764 Asset *asset = format->asset;
765 asset->format = new_format;
766 asset->audio_data = File::renders_audio(asset);
767 asset->video_data = File::renders_video(asset);
768 asset->ff_audio_options[0] = 0;
769 asset->ff_video_options[0] = 0;
770 asset->ff_format_options[0] = 0;
771 format->format_text->update(selection->get_text());
772 if( !format->use_brender )
773 format->update_extension();
774 format->close_format_windows();
775 if (format->path_recent) format->path_recent->
776 load_items(File::formattostr(format->asset->format));
777 format->update_format();
779 format->handle_event();
785 FormatFFMPEG::FormatFFMPEG(int x, int y, FormatTools *format)
788 this->format = format;
791 FormatFFMPEG::~FormatFFMPEG()
795 int FormatFFMPEG::handle_event()
797 BC_ListBoxItem *selection = get_selection(0, 0);
799 const char *text = get_selection(0, 0)->get_text();
800 format->ffmpeg_type->update(text);
801 // forces options load defaults
802 format->asset->ff_audio_options[0] = 0;
803 format->asset->ff_video_options[0] = 0;
804 format->asset->ff_format_options[0] = 0;
805 FFMPEG::set_asset_format(format->asset, format->mwindow->edl, text);
806 format->update_extension();
807 format->close_format_windows();
808 format->update_format();
809 format->handle_event();
815 FormatFilePerLabel::FormatFilePerLabel(FormatTools *format,
816 int x, int y, int *output)
817 : BC_CheckBox(x, y, *output, _("Create new file at each label"))
819 this->format = format;
820 this->output = output;
823 FormatFilePerLabel::~FormatFilePerLabel()
827 int FormatFilePerLabel::handle_event()
829 *output = get_value();
830 format->handle_event();
834 void FormatFilePerLabel::update(int *output)
836 this->output = output;
837 set_value(*output ? 1 : 0);