4 * Copyright (C) 2010-2013 Adam Williams <broadcast at earthling dot net>
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.
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.
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
23 #include "bcsignals.h"
27 #include "filesystem.h"
28 #include "formattools.h"
34 #include "maxchannels.h"
36 #include "preferences.h"
38 #include "videodevice.inc"
44 FormatTools::FormatTools(MWindow *mwindow,
45 BC_WindowBase *window,
48 this->mwindow = mwindow;
49 this->window = window;
74 prompt_audio_channels = 0;
76 prompt_video_compression = 0;
78 locked_compressor = 0;
82 FormatTools::~FormatTools()
93 if(aparams_button) delete aparams_button;
95 if(vparams_button) delete vparams_button;
97 if(aparams_thread) delete aparams_thread;
99 if(vparams_thread) delete vparams_thread;
103 void FormatTools::create_objects(
104 int &init_x, int &init_y,
105 int do_audio, int do_video, // Include support for audio, video
106 int prompt_audio, int prompt_video, // Include checkbox for audio, video
107 int prompt_audio_channels,
108 int prompt_video_compression,
109 const char *locked_compressor,
113 int horizontal_layout)
119 int margin = mwindow->theme->widget_border;
121 this->locked_compressor = locked_compressor;
122 this->recording = recording;
123 this->use_brender = brender;
124 this->do_audio = do_audio;
125 this->do_video = do_video;
126 this->prompt_audio = prompt_audio;
127 this->prompt_audio_channels = prompt_audio_channels;
128 this->prompt_video = prompt_video;
129 this->prompt_video_compression = prompt_video_compression;
130 this->file_per_label = file_per_label;
133 if(asset->format == FILE_UNKNOWN)
134 asset->format = FILE_FFMPEG;
135 //printf("FormatTools::create_objects 1\n");
140 window->add_subwindow(path_textbox = new FormatPathText(px, y, this));
141 path_textbox->context_help_set_keyword("File Format section");
142 px += path_textbox->get_w() + 5;
143 path_recent = new BC_RecentList("PATH", mwindow->defaults,
144 path_textbox, 10, px, y, xS(300), yS(100));
145 window->add_subwindow(path_recent);
146 path_recent->load_items(File::formattostr(asset->format));
147 path_recent->context_help_set_keyword("File Format section");
148 px += path_recent->get_w();
149 window->add_subwindow(path_button = new BrowseButton(
150 mwindow->theme, window, path_textbox, px, y, asset->path,
151 _("Output to file"), _("Select a file to write to:"), 0));
152 path_button->context_help_set_keyword("File Format section");
156 y += path_textbox->get_h() + ys10;
165 window->add_subwindow(format_title = new BC_Title(x, y, _("File Format:")));
166 format_title->context_help_set_keyword("File Format section");
167 x += format_title->get_w() + margin;
168 window->add_subwindow(format_text = new BC_TextBox(x, y, xS(160), 1,
169 File::formattostr(asset->format)));
170 format_text->context_help_set_keyword("File Format section");
171 x += format_text->get_w() + margin;
172 //printf("FormatTools::create_objects %d %p\n", __LINE__, window);
173 window->add_subwindow(format_button = new FormatFormat(x, y, this));
174 format_button->create_objects();
175 format_button->context_help_set_keyword("File Format section");
176 x += format_button->get_w() + 5;
177 window->add_subwindow(ffmpeg_type = new FFMpegType(x, y, xS(70), 1, asset->fformat));
178 FFMPEG::set_asset_format(asset, mwindow->edl, asset->fformat);
179 ffmpeg_type->context_help_set_keyword("File Format section");
180 x += ffmpeg_type->get_w();
181 window->add_subwindow(format_ffmpeg = new FormatFFMPEG(x, y, this));
182 format_ffmpeg->create_objects();
183 format_ffmpeg->context_help_set_keyword("File Format section");
185 y += format_button->get_h() + ys10;
187 window->add_subwindow(audio_title = new BC_Title(x, y, _("Audio:"), LARGEFONT,
188 BC_WindowBase::get_resources()->audiovideo_color));
189 audio_title->context_help_set_keyword("File Format section");
190 x += audio_title->get_w() + margin;
191 window->add_subwindow(aparams_button = new FormatAParams(mwindow, this, x, y));
192 aparams_button->context_help_set_keyword("File Format section");
193 x += aparams_button->get_w() + margin;
195 window->add_subwindow(audio_switch = new FormatAudio(x, y, this, asset->audio_data));
196 audio_switch->context_help_set_keyword("File Format section");
200 y += aparams_button->get_h() + ys10;
202 //printf("FormatTools::create_objects 6\n");
203 aparams_thread = new FormatAThread(this);
206 //printf("FormatTools::create_objects 7\n");
208 if( horizontal_layout && do_audio ) {
213 //printf("FormatTools::create_objects 8\n");
214 window->add_subwindow(video_title = new BC_Title(x, y, _("Video:"), LARGEFONT,
215 BC_WindowBase::get_resources()->audiovideo_color));
216 video_title->context_help_set_keyword("File Format section");
217 x += video_title->get_w() + margin;
218 if(prompt_video_compression) {
219 window->add_subwindow(vparams_button = new FormatVParams(mwindow, this, x, y));
220 vparams_button->context_help_set_keyword("File Format section");
221 x += vparams_button->get_w() + margin;
224 //printf("FormatTools::create_objects 9\n");
226 window->add_subwindow(video_switch = new FormatVideo(x, y, this, asset->video_data));
227 video_switch->context_help_set_keyword("File Format section");
228 y += video_switch->get_h();
231 y += vparams_button->get_h();
234 //printf("FormatTools::create_objects 10\n");
236 vparams_thread = new FormatVThread(this);
239 //printf("FormatTools::create_objects 11\n");
242 if( file_per_label ) {
243 labeled_files = new FormatFilePerLabel(this, x, y, file_per_label);
244 window->add_subwindow(labeled_files);
245 labeled_files->context_help_set_keyword("File Format section");
246 y += labeled_files->get_h() + ys10;
249 //printf("FormatTools::create_objects 12\n");
255 void FormatTools::update_driver(int driver)
257 this->video_driver = driver;
259 locked_compressor = 0;
263 case VIDEO4LINUX2MPEG:
264 // Just give the user information about how the stream is going to be
265 // stored but don't change the asset.
266 // Want to be able to revert to user settings.
267 if(asset->format == FILE_MPEG) break;
268 asset->format = FILE_MPEG;
269 format_text->update(File::formattostr(asset->format));
270 asset->audio_data = 1;
271 asset->video_data = 1;
272 audio_switch->update(1);
273 video_switch->update(1);
276 case CAPTURE_IEC61883:
277 case CAPTURE_FIREWIRE:
278 case VIDEO4LINUX2JPEG:
279 case CAPTURE_JPEG_WEBCAM:
280 asset->format = FILE_FFMPEG;
281 format_text->update(File::formattostr(asset->format));
285 case CAPTURE_IEC61883:
286 case CAPTURE_FIREWIRE:
287 locked_compressor = (char*)CODEC_TAG_DVSD;
290 case VIDEO4LINUX2JPEG:
291 locked_compressor = (char*)CODEC_TAG_MJPEG;
294 case CAPTURE_JPEG_WEBCAM:
295 locked_compressor = (char*)CODEC_TAG_JPEG;
298 if( locked_compressor )
299 strcpy(asset->vcodec, locked_compressor);
301 audio_switch->update(asset->audio_data);
302 video_switch->update(asset->video_data);
306 format_text->update(File::formattostr(asset->format));
307 audio_switch->update(asset->audio_data);
308 video_switch->update(asset->video_data);
311 close_format_windows();
315 void FormatTools::update_format()
317 if( do_audio && prompt_audio && audio_switch ) {
318 audio_switch->update(asset->audio_data);
319 if( File::renders_audio(asset) )
320 audio_switch->enable();
322 audio_switch->disable();
324 if( do_video && prompt_video && video_switch ) {
325 video_switch->update(asset->video_data);
326 if( File::renders_video(asset) )
327 video_switch->enable();
329 video_switch->disable();
331 if( asset->format == FILE_FFMPEG ) {
333 format_ffmpeg->show();
337 format_ffmpeg->hide();
341 int FormatTools::handle_event()
346 Asset* FormatTools::get_asset()
351 void FormatTools::update_extension()
353 const char *extension = File::get_tag(asset->format);
354 // split multiple extensions
355 ArrayList<const char*> extensions;
356 int len = !extension ? -1 : strlen(extension);
357 const char *extension_ptr = extension;
358 for(int i = 0; i <= len; i++)
360 if(extension[i] == '/' || extension[i] == 0)
362 extensions.append(extension_ptr);
363 extension_ptr = extension + i + 1;
367 if(extensions.size())
369 char *ptr = strrchr(asset->path, '.');
372 ptr = asset->path + strlen(asset->path);
377 // test for equivalent extension
378 int need_extension = 1;
379 //int extension_len = 0;
380 for(int i = 0; i < extensions.size() && need_extension; i++)
383 extension_ptr = extensions.get(i);
386 while(*ptr1 != 0 && *extension_ptr != 0 && *extension_ptr != '/')
388 if(tolower(*ptr1) != tolower(*extension_ptr))
397 if( (!*ptr1 && (*extension_ptr && *extension_ptr != '/')) ||
398 (*ptr1 && (!*extension_ptr || *extension_ptr == '/')) )
402 //printf("FormatTools::update_extension %d %d\n", __LINE__, need_extension);
407 // change "qt" to "mov" since ffmpeg does not know qt
408 extension_ptr = asset->format != FILE_FFMPEG ? extensions.get(0) :
409 !strcmp(asset->fformat, "qt" ) ||
410 !strcmp(asset->fformat, "pro" ) ? "mov" : asset->fformat ;
411 while(*extension_ptr != 0 && *extension_ptr != '/')
412 *ptr1++ = *extension_ptr++;
416 int character1 = ptr - asset->path;
417 int character2 = strlen(asset->path);
418 // *(asset->path + character2) = 0;
421 path_textbox->update(asset->path);
422 path_textbox->set_selection(character1, character2, character2);
427 void FormatTools::update(Asset *asset, int *file_per_label)
430 this->file_per_label = file_per_label;
431 if( file_per_label ) labeled_files->update(file_per_label);
432 if( path_textbox ) path_textbox->update(asset->path);
433 format_text->update(File::formattostr(asset->format));
435 close_format_windows();
438 void FormatTools::close_format_windows()
440 // This is done in ~file
441 if( aparams_thread ) {
442 if( aparams_thread->running() )
443 aparams_thread->file->close_window();
444 aparams_thread->join();
446 if( vparams_thread ) {
447 if( vparams_thread->running() )
448 vparams_thread->file->close_window();
449 vparams_thread->join();
453 int FormatTools::get_w()
455 return asset->format != FILE_FFMPEG ? w :
456 format_ffmpeg->get_x() + format_ffmpeg->get_w();
459 void FormatTools::set_w(int w)
464 void FormatTools::reposition_window(int &init_x, int &init_y)
466 int xs10 = xS(10), xs80 = xS(80);
474 path_textbox->reposition_window(px, y);
475 px += path_textbox->get_w() + xS(5);
476 path_recent->reposition_window(px, y);
477 px += path_recent->get_w() + xS(8);
478 path_button->reposition_window(px, y);
479 y += path_textbox->get_h() + ys10;
482 format_title->reposition_window(x, y);
484 format_text->reposition_window(x, y);
485 x += format_text->get_w();
486 format_button->reposition_window(x, y);
487 x += format_button->get_w() + 5;
488 ffmpeg_type->reposition_window(x, y);
489 x += ffmpeg_type->get_w();
490 format_ffmpeg->reposition_window(x, y);
493 y += format_button->get_h() + ys10;
497 audio_title->reposition_window(x, y);
499 aparams_button->reposition_window(x, y);
500 x += aparams_button->get_w() + xs10;
501 if(prompt_audio) audio_switch->reposition_window(x, y);
504 y += aparams_button->get_h() + ys10;
510 video_title->reposition_window(x, y);
512 if(prompt_video_compression)
514 vparams_button->reposition_window(x, y);
515 x += vparams_button->get_w() + xs10;
520 video_switch->reposition_window(x, y);
521 y += video_switch->get_h();
525 y += vparams_button->get_h();
532 if( file_per_label ) {
533 labeled_files->reposition_window(x, y);
534 y += labeled_files->get_h() + ys10;
541 int FormatTools::set_audio_options()
543 // if(video_driver == CAPTURE_DVB)
548 if(!aparams_thread->running())
550 aparams_thread->start();
554 aparams_thread->file->raise_window();
559 int FormatTools::set_video_options()
561 // if(video_driver == CAPTURE_DVB)
566 if(!vparams_thread->running())
568 vparams_thread->start();
572 vparams_thread->file->raise_window();
582 FormatAParams::FormatAParams(MWindow *mwindow, FormatTools *format, int x, int y)
583 : BC_Button(x, y, mwindow->theme->get_image_set("wrench"))
585 this->format = format;
586 set_tooltip(_("Configure audio compression"));
589 FormatAParams::~FormatAParams()
593 int FormatAParams::handle_event()
595 format->set_audio_options();
596 format->handle_event();
604 FormatVParams::FormatVParams(MWindow *mwindow, FormatTools *format, int x, int y)
605 : BC_Button(x, y, mwindow->theme->get_image_set("wrench"))
607 this->format = format;
608 set_tooltip(_("Configure video compression"));
611 FormatVParams::~FormatVParams()
615 int FormatVParams::handle_event()
617 format->set_video_options();
618 format->handle_event();
626 FormatAThread::FormatAThread(FormatTools *format)
629 this->format = format;
634 FormatAThread::~FormatAThread()
636 delete file; file = 0;
640 void FormatAThread::start()
648 void FormatAThread::run()
650 file->get_options(format, 1, 0);
656 FormatVThread::FormatVThread(FormatTools *format)
659 this->format = format;
664 FormatVThread::~FormatVThread()
666 delete file; file = 0;
670 void FormatVThread::start()
677 void FormatVThread::run()
679 file->get_options(format, 0, 1);
686 FormatPathText::FormatPathText(int x, int y, FormatTools *format)
687 : BC_TextBox(x, y, format->w - x -
688 2*format->mwindow->theme->get_image_set("wrench")[0]->get_w() - xS(20), 1,
691 this->format = format;
694 FormatPathText::~FormatPathText()
697 int FormatPathText::handle_event()
699 calculate_suggestions();
700 strcpy(format->asset->path, get_text());
701 format->handle_event();
708 FormatAudio::FormatAudio(int x, int y, FormatTools *format, int default_)
712 (char*)(format->recording ? _("Record audio tracks") : _("Render audio tracks")))
714 this->format = format;
717 FormatAudio::~FormatAudio() {}
718 int FormatAudio::handle_event()
720 format->asset->audio_data = get_value();
721 format->handle_event();
726 FormatVideo::FormatVideo(int x, int y, FormatTools *format, int default_)
730 (char*)(format->recording ? _("Record video tracks") : _("Render video tracks")))
732 this->format = format;
735 FormatVideo::~FormatVideo() {}
736 int FormatVideo::handle_event()
738 format->asset->video_data = get_value();
739 format->handle_event();
746 FormatFormat::FormatFormat(int x, int y, FormatTools *format)
747 : FormatPopup(x, y, format->do_audio, format->do_video, format->use_brender)
749 this->format = format;
752 FormatFormat::~FormatFormat()
756 int FormatFormat::handle_event()
758 BC_ListBoxItem *selection = get_selection(0, 0);
760 int new_format = File::strtoformat(get_selection(0, 0)->get_text());
761 // if(new_format != format->asset->format)
763 Asset *asset = format->asset;
764 asset->format = new_format;
765 asset->audio_data = File::renders_audio(asset);
766 asset->video_data = File::renders_video(asset);
767 asset->ff_audio_options[0] = 0;
768 asset->ff_video_options[0] = 0;
769 asset->ff_format_options[0] = 0;
770 format->format_text->update(selection->get_text());
771 if( !format->use_brender )
772 format->update_extension();
773 format->close_format_windows();
774 if (format->path_recent) format->path_recent->
775 load_items(File::formattostr(format->asset->format));
776 format->update_format();
778 format->handle_event();
784 FormatFFMPEG::FormatFFMPEG(int x, int y, FormatTools *format)
787 this->format = format;
790 FormatFFMPEG::~FormatFFMPEG()
794 int FormatFFMPEG::handle_event()
796 BC_ListBoxItem *selection = get_selection(0, 0);
798 const char *text = get_selection(0, 0)->get_text();
799 format->ffmpeg_type->update(text);
800 // forces options load defaults
801 format->asset->ff_audio_options[0] = 0;
802 format->asset->ff_video_options[0] = 0;
803 format->asset->ff_format_options[0] = 0;
804 FFMPEG::set_asset_format(format->asset, format->mwindow->edl, text);
805 format->update_extension();
806 format->close_format_windows();
807 format->update_format();
808 format->handle_event();
814 FormatFilePerLabel::FormatFilePerLabel(FormatTools *format,
815 int x, int y, int *output)
816 : BC_CheckBox(x, y, *output, _("Create new file at each label"))
818 this->format = format;
819 this->output = output;
822 FormatFilePerLabel::~FormatFilePerLabel()
826 int FormatFilePerLabel::handle_event()
828 *output = get_value();
829 format->handle_event();
833 void FormatFilePerLabel::update(int *output)
835 this->output = output;
836 set_value(*output ? 1 : 0);