b27409f96ed9e3ef55ee3188c41e22940d4153d6
[goodguy/history.git] / cinelerra-5.0 / cinelerra / formattools.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2010-2013 Adam Williams <broadcast at earthling dot net>
5  * 
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.
10  * 
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.
15  * 
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
19  * 
20  */
21
22 #include "asset.h"
23 #include "bcsignals.h"
24 #include "clip.h"
25 #include "guicast.h"
26 #include "file.h"
27 #include "filesystem.h"
28 #include "formattools.h"
29 #include "language.h"
30 #include "maxchannels.h"
31 #include "mwindow.h"
32 #include "preferences.h"
33 #include "quicktime.h"
34 #include "theme.h"
35 #include "videodevice.inc"
36 #include <string.h>
37 #include <unistd.h>
38 #include <ctype.h>
39
40
41 FormatTools::FormatTools(MWindow *mwindow,
42                                 BC_WindowBase *window, 
43                                 Asset *asset)
44 {
45         this->mwindow = mwindow;
46         this->window = window;
47         this->asset = asset;
48         this->plugindb = mwindow->plugindb;
49
50         aparams_button = 0;
51         vparams_button = 0;
52         aparams_thread = 0;
53         vparams_thread = 0;
54         channels_tumbler = 0;
55         path_textbox = 0;
56         path_button = 0;
57         w = window->get_w();
58         file_entries = 0;
59 }
60
61 FormatTools::~FormatTools()
62 {
63 SET_TRACE
64         delete path_button;
65 SET_TRACE
66         delete path_textbox;
67 SET_TRACE
68         delete format_button;
69 SET_TRACE
70
71         if(aparams_button) delete aparams_button;
72 SET_TRACE
73         if(vparams_button) delete vparams_button;
74 SET_TRACE
75         if(aparams_thread) delete aparams_thread;
76 SET_TRACE
77         if(vparams_thread) delete vparams_thread;
78 SET_TRACE
79         if(channels_tumbler) delete channels_tumbler;
80 SET_TRACE
81         if(file_entries)
82         {
83                 file_entries->remove_all_objects();
84                 delete file_entries;
85         }
86 }
87
88 void FormatTools::create_objects(int &init_x, 
89                                                 int &init_y, 
90                                                 int do_audio,    // Include support for audio
91                                                 int do_video,   // Include support for video
92                                                 int prompt_audio,  // Include checkbox for audio
93                                                 int prompt_video,
94                                                 int prompt_audio_channels,
95                                                 int prompt_video_compression,
96                                                 char *locked_compressor,
97                                                 int recording,
98                                                 int *strategy,
99                                                 int brender)
100 {
101         int x = init_x;
102         int y = init_y;
103
104         this->locked_compressor = locked_compressor;
105         this->recording = recording;
106         this->use_brender = brender;
107         this->do_audio = do_audio;
108         this->do_video = do_video;
109         this->prompt_audio = prompt_audio;
110         this->prompt_audio_channels = prompt_audio_channels;
111         this->prompt_video = prompt_video;
112         this->prompt_video_compression = prompt_video_compression;
113         this->strategy = strategy;
114
115
116         file_entries = new ArrayList<BC_ListBoxItem*>;
117         FileSystem fs;
118         char string[BCTEXTLEN];
119 // Load current directory
120         fs.update(getcwd(string, BCTEXTLEN));
121         for(int i = 0; i < fs.total_files(); i++)
122         {
123                 file_entries->append(
124                         new BC_ListBoxItem(
125                                 fs.get_entry(i)->get_name()));
126         }
127
128 //printf("FormatTools::create_objects 1\n");
129
130 // Modify strategy depending on render farm
131         if(strategy)
132         {
133                 if(mwindow->preferences->use_renderfarm)
134                 {
135                         if(*strategy == FILE_PER_LABEL)
136                                 *strategy = FILE_PER_LABEL_FARM;
137                         else
138                         if(*strategy == SINGLE_PASS)
139                                 *strategy = SINGLE_PASS_FARM;
140                 }
141                 else
142                 {
143                         if(*strategy == FILE_PER_LABEL_FARM)
144                                 *strategy = FILE_PER_LABEL;
145                         else
146                         if(*strategy == SINGLE_PASS_FARM)
147                                 *strategy = SINGLE_PASS;
148                 }
149         }
150
151         if(!recording)
152         {
153                 window->add_subwindow(path_textbox = new FormatPathText(x, y, this));
154                 x += path_textbox->get_w() + 5;
155                 window->add_subwindow(path_button = new BrowseButton(
156                         mwindow,
157                         window,
158                         path_textbox, 
159                         x, 
160                         y, 
161                         asset->path,
162                         _("Output to file"),
163                         _("Select a file to write to:"),
164                         0));
165
166 // Set w for user.
167                 w = MAX(w, 305);
168 //              w = x + path_button->get_w() + 5;
169                 x -= path_textbox->get_w() + 5;
170                 y += 35;
171         }
172         else
173         {
174 //              w = x + 305;
175                 w = 305;
176         }
177
178         window->add_subwindow(format_title = new BC_Title(x, y, _("File Format:")));
179         x += 90;
180         window->add_subwindow(format_text = new BC_TextBox(x, y, 200, 1, 
181                 File::formattostr(asset->format)));
182         x += format_text->get_w();
183 //printf("FormatTools::create_objects %d %p\n", __LINE__, window);
184         window->add_subwindow(format_button = new FormatFormat(x, y, this));
185         format_button->create_objects();
186
187         x = init_x;
188         y += format_button->get_h() + 10;
189         if(do_audio)
190         {
191                 window->add_subwindow(audio_title = new BC_Title(x, y, _("Audio:"), LARGEFONT, RED));
192                 x += 80;
193                 window->add_subwindow(aparams_button = new FormatAParams(mwindow, this, x, y));
194                 x += aparams_button->get_w() + 10;
195                 if(prompt_audio) 
196                 {
197                         window->add_subwindow(audio_switch = new FormatAudio(x, y, this, asset->audio_data));
198                 }
199                 x = init_x;
200                 y += aparams_button->get_h() + 10;
201
202 // Audio channels only used for recording.
203 //              if(prompt_audio_channels)
204 //              {
205 //                      window->add_subwindow(channels_title = new BC_Title(x, y, _("Number of audio channels to record:")));
206 //                      x += 260;
207 //                      window->add_subwindow(channels_button = new FormatChannels(x, y, this));
208 //                      x += channels_button->get_w() + 5;
209 //                      window->add_subwindow(channels_tumbler = new BC_ITumbler(channels_button, 1, MAXCHANNELS, x, y));
210 //                      y += channels_button->get_h() + 20;
211 //                      x = init_x;
212 //              }
213
214 //printf("FormatTools::create_objects 6\n");
215                 aparams_thread = new FormatAThread(this);
216         }
217
218 //printf("FormatTools::create_objects 7\n");
219         if(do_video)
220         {
221
222 //printf("FormatTools::create_objects 8\n");
223                 window->add_subwindow(video_title = new BC_Title(x, y, _("Video:"), LARGEFONT, RED));
224                 x += 80;
225                 if(prompt_video_compression)
226                 {
227                         window->add_subwindow(vparams_button = new FormatVParams(mwindow, this, x, y));
228                         x += vparams_button->get_w() + 10;
229                 }
230
231 //printf("FormatTools::create_objects 9\n");
232                 if(prompt_video)
233                 {
234                         window->add_subwindow(video_switch = new FormatVideo(x, y, this, asset->video_data));
235                         y += video_switch->get_h();
236                 }
237                 else
238                 {
239                         y += vparams_button->get_h();
240                 }
241
242 //printf("FormatTools::create_objects 10\n");
243                 y += 10;
244                 vparams_thread = new FormatVThread(this);
245         }
246
247 //printf("FormatTools::create_objects 11\n");
248
249         x = init_x;
250         if(strategy)
251         {
252                 window->add_subwindow(multiple_files = new FormatMultiple(mwindow, x, y, strategy));
253                 y += multiple_files->get_h() + 10;
254         }
255
256 //printf("FormatTools::create_objects 12\n");
257
258         init_y = y;
259         update_format();
260 }
261
262 void FormatTools::update_driver(int driver)
263 {
264         this->video_driver = driver;
265
266         switch(driver)
267         {
268                 case CAPTURE_DVB:
269                 case VIDEO4LINUX2MPEG:
270 // Just give the user information about how the stream is going to be
271 // stored but don't change the asset.
272 // Want to be able to revert to user settings.
273                         if(asset->format != FILE_MPEG)
274                         {
275                                 format_text->update(_("MPEG stream"));
276                                 asset->format = FILE_MPEG;
277                         }
278                         locked_compressor = 0;
279                         audio_switch->update(1);
280                         video_switch->update(1);
281                         break;
282
283                 case CAPTURE_IEC61883:
284                 case CAPTURE_FIREWIRE:
285                 case CAPTURE_BUZ:
286                 case VIDEO4LINUX2JPEG:
287                 case CAPTURE_JPEG_WEBCAM:
288                         if(asset->format != FILE_AVI &&
289                                 asset->format != FILE_MOV)
290                         {
291                                 format_text->update(MOV_NAME);
292                                 asset->format = FILE_MOV;
293                         }
294                         else
295                                 format_text->update(File::formattostr(asset->format));
296
297                         switch(driver)
298                         {
299                                 case CAPTURE_IEC61883:
300                                 case CAPTURE_FIREWIRE:
301                                         locked_compressor = (char*)QUICKTIME_DVSD;
302                                         strcpy(asset->vcodec, QUICKTIME_DVSD);
303                                         break;
304
305                                 case CAPTURE_BUZ:
306                                 case VIDEO4LINUX2JPEG:
307                                         locked_compressor = (char*)QUICKTIME_MJPA;
308                                         strcpy(asset->vcodec, QUICKTIME_MJPA);
309                                         break;
310
311                                 case CAPTURE_JPEG_WEBCAM:
312                                         locked_compressor = (char*)QUICKTIME_JPEG;
313                                         strcpy(asset->vcodec, QUICKTIME_JPEG);
314                                         break;
315                         }
316
317                         audio_switch->update(asset->audio_data);
318                         video_switch->update(asset->video_data);
319                         break;
320
321
322
323
324
325                 default:
326                         format_text->update(File::formattostr(asset->format));
327                         locked_compressor = 0;
328                         audio_switch->update(asset->audio_data);
329                         video_switch->update(asset->video_data);
330                         break;
331         }
332         close_format_windows();
333 }
334
335 void FormatTools::update_format()
336 {
337         if( do_audio && audio_switch ) {
338                 asset->audio_data = File::supports_audio(asset->format);
339                 audio_switch->update(asset->audio_data);
340                 if( !asset->audio_data )
341                         audio_switch->disable();
342                 else
343                         audio_switch->enable();
344         }
345         if( do_video && video_switch ) {
346                 asset->video_data = File::supports_video(asset->format);
347                 video_switch->update(asset->video_data);
348                 if( !asset->video_data )
349                         video_switch->disable();
350                 else
351                         video_switch->enable();
352         }
353 }
354
355 int FormatTools::handle_event()
356 {
357         return 0;
358 }
359
360 Asset* FormatTools::get_asset()
361 {
362         return asset;
363 }
364
365 void FormatTools::update_extension()
366 {
367         const char *extension = File::get_tag(asset->format);
368 // split multiple extensions
369         ArrayList<const char*> extensions;
370         int len = strlen(extension);
371         const char *extension_ptr = extension;
372         for(int i = 0; i <= len; i++)
373         {
374                 if(extension[i] == '/' || extension[i] == 0)
375                 {
376                         extensions.append(extension_ptr);
377                         extension_ptr = extension + i + 1;
378                 }
379         }
380         
381         if(extensions.size())
382         {
383                 char *ptr = strrchr(asset->path, '.');
384                 if(!ptr)
385                 {
386                         ptr = asset->path + strlen(asset->path);
387                         *ptr = '.';
388                 }
389                 ptr++;
390                 
391                 
392 // test for equivalent extension
393                 int need_extension = 1;
394                 //int extension_len = 0;
395                 for(int i = 0; i < extensions.size() && need_extension; i++)
396                 {
397                         char *ptr1 = ptr;
398                         extension_ptr = extensions.get(i);
399 // test an extension
400                         need_extension = 0;
401                         while(*ptr1 != 0 && *extension_ptr != 0 && *extension_ptr != '/')
402                         {
403                                 if(tolower(*ptr1) != tolower(*extension_ptr))
404                                 {
405                                         need_extension = 1;
406                                         break;
407                                 }
408                                 ptr1++;
409                                 extension_ptr++;
410                         }
411
412                         if(*ptr1 == 0 && 
413                                 *extension_ptr != 0 &&
414                                 *extension_ptr != '/')
415                                 need_extension = 1;
416                 }
417
418 //printf("FormatTools::update_extension %d %d\n", __LINE__, need_extension);
419 // copy extension
420                 if(need_extension) 
421                 {
422                         char *ptr1 = ptr;
423                         extension_ptr = extensions.get(0);
424                         while(*extension_ptr != 0 && *extension_ptr != '/')
425                                 *ptr1++ = *extension_ptr++;
426                         *ptr1 = 0;
427                 }
428
429                 int character1 = ptr - asset->path;
430                 int character2 = strlen(asset->path);
431 //              *(asset->path + character2) = 0;
432                 if(path_textbox) 
433                 {
434                         path_textbox->update(asset->path);
435                         path_textbox->set_selection(character1, character2, character2);
436                 }
437         }
438 }
439
440 void FormatTools::update(Asset *asset, int *strategy)
441 {
442         this->asset = asset;
443         this->strategy = strategy;
444
445         if(path_textbox) 
446                 path_textbox->update(asset->path);
447         format_text->update(File::formattostr(plugindb, asset->format));
448         if(do_audio && audio_switch) audio_switch->update(asset->audio_data);
449         if(do_video && video_switch) video_switch->update(asset->video_data);
450         if(strategy)
451         {
452                 multiple_files->update(strategy);
453         }
454         close_format_windows();
455 }
456
457 void FormatTools::close_format_windows()
458 {
459 // This is done in ~file
460         if(aparams_thread && aparams_thread->running())
461         {
462                 aparams_thread->file->close_window();
463                 aparams_thread->join();
464         }
465         if(vparams_thread && vparams_thread->running())
466         {
467                 vparams_thread->file->close_window();
468                 vparams_thread->join();
469         }
470 }
471
472 int FormatTools::get_w()
473 {
474         return w;
475 }
476
477 void FormatTools::set_w(int w)
478 {
479         this->w = w;
480 }
481
482 void FormatTools::reposition_window(int &init_x, int &init_y)
483 {
484         int x = init_x;
485         int y = init_y;
486
487         if(path_textbox) 
488         {
489                 path_textbox->reposition_window(x, y);
490                 x += path_textbox->get_w() + 5;
491                 path_button->reposition_window(x, y);
492                 x -= path_textbox->get_w() + 5;
493                 y += 35;
494         }
495
496         format_title->reposition_window(x, y);
497         x += 90;
498         format_text->reposition_window(x, y);
499         x += format_text->get_w();
500         format_button->reposition_window(x, y);
501
502         x = init_x;
503         y += format_button->get_h() + 10;
504
505         if(do_audio)
506         {
507                 audio_title->reposition_window(x, y);
508                 x += 80;
509                 aparams_button->reposition_window(x, y);
510                 x += aparams_button->get_w() + 10;
511                 if(prompt_audio) audio_switch->reposition_window(x, y);
512
513                 x = init_x;
514                 y += aparams_button->get_h() + 20;
515                 if(prompt_audio_channels)
516                 {
517                         channels_title->reposition_window(x, y);
518                         x += 260;
519                         channels_button->reposition_window(x, y);
520                         x += channels_button->get_w() + 5;
521                         channels_tumbler->reposition_window(x, y);
522                         y += channels_button->get_h() + 20;
523                         x = init_x;
524                 }
525         }
526
527
528         if(do_video)
529         {
530                 video_title->reposition_window(x, y);
531                 x += 80;
532                 if(prompt_video_compression)
533                 {
534                         vparams_button->reposition_window(x, y);
535                         x += vparams_button->get_w() + 10;
536                 }
537
538                 if(prompt_video)
539                 {
540                         video_switch->reposition_window(x, y);
541                         y += video_switch->get_h();
542                 }
543                 else
544                 {
545                         y += vparams_button->get_h();
546                 }
547
548                 y += 10;
549                 x = init_x;
550         }
551
552         if(strategy)
553         {
554                 multiple_files->reposition_window(x, y);
555                 y += multiple_files->get_h() + 10;
556         }
557
558         init_y = y;
559 }
560
561
562 int FormatTools::set_audio_options()
563 {
564 //      if(video_driver == CAPTURE_DVB)
565 //      {
566 //              return 0;
567 //      }
568
569         if(!aparams_thread->running())
570         {
571                 aparams_thread->start();
572         }
573         else
574         {
575                 aparams_thread->file->raise_window();
576         }
577         return 0;
578 }
579
580 int FormatTools::set_video_options()
581 {
582 //      if(video_driver == CAPTURE_DVB)
583 //      {
584 //              return 0;
585 //      }
586
587         if(!vparams_thread->running())
588         {
589                 vparams_thread->start();
590         }
591         else
592         {
593                 vparams_thread->file->raise_window();
594         }
595
596         return 0;
597 }
598
599
600
601
602
603 FormatAParams::FormatAParams(MWindow *mwindow, FormatTools *format, int x, int y)
604  : BC_Button(x, y, mwindow->theme->get_image_set("wrench"))
605 {
606         this->format = format;
607         set_tooltip(_("Configure audio compression"));
608 }
609
610 FormatAParams::~FormatAParams() 
611 {
612 }
613
614 int FormatAParams::handle_event() 
615 {
616         format->set_audio_options(); 
617         return 1;
618 }
619
620
621
622
623
624 FormatVParams::FormatVParams(MWindow *mwindow, FormatTools *format, int x, int y)
625  : BC_Button(x, y, mwindow->theme->get_image_set("wrench"))
626
627         this->format = format; 
628         set_tooltip(_("Configure video compression"));
629 }
630
631 FormatVParams::~FormatVParams() 
632 {
633 }
634
635 int FormatVParams::handle_event() 
636
637         format->set_video_options(); 
638         return 1;
639 }
640
641
642
643
644
645 FormatAThread::FormatAThread(FormatTools *format)
646  : Thread(1, 0, 0)
647
648         this->format = format; 
649         file = new File;
650         joined = 1;
651 }
652
653 FormatAThread::~FormatAThread() 
654 {
655         join();
656         delete file;
657         file = 0;
658 }
659
660 void FormatAThread::start()
661 {
662         join();
663         joined = 0;
664         Thread::start();
665 }
666
667
668 void FormatAThread::run()
669 {
670         file->get_options(format, 1, 0);
671 }
672
673
674
675
676 FormatVThread::FormatVThread(FormatTools *format)
677  : Thread(1, 0, 0)
678 {
679         this->format = format;
680         file = new File;
681         joined = 1;
682 }
683
684 FormatVThread::~FormatVThread() 
685 {
686         join();
687         delete file;
688         file = 0;
689 }
690
691 void FormatVThread::start()
692 {
693         join();
694         joined = 0;
695         Thread::start();
696 }
697
698 void FormatVThread::run()
699 {
700         file->get_options(format, 0, 1);
701 }
702
703
704
705
706
707 FormatPathText::FormatPathText(int x, int y, FormatTools *format)
708  : BC_TextBox(x, 
709         y, 
710         format->w - 
711                 format->mwindow->theme->get_image_set("wrench")[0]->get_w() - 
712                 x - 10, 
713         1, 
714         format->asset->path) 
715 {
716         this->format = format; 
717 }
718
719 FormatPathText::~FormatPathText() 
720 {
721 }
722 int FormatPathText::handle_event() 
723 {
724 // Suggestions
725         calculate_suggestions(format->file_entries);
726
727
728
729         strcpy(format->asset->path, get_text());
730         format->handle_event();
731
732         return 1;
733 }
734
735
736
737
738 FormatAudio::FormatAudio(int x, int y, FormatTools *format, int default_)
739  : BC_CheckBox(x, 
740         y, 
741         default_, 
742         (char*)(format->recording ? _("Record audio tracks") : _("Render audio tracks")))
743
744         this->format = format; 
745 }
746
747 FormatAudio::~FormatAudio() {}
748 int FormatAudio::handle_event()
749 {
750         format->asset->audio_data = get_value();
751         return 1;
752 }
753
754
755 FormatVideo::FormatVideo(int x, int y, FormatTools *format, int default_)
756  : BC_CheckBox(x, 
757         y, 
758         default_, 
759         (char*)(format->recording ? _("Record video tracks") : _("Render video tracks")))
760 {
761 this->format = format; 
762 }
763
764 FormatVideo::~FormatVideo() {}
765 int FormatVideo::handle_event()
766 {
767         format->asset->video_data = get_value();
768         return 1;
769 }
770
771
772
773
774 FormatFormat::FormatFormat(int x, int y, FormatTools *format)
775  : FormatPopup(format->plugindb, x, y, format->use_brender)
776
777         this->format = format; 
778 }
779
780 FormatFormat::~FormatFormat() 
781 {
782 }
783
784 int FormatFormat::handle_event()
785 {
786         if(get_selection(0, 0) >= 0)
787         {
788                 int new_format = File::strtoformat(format->plugindb, get_selection(0, 0)->get_text());
789 //              if(new_format != format->asset->format)
790                 {
791                         format->asset->format = new_format;
792                         format->format_text->update(get_selection(0, 0)->get_text());
793                         format->update_extension();
794                         format->close_format_windows();
795                         format->update_format();
796                 }
797         }
798         return 1;
799 }
800
801
802
803 FormatChannels::FormatChannels(int x, int y, FormatTools *format)
804  : BC_TextBox(x, y, 100, 1, format->asset->channels) 
805
806         this->format = format; 
807 }
808
809 FormatChannels::~FormatChannels() 
810 {
811 }
812
813 int FormatChannels::handle_event() 
814 {
815         format->asset->channels = atol(get_text());
816         return 1;
817 }
818
819
820 FormatToTracks::FormatToTracks(int x, int y, int *output)
821  : BC_CheckBox(x, y, *output, _("Overwrite project with output"))
822
823         this->output = output; 
824 }
825
826 FormatToTracks::~FormatToTracks() 
827 {
828 }
829
830 int FormatToTracks::handle_event()
831 {
832         *output = get_value();
833         return 1;
834 }
835
836
837 FormatMultiple::FormatMultiple(MWindow *mwindow, int x, int y, int *output)
838  : BC_CheckBox(x, 
839         y, 
840         (*output == FILE_PER_LABEL) || (*output == FILE_PER_LABEL_FARM), 
841         _("Create new file at each label"))
842
843         this->output = output;
844         this->mwindow = mwindow;
845 }
846
847 FormatMultiple::~FormatMultiple() 
848 {
849 }
850
851 int FormatMultiple::handle_event()
852 {
853         if(get_value())
854         {
855                 if(mwindow->preferences->use_renderfarm)
856                         *output = FILE_PER_LABEL_FARM;
857                 else
858                         *output = FILE_PER_LABEL;
859         }
860         else
861         {
862                 if(mwindow->preferences->use_renderfarm)
863                         *output = SINGLE_PASS_FARM;
864                 else
865                         *output = SINGLE_PASS;
866         }
867         return 1;
868 }
869
870 void FormatMultiple::update(int *output)
871 {
872         this->output = output;
873         if(*output == FILE_PER_LABEL_FARM ||
874                 *output ==FILE_PER_LABEL)
875                 set_value(1);
876         else
877                 set_value(0);
878 }
879
880