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;
78 prompt_audio_channels = 0;
80 prompt_video_compression = 0;
82 locked_compressor = 0;
86 FormatTools::~FormatTools()
96 if(aparams_button) delete aparams_button;
98 if(vparams_button) delete vparams_button;
100 if(aparams_thread) delete aparams_thread;
102 if(vparams_thread) delete vparams_thread;
104 if(channels_tumbler) delete channels_tumbler;
108 file_entries->remove_all_objects();
113 void FormatTools::create_objects(int &init_x,
115 int do_audio, // Include support for audio
116 int do_video, // Include support for video
117 int prompt_audio, // Include checkbox for audio
119 int prompt_audio_channels,
120 int prompt_video_compression,
121 char *locked_compressor,
129 this->locked_compressor = locked_compressor;
130 this->recording = recording;
131 this->use_brender = brender;
132 this->do_audio = do_audio;
133 this->do_video = do_video;
134 this->prompt_audio = prompt_audio;
135 this->prompt_audio_channels = prompt_audio_channels;
136 this->prompt_video = prompt_video;
137 this->prompt_video_compression = prompt_video_compression;
138 this->strategy = strategy;
141 file_entries = new ArrayList<BC_ListBoxItem*>;
143 char string[BCTEXTLEN];
144 // Load current directory
145 fs.update(getcwd(string, BCTEXTLEN));
146 for(int i = 0; i < fs.total_files(); i++)
148 file_entries->append(
150 fs.get_entry(i)->get_name()));
153 //printf("FormatTools::create_objects 1\n");
155 // Modify strategy depending on render farm
158 if(mwindow->preferences->use_renderfarm)
160 if(*strategy == FILE_PER_LABEL)
161 *strategy = FILE_PER_LABEL_FARM;
163 if(*strategy == SINGLE_PASS)
164 *strategy = SINGLE_PASS_FARM;
168 if(*strategy == FILE_PER_LABEL_FARM)
169 *strategy = FILE_PER_LABEL;
171 if(*strategy == SINGLE_PASS_FARM)
172 *strategy = SINGLE_PASS;
178 window->add_subwindow(path_textbox = new FormatPathText(x, y, this));
179 x += path_textbox->get_w() + 5;
180 window->add_subwindow(path_button = new BrowseButton(
188 _("Select a file to write to:"),
193 // w = x + path_button->get_w() + 5;
194 x -= path_textbox->get_w() + 5;
203 window->add_subwindow(format_title = new BC_Title(x, y, _("File Format:")));
205 window->add_subwindow(format_text = new BC_TextBox(x, y, 180, 1,
206 File::formattostr(asset->format)));
207 x += format_text->get_w();
208 //printf("FormatTools::create_objects %d %p\n", __LINE__, window);
209 window->add_subwindow(format_button = new FormatFormat(x, y, this));
210 format_button->create_objects();
211 x += format_button->get_w() + 5;
212 window->add_subwindow(ffmpeg_type = new FFMpegType(x, y, 50, 1, asset->fformat));
213 x += ffmpeg_type->get_w();
214 window->add_subwindow(format_ffmpeg = new FormatFFMPEG(x, y, this));
215 format_ffmpeg->create_objects();
218 y += format_button->get_h() + 10;
221 window->add_subwindow(audio_title = new BC_Title(x, y, _("Audio:"), LARGEFONT, RED));
223 window->add_subwindow(aparams_button = new FormatAParams(mwindow, this, x, y));
224 x += aparams_button->get_w() + 10;
227 window->add_subwindow(audio_switch = new FormatAudio(x, y, this, asset->audio_data));
230 y += aparams_button->get_h() + 10;
232 // Audio channels only used for recording.
233 // if(prompt_audio_channels)
235 // window->add_subwindow(channels_title = new BC_Title(x, y, _("Number of audio channels to record:")));
237 // window->add_subwindow(channels_button = new FormatChannels(x, y, this));
238 // x += channels_button->get_w() + 5;
239 // window->add_subwindow(channels_tumbler = new BC_ITumbler(channels_button, 1, MAXCHANNELS, x, y));
240 // y += channels_button->get_h() + 20;
244 //printf("FormatTools::create_objects 6\n");
245 aparams_thread = new FormatAThread(this);
248 //printf("FormatTools::create_objects 7\n");
252 //printf("FormatTools::create_objects 8\n");
253 window->add_subwindow(video_title = new BC_Title(x, y, _("Video:"), LARGEFONT, RED));
255 if(prompt_video_compression)
257 window->add_subwindow(vparams_button = new FormatVParams(mwindow, this, x, y));
258 x += vparams_button->get_w() + 10;
261 //printf("FormatTools::create_objects 9\n");
264 window->add_subwindow(video_switch = new FormatVideo(x, y, this, asset->video_data));
265 y += video_switch->get_h();
269 y += vparams_button->get_h();
272 //printf("FormatTools::create_objects 10\n");
274 vparams_thread = new FormatVThread(this);
277 //printf("FormatTools::create_objects 11\n");
282 window->add_subwindow(multiple_files = new FormatMultiple(mwindow, x, y, strategy));
283 y += multiple_files->get_h() + 10;
286 //printf("FormatTools::create_objects 12\n");
292 void FormatTools::update_driver(int driver)
294 this->video_driver = driver;
296 locked_compressor = 0;
300 case VIDEO4LINUX2MPEG:
301 // Just give the user information about how the stream is going to be
302 // stored but don't change the asset.
303 // Want to be able to revert to user settings.
304 if(asset->format != FILE_MPEG)
306 format_text->update(_("MPEG stream"));
307 asset->format = FILE_MPEG;
309 audio_switch->update(1);
310 video_switch->update(1);
313 case CAPTURE_IEC61883:
314 case CAPTURE_FIREWIRE:
317 case VIDEO4LINUX2JPEG:
318 case CAPTURE_JPEG_WEBCAM:
319 asset->format = FILE_FFMPEG;
320 format_text->update(File::formattostr(asset->format));
323 case CAPTURE_IEC61883:
324 case CAPTURE_FIREWIRE:
325 locked_compressor = (char*)CODEC_TAG_DVSD;
330 case VIDEO4LINUX2JPEG:
331 locked_compressor = (char*)CODEC_TAG_MJPEG;
334 case CAPTURE_JPEG_WEBCAM:
335 locked_compressor = (char*)CODEC_TAG_JPEG;
338 if( locked_compressor )
339 strcpy(asset->vcodec, locked_compressor);
341 audio_switch->update(asset->audio_data);
342 video_switch->update(asset->video_data);
346 format_text->update(File::formattostr(asset->format));
347 audio_switch->update(asset->audio_data);
348 video_switch->update(asset->video_data);
351 close_format_windows();
355 void FormatTools::update_format()
357 if( do_audio && prompt_audio && audio_switch ) {
358 audio_switch->update(asset->audio_data);
359 if( !asset->audio_data )
360 audio_switch->disable();
362 audio_switch->enable();
364 if( do_video && prompt_video && video_switch ) {
365 video_switch->update(asset->video_data);
366 if( !asset->video_data )
367 video_switch->disable();
369 video_switch->enable();
371 if( asset->format == FILE_FFMPEG ) {
373 format_ffmpeg->show();
377 format_ffmpeg->hide();
381 int FormatTools::handle_event()
386 Asset* FormatTools::get_asset()
391 void FormatTools::update_extension()
393 const char *extension = File::get_tag(asset->format);
394 // split multiple extensions
395 ArrayList<const char*> extensions;
396 int len = !extension ? -1 : strlen(extension);
397 const char *extension_ptr = extension;
398 for(int i = 0; i <= len; i++)
400 if(extension[i] == '/' || extension[i] == 0)
402 extensions.append(extension_ptr);
403 extension_ptr = extension + i + 1;
407 if(extensions.size())
409 char *ptr = strrchr(asset->path, '.');
412 ptr = asset->path + strlen(asset->path);
418 // test for equivalent extension
419 int need_extension = 1;
420 //int extension_len = 0;
421 for(int i = 0; i < extensions.size() && need_extension; i++)
424 extension_ptr = extensions.get(i);
427 while(*ptr1 != 0 && *extension_ptr != 0 && *extension_ptr != '/')
429 if(tolower(*ptr1) != tolower(*extension_ptr))
439 *extension_ptr != 0 &&
440 *extension_ptr != '/')
444 //printf("FormatTools::update_extension %d %d\n", __LINE__, need_extension);
449 extension_ptr = asset->format != FILE_FFMPEG ?
450 extensions.get(0) : asset->fformat;
451 while(*extension_ptr != 0 && *extension_ptr != '/')
452 *ptr1++ = *extension_ptr++;
456 int character1 = ptr - asset->path;
457 int character2 = strlen(asset->path);
458 // *(asset->path + character2) = 0;
461 path_textbox->update(asset->path);
462 path_textbox->set_selection(character1, character2, character2);
467 void FormatTools::update(Asset *asset, int *strategy)
470 this->strategy = strategy;
473 path_textbox->update(asset->path);
474 format_text->update(File::formattostr(plugindb, asset->format));
475 if(do_audio && prompt_audio && audio_switch)
476 audio_switch->update(asset->audio_data);
477 if(do_video && prompt_video && video_switch)
478 video_switch->update(asset->video_data);
481 multiple_files->update(strategy);
483 close_format_windows();
486 void FormatTools::close_format_windows()
488 // This is done in ~file
489 if(aparams_thread && aparams_thread->running())
491 aparams_thread->file->close_window();
492 aparams_thread->join();
494 if(vparams_thread && vparams_thread->running())
496 vparams_thread->file->close_window();
497 vparams_thread->join();
501 int FormatTools::get_w()
506 void FormatTools::set_w(int w)
511 void FormatTools::reposition_window(int &init_x, int &init_y)
518 path_textbox->reposition_window(x, y);
519 x += path_textbox->get_w() + 5;
520 path_button->reposition_window(x, y);
521 x -= path_textbox->get_w() + 5;
525 format_title->reposition_window(x, y);
527 format_text->reposition_window(x, y);
528 x += format_text->get_w();
529 format_button->reposition_window(x, y);
532 y += format_button->get_h() + 10;
536 audio_title->reposition_window(x, y);
538 aparams_button->reposition_window(x, y);
539 x += aparams_button->get_w() + 10;
540 if(prompt_audio) audio_switch->reposition_window(x, y);
543 y += aparams_button->get_h() + 20;
544 if(prompt_audio_channels)
546 channels_title->reposition_window(x, y);
548 channels_button->reposition_window(x, y);
549 x += channels_button->get_w() + 5;
550 channels_tumbler->reposition_window(x, y);
551 y += channels_button->get_h() + 20;
559 video_title->reposition_window(x, y);
561 if(prompt_video_compression)
563 vparams_button->reposition_window(x, y);
564 x += vparams_button->get_w() + 10;
569 video_switch->reposition_window(x, y);
570 y += video_switch->get_h();
574 y += vparams_button->get_h();
583 multiple_files->reposition_window(x, y);
584 y += multiple_files->get_h() + 10;
591 int FormatTools::set_audio_options()
593 // if(video_driver == CAPTURE_DVB)
598 if(!aparams_thread->running())
600 aparams_thread->start();
604 aparams_thread->file->raise_window();
609 int FormatTools::set_video_options()
611 // if(video_driver == CAPTURE_DVB)
616 if(!vparams_thread->running())
618 vparams_thread->start();
622 vparams_thread->file->raise_window();
632 FormatAParams::FormatAParams(MWindow *mwindow, FormatTools *format, int x, int y)
633 : BC_Button(x, y, mwindow->theme->get_image_set("wrench"))
635 this->format = format;
636 set_tooltip(_("Configure audio compression"));
639 FormatAParams::~FormatAParams()
643 int FormatAParams::handle_event()
645 format->set_audio_options();
653 FormatVParams::FormatVParams(MWindow *mwindow, FormatTools *format, int x, int y)
654 : BC_Button(x, y, mwindow->theme->get_image_set("wrench"))
656 this->format = format;
657 set_tooltip(_("Configure video compression"));
660 FormatVParams::~FormatVParams()
664 int FormatVParams::handle_event()
666 format->set_video_options();
674 FormatAThread::FormatAThread(FormatTools *format)
677 this->format = format;
682 FormatAThread::~FormatAThread()
689 void FormatAThread::start()
697 void FormatAThread::run()
699 file->get_options(format, 1, 0);
705 FormatVThread::FormatVThread(FormatTools *format)
708 this->format = format;
713 FormatVThread::~FormatVThread()
720 void FormatVThread::start()
727 void FormatVThread::run()
729 file->get_options(format, 0, 1);
736 FormatPathText::FormatPathText(int x, int y, FormatTools *format)
740 format->mwindow->theme->get_image_set("wrench")[0]->get_w() -
745 this->format = format;
748 FormatPathText::~FormatPathText()
751 int FormatPathText::handle_event()
754 calculate_suggestions(format->file_entries);
758 strcpy(format->asset->path, get_text());
759 format->handle_event();
767 FormatAudio::FormatAudio(int x, int y, FormatTools *format, int default_)
771 (char*)(format->recording ? _("Record audio tracks") : _("Render audio tracks")))
773 this->format = format;
776 FormatAudio::~FormatAudio() {}
777 int FormatAudio::handle_event()
779 format->asset->audio_data = get_value();
784 FormatVideo::FormatVideo(int x, int y, FormatTools *format, int default_)
788 (char*)(format->recording ? _("Record video tracks") : _("Render video tracks")))
790 this->format = format;
793 FormatVideo::~FormatVideo() {}
794 int FormatVideo::handle_event()
796 format->asset->video_data = get_value();
803 FormatFormat::FormatFormat(int x, int y, FormatTools *format)
804 : FormatPopup(format->plugindb, x, y, format->use_brender)
806 this->format = format;
809 FormatFormat::~FormatFormat()
813 int FormatFormat::handle_event()
815 BC_ListBoxItem *selection = get_selection(0, 0);
817 int new_format = File::strtoformat(format->plugindb, get_selection(0, 0)->get_text());
818 // if(new_format != format->asset->format)
820 Asset *asset = format->asset;
821 asset->format = new_format;
822 asset->audio_data = File::supports_audio(asset->format);
823 asset->video_data = File::supports_video(asset->format);
824 format->format_text->update(selection->get_text());
825 format->update_extension();
826 format->close_format_windows();
827 format->update_format();
834 FormatFFMPEG::FormatFFMPEG(int x, int y, FormatTools *format)
835 : FFMPEGPopup(format->plugindb, x, y)
837 this->format = format;
840 FormatFFMPEG::~FormatFFMPEG()
844 int FormatFFMPEG::load_defaults(const char *path, const char *type,
845 char *codec, char *codec_options, int len)
847 char default_file[BCTEXTLEN];
848 FFMPEG::set_option_path(default_file, "%s/%s.dfl", path, type);
849 FILE *fp = fopen(default_file,"r");
851 fgets(codec, BCSTRLEN, fp);
853 while( *cp && *cp!='\n' ) ++cp;
855 while( len > 0 && fgets(codec_options, len, fp) ) {
856 int n = strlen(codec_options);
857 codec_options += n; len -= n;
860 FFMPEG::set_option_path(default_file, "%s/%s", path, codec);
861 return FFMPEG::load_options(default_file, codec_options, len);
864 int FormatFFMPEG::handle_event()
866 BC_ListBoxItem *selection = get_selection(0, 0);
868 char *text = get_selection(0, 0)->get_text();
869 format->ffmpeg_type->update(text);
870 Asset *asset = format->asset;
871 strcpy(asset->fformat, text);
872 strcpy(asset->ff_audio_options, "");
873 strcpy(asset->ff_video_options, "");
874 asset->audio_data = !load_defaults("audio", text, asset->acodec,
875 asset->ff_audio_options, sizeof(asset->ff_audio_options));
876 asset->video_data = !load_defaults("video", text, asset->vcodec,
877 asset->ff_video_options, sizeof(asset->ff_video_options));
878 format->update_extension();
879 format->close_format_windows();
880 format->update_format();
888 FormatChannels::FormatChannels(int x, int y, FormatTools *format)
889 : BC_TextBox(x, y, 100, 1, format->asset->channels)
891 this->format = format;
894 FormatChannels::~FormatChannels()
898 int FormatChannels::handle_event()
900 format->asset->channels = atol(get_text());
905 FormatToTracks::FormatToTracks(int x, int y, int *output)
906 : BC_CheckBox(x, y, *output, _("Overwrite project with output"))
908 this->output = output;
911 FormatToTracks::~FormatToTracks()
915 int FormatToTracks::handle_event()
917 *output = get_value();
922 FormatMultiple::FormatMultiple(MWindow *mwindow, int x, int y, int *output)
925 (*output == FILE_PER_LABEL) || (*output == FILE_PER_LABEL_FARM),
926 _("Create new file at each label"))
928 this->output = output;
929 this->mwindow = mwindow;
932 FormatMultiple::~FormatMultiple()
936 int FormatMultiple::handle_event()
940 if(mwindow->preferences->use_renderfarm)
941 *output = FILE_PER_LABEL_FARM;
943 *output = FILE_PER_LABEL;
947 if(mwindow->preferences->use_renderfarm)
948 *output = SINGLE_PASS_FARM;
950 *output = SINGLE_PASS;
955 void FormatMultiple::update(int *output)
957 this->output = output;
958 if(*output == FILE_PER_LABEL_FARM ||
959 *output ==FILE_PER_LABEL)