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"
32 #include "maxchannels.h"
34 #include "preferences.h"
36 #include "videodevice.inc"
42 FormatTools::FormatTools(MWindow *mwindow,
43 BC_WindowBase *window,
46 this->mwindow = mwindow;
47 this->window = window;
49 this->plugindb = mwindow->plugindb;
79 prompt_audio_channels = 0;
81 prompt_video_compression = 0;
83 locked_compressor = 0;
87 FormatTools::~FormatTools()
98 if(aparams_button) delete aparams_button;
100 if(vparams_button) delete vparams_button;
102 if(aparams_thread) delete aparams_thread;
104 if(vparams_thread) delete vparams_thread;
106 if(channels_tumbler) delete channels_tumbler;
110 file_entries->remove_all_objects();
115 void FormatTools::create_objects(int &init_x,
117 int do_audio, // Include support for audio
118 int do_video, // Include support for video
119 int prompt_audio, // Include checkbox for audio
121 int prompt_audio_channels,
122 int prompt_video_compression,
123 const char *locked_compressor,
127 int horizontal_layout)
133 this->locked_compressor = locked_compressor;
134 this->recording = recording;
135 this->use_brender = brender;
136 this->do_audio = do_audio;
137 this->do_video = do_video;
138 this->prompt_audio = prompt_audio;
139 this->prompt_audio_channels = prompt_audio_channels;
140 this->prompt_video = prompt_video;
141 this->prompt_video_compression = prompt_video_compression;
142 this->strategy = strategy;
145 file_entries = new ArrayList<BC_ListBoxItem*>;
147 char string[BCTEXTLEN];
148 // Load current directory
149 fs.update(getcwd(string, BCTEXTLEN));
150 for(int i = 0; i < fs.total_files(); i++)
152 file_entries->append(
154 fs.get_entry(i)->get_name()));
157 //printf("FormatTools::create_objects 1\n");
159 // Modify strategy depending on render farm
162 if(mwindow->preferences->use_renderfarm)
164 if(*strategy == FILE_PER_LABEL)
165 *strategy = FILE_PER_LABEL_FARM;
167 if(*strategy == SINGLE_PASS)
168 *strategy = SINGLE_PASS_FARM;
172 if(*strategy == FILE_PER_LABEL_FARM)
173 *strategy = FILE_PER_LABEL;
175 if(*strategy == SINGLE_PASS_FARM)
176 *strategy = SINGLE_PASS;
183 window->add_subwindow(path_textbox = new FormatPathText(px, y, this));
184 px += path_textbox->get_w() + 5;
185 path_recent = new BC_RecentList("PATH", mwindow->defaults,
186 path_textbox, 10, px, y, 300, 100);
187 window->add_subwindow(path_recent);
188 path_recent->load_items(File::formattostr(asset->format));
189 px += path_recent->get_w() + 8;
190 window->add_subwindow(path_button = new BrowseButton(
191 mwindow->theme, window, path_textbox, px, y, asset->path,
192 _("Output to file"), _("Select a file to write to:"), 0));
196 y += path_textbox->get_h() + 10;
205 window->add_subwindow(format_title = new BC_Title(x, y, _("File Format:")));
207 window->add_subwindow(format_text = new BC_TextBox(x, y, 160, 1,
208 File::formattostr(asset->format)));
209 x += format_text->get_w();
210 //printf("FormatTools::create_objects %d %p\n", __LINE__, window);
211 window->add_subwindow(format_button = new FormatFormat(x, y, this));
212 format_button->create_objects();
213 x += format_button->get_w() + 5;
214 window->add_subwindow(ffmpeg_type = new FFMpegType(x, y, 64, 1, asset->fformat));
215 FFMPEG::set_asset_format(asset, asset->fformat);
216 x += ffmpeg_type->get_w();
217 window->add_subwindow(format_ffmpeg = new FormatFFMPEG(x, y, this));
218 format_ffmpeg->create_objects();
220 y += format_button->get_h() + 10;
223 window->add_subwindow(audio_title = new BC_Title(x, y, _("Audio:"), LARGEFONT, BC_WindowBase::get_resources()->audiovideo_color));
225 window->add_subwindow(aparams_button = new FormatAParams(mwindow, this, x, y));
226 x += aparams_button->get_w() + 10;
229 window->add_subwindow(audio_switch = new FormatAudio(x, y, this, asset->audio_data));
233 y += aparams_button->get_h() + 10;
235 // Audio channels only used for recording.
236 // if(prompt_audio_channels)
238 // window->add_subwindow(channels_title = new BC_Title(x, y, _("Number of audio channels to record:")));
240 // window->add_subwindow(channels_button = new FormatChannels(x, y, this));
241 // x += channels_button->get_w() + 5;
242 // window->add_subwindow(channels_tumbler = new BC_ITumbler(channels_button, 1, MAXCHANNELS, x, y));
243 // y += channels_button->get_h() + 20;
247 //printf("FormatTools::create_objects 6\n");
248 aparams_thread = new FormatAThread(this);
251 //printf("FormatTools::create_objects 7\n");
254 if(horizontal_layout && do_audio){
259 //printf("FormatTools::create_objects 8\n");
260 window->add_subwindow(video_title = new BC_Title(x, y, _("Video:"), LARGEFONT, BC_WindowBase::get_resources()->audiovideo_color));
262 if(prompt_video_compression)
264 window->add_subwindow(vparams_button = new FormatVParams(mwindow, this, x, y));
265 x += vparams_button->get_w() + 10;
268 //printf("FormatTools::create_objects 9\n");
271 window->add_subwindow(video_switch = new FormatVideo(x, y, this, asset->video_data));
272 y += video_switch->get_h();
276 y += vparams_button->get_h();
279 //printf("FormatTools::create_objects 10\n");
281 vparams_thread = new FormatVThread(this);
284 //printf("FormatTools::create_objects 11\n");
289 window->add_subwindow(multiple_files = new FormatMultiple(mwindow, x, y, strategy));
290 y += multiple_files->get_h() + 10;
293 //printf("FormatTools::create_objects 12\n");
299 void FormatTools::update_driver(int driver)
301 this->video_driver = driver;
303 locked_compressor = 0;
307 case VIDEO4LINUX2MPEG:
308 // Just give the user information about how the stream is going to be
309 // stored but don't change the asset.
310 // Want to be able to revert to user settings.
311 if(asset->format == FILE_MPEG) break;
312 asset->format = FILE_MPEG;
313 format_text->update(File::formattostr(asset->format));
314 asset->audio_data = 1;
315 asset->video_data = 1;
316 audio_switch->update(1);
317 video_switch->update(1);
320 case CAPTURE_IEC61883:
321 case CAPTURE_FIREWIRE:
322 case VIDEO4LINUX2JPEG:
323 case CAPTURE_JPEG_WEBCAM:
324 asset->format = FILE_FFMPEG;
325 format_text->update(File::formattostr(asset->format));
328 case CAPTURE_IEC61883:
329 case CAPTURE_FIREWIRE:
330 locked_compressor = (char*)CODEC_TAG_DVSD;
333 case VIDEO4LINUX2JPEG:
334 locked_compressor = (char*)CODEC_TAG_MJPEG;
337 case CAPTURE_JPEG_WEBCAM:
338 locked_compressor = (char*)CODEC_TAG_JPEG;
341 if( locked_compressor )
342 strcpy(asset->vcodec, locked_compressor);
344 audio_switch->update(asset->audio_data);
345 video_switch->update(asset->video_data);
349 format_text->update(File::formattostr(asset->format));
350 audio_switch->update(asset->audio_data);
351 video_switch->update(asset->video_data);
354 close_format_windows();
358 void FormatTools::update_format()
360 if( do_audio && prompt_audio && audio_switch ) {
361 audio_switch->update(asset->audio_data);
362 if( !asset->audio_data )
363 audio_switch->disable();
365 audio_switch->enable();
367 if( do_video && prompt_video && video_switch ) {
368 video_switch->update(asset->video_data);
369 if( !asset->video_data )
370 video_switch->disable();
372 video_switch->enable();
374 if( asset->format == FILE_FFMPEG ) {
376 format_ffmpeg->show();
380 format_ffmpeg->hide();
384 int FormatTools::handle_event()
389 Asset* FormatTools::get_asset()
394 void FormatTools::update_extension()
396 const char *extension = File::get_tag(asset->format);
397 // split multiple extensions
398 ArrayList<const char*> extensions;
399 int len = !extension ? -1 : strlen(extension);
400 const char *extension_ptr = extension;
401 for(int i = 0; i <= len; i++)
403 if(extension[i] == '/' || extension[i] == 0)
405 extensions.append(extension_ptr);
406 extension_ptr = extension + i + 1;
410 if(extensions.size())
412 char *ptr = strrchr(asset->path, '.');
415 ptr = asset->path + strlen(asset->path);
420 // test for equivalent extension
421 int need_extension = 1;
422 //int extension_len = 0;
423 for(int i = 0; i < extensions.size() && need_extension; i++)
426 extension_ptr = extensions.get(i);
429 while(*ptr1 != 0 && *extension_ptr != 0 && *extension_ptr != '/')
431 if(tolower(*ptr1) != tolower(*extension_ptr))
441 *extension_ptr != 0 &&
442 *extension_ptr != '/')
446 //printf("FormatTools::update_extension %d %d\n", __LINE__, need_extension);
451 extension_ptr = asset->format != FILE_FFMPEG ?
452 extensions.get(0) : asset->fformat;
453 while(*extension_ptr != 0 && *extension_ptr != '/')
454 *ptr1++ = *extension_ptr++;
458 int character1 = ptr - asset->path;
459 int character2 = strlen(asset->path);
460 // *(asset->path + character2) = 0;
463 path_textbox->update(asset->path);
464 path_textbox->set_selection(character1, character2, character2);
469 void FormatTools::update(Asset *asset, int *strategy)
472 this->strategy = strategy;
475 path_textbox->update(asset->path);
476 format_text->update(File::formattostr(plugindb, asset->format));
477 if(do_audio && prompt_audio && audio_switch)
478 audio_switch->update(asset->audio_data);
479 if(do_video && prompt_video && video_switch)
480 video_switch->update(asset->video_data);
483 multiple_files->update(strategy);
485 close_format_windows();
488 void FormatTools::close_format_windows()
490 // This is done in ~file
491 if( aparams_thread ) {
492 if( aparams_thread->running() )
493 aparams_thread->file->close_window();
494 aparams_thread->join();
496 if( vparams_thread ) {
497 if( vparams_thread->running() )
498 vparams_thread->file->close_window();
499 vparams_thread->join();
503 int FormatTools::get_w()
505 return asset->format != FILE_FFMPEG ? w :
506 format_ffmpeg->get_x() + format_ffmpeg->get_w();
509 void FormatTools::set_w(int w)
514 void FormatTools::reposition_window(int &init_x, int &init_y)
522 path_textbox->reposition_window(px, y);
523 px += path_textbox->get_w() + 5;
524 path_recent->reposition_window(px, y);
525 px += path_recent->get_w() + 8;
526 path_button->reposition_window(px, y);
527 y += path_textbox->get_h() + 10;
530 format_title->reposition_window(x, y);
532 format_text->reposition_window(x, y);
533 x += format_text->get_w();
534 format_button->reposition_window(x, y);
537 y += format_button->get_h() + 10;
541 audio_title->reposition_window(x, y);
543 aparams_button->reposition_window(x, y);
544 x += aparams_button->get_w() + 10;
545 if(prompt_audio) audio_switch->reposition_window(x, y);
548 y += aparams_button->get_h() + 10;
549 if(prompt_audio_channels)
551 channels_title->reposition_window(x, y);
553 channels_button->reposition_window(x, y);
554 x += channels_button->get_w() + 5;
555 channels_tumbler->reposition_window(x, y);
556 y += channels_button->get_h() + 20;
564 video_title->reposition_window(x, y);
566 if(prompt_video_compression)
568 vparams_button->reposition_window(x, y);
569 x += vparams_button->get_w() + 10;
574 video_switch->reposition_window(x, y);
575 y += video_switch->get_h();
579 y += vparams_button->get_h();
588 multiple_files->reposition_window(x, y);
589 y += multiple_files->get_h() + 10;
596 int FormatTools::set_audio_options()
598 // if(video_driver == CAPTURE_DVB)
603 if(!aparams_thread->running())
605 aparams_thread->start();
609 aparams_thread->file->raise_window();
614 int FormatTools::set_video_options()
616 // if(video_driver == CAPTURE_DVB)
621 if(!vparams_thread->running())
623 vparams_thread->start();
627 vparams_thread->file->raise_window();
637 FormatAParams::FormatAParams(MWindow *mwindow, FormatTools *format, int x, int y)
638 : BC_Button(x, y, mwindow->theme->get_image_set("wrench"))
640 this->format = format;
641 set_tooltip(_("Configure audio compression"));
644 FormatAParams::~FormatAParams()
648 int FormatAParams::handle_event()
650 format->set_audio_options();
658 FormatVParams::FormatVParams(MWindow *mwindow, FormatTools *format, int x, int y)
659 : BC_Button(x, y, mwindow->theme->get_image_set("wrench"))
661 this->format = format;
662 set_tooltip(_("Configure video compression"));
665 FormatVParams::~FormatVParams()
669 int FormatVParams::handle_event()
671 format->set_video_options();
679 FormatAThread::FormatAThread(FormatTools *format)
682 this->format = format;
687 FormatAThread::~FormatAThread()
689 delete file; file = 0;
693 void FormatAThread::start()
701 void FormatAThread::run()
703 file->get_options(format, 1, 0);
709 FormatVThread::FormatVThread(FormatTools *format)
712 this->format = format;
717 FormatVThread::~FormatVThread()
719 delete file; file = 0;
723 void FormatVThread::start()
730 void FormatVThread::run()
732 file->get_options(format, 0, 1);
739 FormatPathText::FormatPathText(int x, int y, FormatTools *format)
740 : BC_TextBox(x, y, format->w - x -
741 2*format->mwindow->theme->get_image_set("wrench")[0]->get_w() - 20, 1,
744 this->format = format;
747 FormatPathText::~FormatPathText()
750 int FormatPathText::handle_event()
753 calculate_suggestions(format->file_entries);
757 strcpy(format->asset->path, get_text());
758 format->handle_event();
765 FormatAudio::FormatAudio(int x, int y, FormatTools *format, int default_)
769 (char*)(format->recording ? _("Record audio tracks") : _("Render audio tracks")))
771 this->format = format;
774 FormatAudio::~FormatAudio() {}
775 int FormatAudio::handle_event()
777 format->asset->audio_data = get_value();
782 FormatVideo::FormatVideo(int x, int y, FormatTools *format, int default_)
786 (char*)(format->recording ? _("Record video tracks") : _("Render video tracks")))
788 this->format = format;
791 FormatVideo::~FormatVideo() {}
792 int FormatVideo::handle_event()
794 format->asset->video_data = get_value();
801 FormatFormat::FormatFormat(int x, int y, FormatTools *format)
802 : FormatPopup(format->plugindb, x, y, format->use_brender)
804 this->format = format;
807 FormatFormat::~FormatFormat()
811 int FormatFormat::handle_event()
813 BC_ListBoxItem *selection = get_selection(0, 0);
815 int new_format = File::strtoformat(format->plugindb, get_selection(0, 0)->get_text());
816 // if(new_format != format->asset->format)
818 Asset *asset = format->asset;
819 asset->format = new_format;
820 asset->audio_data = File::supports_audio(asset->format);
821 asset->video_data = File::supports_video(asset->format);
822 asset->ff_audio_options[0] = 0;
823 asset->ff_video_options[0] = 0;
824 format->format_text->update(selection->get_text());
825 format->update_extension();
826 format->close_format_windows();
827 if (format->path_recent) format->path_recent->
828 load_items(File::formattostr(format->asset->format));
829 format->update_format();
836 FormatFFMPEG::FormatFFMPEG(int x, int y, FormatTools *format)
837 : FFMPEGPopup(format->plugindb, x, y)
839 this->format = format;
842 FormatFFMPEG::~FormatFFMPEG()
846 int FormatFFMPEG::handle_event()
848 BC_ListBoxItem *selection = get_selection(0, 0);
850 char *text = get_selection(0, 0)->get_text();
851 format->ffmpeg_type->update(text);
852 format->asset->ff_audio_options[0] = 0;
853 format->asset->ff_video_options[0] = 0;
854 FFMPEG::set_asset_format(format->asset, text);
855 format->update_extension();
856 format->close_format_windows();
857 format->update_format();
865 FormatChannels::FormatChannels(int x, int y, FormatTools *format)
866 : BC_TextBox(x, y, 100, 1, format->asset->channels)
868 this->format = format;
871 FormatChannels::~FormatChannels()
875 int FormatChannels::handle_event()
877 format->asset->channels = atol(get_text());
882 FormatToTracks::FormatToTracks(int x, int y, int *output)
883 : BC_CheckBox(x, y, *output, _("Overwrite project with output"))
885 this->output = output;
888 FormatToTracks::~FormatToTracks()
892 int FormatToTracks::handle_event()
894 *output = get_value();
899 FormatMultiple::FormatMultiple(MWindow *mwindow, int x, int y, int *output)
902 (*output == FILE_PER_LABEL) || (*output == FILE_PER_LABEL_FARM),
903 _("Create new file at each label"))
905 this->output = output;
906 this->mwindow = mwindow;
909 FormatMultiple::~FormatMultiple()
913 int FormatMultiple::handle_event()
917 if(mwindow->preferences->use_renderfarm)
918 *output = FILE_PER_LABEL_FARM;
920 *output = FILE_PER_LABEL;
924 if(mwindow->preferences->use_renderfarm)
925 *output = SINGLE_PASS_FARM;
927 *output = SINGLE_PASS;
932 void FormatMultiple::update(int *output)
934 this->output = output;
935 if(*output == FILE_PER_LABEL_FARM ||
936 *output ==FILE_PER_LABEL)