initial commit
[goodguy/history.git] / cinelerra-5.0 / cinelerra / fileavi.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 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
24 #ifdef USE_AVIFILE
25 #include "avifile.h"
26 #include "creators.h"
27 #include "except.h"
28 #include "fourcc.h"
29 #include "StreamInfo.h"
30 #endif
31
32 #include "clip.h"
33 #include "file.h"
34 #include "fileavi.h"
35 #include "fileavi.inc"
36 #include "language.h"
37 #include "mwindow.inc"
38 #include "vframe.h"
39
40
41 #include <string.h>
42
43
44
45
46
47 #ifdef USE_AVIFILE
48 int FileAVI::avifile_initialized = 0;
49 #endif
50
51
52
53
54 // Status of AVI derivatives:
55 // Arne2 - depends on Kino, DV only
56 // Lavtools - 2 gig limited
57
58
59
60
61
62
63
64
65
66
67
68
69 FileAVI::FileAVI(Asset *asset, File *file)
70  : FileBase(asset, file)
71 {
72         reset();
73 }
74
75 FileAVI::~FileAVI()
76 {
77         close_file();
78 }
79
80 int FileAVI::check_sig(Asset *asset)
81 {
82 // Pick whoever gets the most tracks
83         int score_lavtools = 0;
84         int score_arne2 = 0;
85         int score_arne1 = 0;
86         int score_avifile = 0;
87         int final = 0;
88         int result = 0;
89
90
91
92
93
94         check_sig_lavtools(asset, score_lavtools);
95         check_sig_arne2(asset, score_arne2);
96         check_sig_arne1(asset, score_arne1);
97         check_sig_avifile(asset, score_avifile);
98
99         if(score_lavtools > final) 
100         {
101                 final = score_lavtools;
102                 result = FILE_AVI_LAVTOOLS;
103         }
104         if(score_arne2 > final)
105         {
106                 final = score_arne2;
107                 result = FILE_AVI_ARNE2;
108         }
109         if(score_arne1 > final)
110         {
111                 final = score_arne1;
112                 result = FILE_AVI_ARNE1;
113         }
114         if(score_avifile > final)
115         {
116                 final = score_avifile;
117                 result = FILE_AVI_AVIFILE;
118         }
119
120
121
122
123
124
125
126         return result;
127 }
128
129 int FileAVI::check_sig_arne2(Asset *asset, int &score)
130 {
131         return 0;
132 }
133
134 int FileAVI::check_sig_arne1(Asset *asset, int &score)
135 {
136         return 0;
137 }
138
139 int FileAVI::check_sig_lavtools(Asset *asset, int &score)
140 {
141         return 0;
142 }
143
144 int FileAVI::check_sig_avifile(Asset *asset, int &score)
145 {
146 return 0;
147 #ifdef USE_AVIFILE
148         IAviReadFile *in_fd = 0;
149
150         try
151         {
152                 in_fd = CreateIAviReadFile(asset->path);
153         }
154         catch(FatalError& error)
155         {
156                 if(in_fd) delete in_fd;
157                 return 0;
158         }
159
160         int vtracks = in_fd->VideoStreamCount();
161         int atracks = in_fd->AudioStreamCount();
162
163         delete in_fd;
164         
165         score = vtracks + atracks;
166         return 1;
167 #endif
168         return 0;
169 }
170
171
172 char* FileAVI::vcodec_to_fourcc(const char *input, char *output)
173 {
174 #ifdef USE_AVIFILE
175         initialize_avifile();
176         for(avm::vector<CodecInfo>::iterator i = video_codecs.begin();
177                 i < video_codecs.end();
178                 i++)
179         {
180                 if(i->direction & CodecInfo::Encode)
181                 {
182                         if(!strcasecmp(i->GetName(), input))
183                         {
184                                 memcpy(output, (char*)&i->fourcc, 4);
185                                 output[4] = 0;
186                                 return output;
187                         }
188                 }
189         }
190 #endif
191         
192         output[0] = 0;
193         return output;
194 }
195
196 char* FileAVI::fourcc_to_vcodec(char *input, char *output)
197 {
198 #ifdef USE_AVIFILE
199 // Construct codec item list
200         initialize_avifile();
201         for(avm::vector<CodecInfo>::iterator i = video_codecs.begin();
202                 i < video_codecs.end();
203                 i++)
204         {
205                 if(i->direction & CodecInfo::Encode)
206                 {
207                         if(!memcmp((char*)&i->fourcc, input, 4))
208                         {
209                                 memcpy(output, (char*)&i->fourcc, 4);
210                                 strcpy(output, i->GetName());;
211                                 return output;
212                         }
213                 }
214         }
215         
216         output[0] = 0;
217         return output;
218 #else
219         return input;
220 #endif
221 }
222
223
224 char* FileAVI::acodec_to_fourcc(const char *input, char *output)
225 {
226 #ifdef USE_AVIFILE
227 // Construct codec item list
228         initialize_avifile();
229         for(avm::vector<CodecInfo>::iterator i = audio_codecs.begin();
230                 i < audio_codecs.end();
231                 i++)
232         {
233                 if(i->direction & CodecInfo::Encode)
234                 {
235                         if(!strcasecmp(i->GetName(), input))
236                         {
237                                 memcpy(output, (char*)&i->fourcc, 4);
238                                 output[4] = 0;
239                                 return output;
240                         }
241                 }
242         }
243 #endif
244
245         output[0] = 0;
246         return output;
247 }
248
249 char* FileAVI::fourcc_to_acodec(char *input, char *output)
250 {
251 #ifdef USE_AVIFILE
252 // Construct codec item list
253         initialize_avifile();
254         for(avm::vector<CodecInfo>::iterator i = audio_codecs.begin();
255                 i < audio_codecs.end();
256                 i++)
257         {
258                 if(i->direction & CodecInfo::Encode)
259                 {
260                         if(!memcmp((char*)&i->fourcc, input, 4))
261                         {
262                                 memcpy(output, (char*)&i->fourcc, 4);
263                                 strcpy(output, i->GetName());
264                                 return output;
265                         }
266                 }
267         }
268         
269         output[0] = 0;
270         return output;
271 #else
272         return input;
273 #endif
274 }
275
276
277 void FileAVI::initialize_avifile()
278 {
279 #ifdef USE_AVIFILE
280         if(!avifile_initialized)
281         {
282         BITMAPINFOHEADER bih;
283         bih.biCompression = 0xffffffff;
284         Creators::CreateVideoDecoder(bih, 0, 0);
285
286         WAVEFORMATEX wih;
287         memset(&wih, 0xff, sizeof(WAVEFORMATEX));
288                 Creators::CreateAudioDecoder(&wih, 0);
289                 avifile_initialized = 1;
290         }
291 #endif
292 }
293
294
295 int FileAVI::open_file(int rd, int wr)
296 {
297         if(wr)
298         {
299                 switch(asset->format)
300                 {
301                         case FILE_AVI_LAVTOOLS:
302                                 return open_lavtools_out(asset);
303                                 break;
304
305                         case FILE_AVI_ARNE2:
306                                 return open_arne2_out(asset);
307                                 break;
308
309                         case FILE_AVI_ARNE1:
310                                 return open_arne1_out(asset);
311                                 break;
312
313                         case FILE_AVI_AVIFILE:
314                                 return open_avifile_out(asset);
315                                 break;
316                 }
317         }
318         else
319         if(rd)
320         {
321                 asset->format = check_sig(asset);
322
323
324                 switch(asset->format)
325                 {
326                         case FILE_AVI_LAVTOOLS:
327                                 return open_lavtools_in(asset);
328                                 break;
329
330                         case FILE_AVI_ARNE2:
331                                 return open_arne2_in(asset);
332                                 break;
333
334                         case FILE_AVI_ARNE1:
335                                 return open_arne1_in(asset);
336                                 break;
337
338                         case FILE_AVI_AVIFILE:
339                                 return open_avifile_in(asset);
340                                 break;
341                 }
342         }
343
344         return 0;
345 }
346
347
348
349 int FileAVI::open_avifile_out(Asset *asset)
350 {
351 #ifdef USE_AVIFILE
352         try
353         {
354                 out_fd = CreateIAviWriteFile(asset->path);
355         }
356         catch(FatalError& error)
357         {
358                 error.Print();
359                 close_file();
360                 return 1;
361         }
362
363         if(asset->video_data)
364         {
365                 out_color_model = get_best_colormodel(-1, -1);
366                 out_bitmap_info = new BitmapInfo(asset->width, asset->height, 
367                         cmodel_bc_to_avi(out_color_model));
368                 for(int i = 0; i < asset->layers && i < MAX_STREAMS; i++)
369                 {
370                         vstream_out[i] = out_fd->AddVideoStream(*(uint32_t*)asset->vcodec, 
371                                 out_bitmap_info, 
372                                 int(1000000.0 / asset->frame_rate));
373                 }
374         }
375
376         if(asset->audio_data)
377         {
378                 WAVEFORMATEX wfm;
379                 wfm.wFormatTag = 1; // PCM
380                 wfm.nChannels = asset->channels;
381                 wfm.nSamplesPerSec = asset->sample_rate;
382                 wfm.nAvgBytesPerSec = 2 * asset->sample_rate * asset->channels;
383                 wfm.nBlockAlign = 2 * asset->channels;
384                 wfm.wBitsPerSample = 16;
385                 wfm.cbSize = 0;
386
387                 for(int i = 0; i < asset->channels && i < MAX_STREAMS; i++)
388                 {
389                         astream_out[i] = out_fd->AddStream(AviStream::Audio,
390                                 &wfm, 
391                                 sizeof(wfm),
392                                 1,                   // uncompressed PCM data
393                                 wfm.nAvgBytesPerSec, // bytes/sec
394                                 wfm.nBlockAlign);    // bytes/sample
395                 }
396         }
397
398         return 0;
399 #endif
400         return 1;
401 }
402
403 int FileAVI::open_arne2_out(Asset *asset)
404 {
405         
406         return 0;
407 }
408
409 int FileAVI::open_arne1_out(Asset *asset)
410 {
411         return 0;
412 }
413
414 int FileAVI::open_lavtools_out(Asset *asset)
415 {
416         return 0;
417 }
418
419         
420         
421         
422
423
424 int FileAVI::open_avifile_in(Asset *asset)
425 {
426 #ifdef USE_AVIFILE
427         try
428         {
429                 in_fd = CreateIAviReadFile(asset->path);
430         }
431         catch(FatalError& error)
432         {
433                 error.Print();
434                 close_file();
435                 return 1;
436         }
437
438         asset->layers = in_fd->VideoStreamCount();
439         if(asset->layers)
440         {
441                 for(int i = 0; i < asset->layers && i < MAX_STREAMS; i++)
442                 {
443                         vstream_in[i] = in_fd->GetStream(i, IAviReadStream::Video);
444                         vstream_in[i]->StartStreaming();
445                         vstream_in[i]->GetDecoder()->SetDestFmt(24);
446                         vstream_in[i]->Seek(0);
447 //printf("FileAVI::open_file %d %p\n", i, vstream[i]);
448                 }
449
450                 StreamInfo *stream_info = vstream_in[0]->GetStreamInfo();
451                 asset->video_data = 1;
452                 if(!asset->frame_rate)
453                         asset->frame_rate = (double)1 / vstream_in[0]->GetFrameTime();
454                 asset->video_length = stream_info->GetStreamFrames();
455                 BITMAPINFOHEADER bh;
456                 vstream_in[0]->GetVideoFormatInfo(&bh, sizeof(bh));
457                 asset->width = bh.biWidth;
458                 asset->height = bh.biHeight;
459
460                 uint32_t fourcc = stream_info->GetFormat();
461                 asset->vcodec[0] = ((char*)&fourcc)[0];
462                 asset->vcodec[1] = ((char*)&fourcc)[1];
463                 asset->vcodec[2] = ((char*)&fourcc)[2];
464                 asset->vcodec[3] = ((char*)&fourcc)[3];
465                 source_cmodel = BC_RGB888;
466                 delete stream_info;
467         }
468
469         asset->audio_data = in_fd->AudioStreamCount();
470
471         if(asset->audio_data)
472         {
473                 char *extinfo;
474
475                 for(int i = 0; i < 1 && i < MAX_STREAMS; i++)
476                 {
477                         astream_in[i] = in_fd->GetStream(i, IAviReadStream::Audio);
478                         astream_in[i]->StartStreaming();
479                 }
480
481                 StreamInfo *stream_info = astream_in[0]->GetStreamInfo();
482                 asset->channels = stream_info->GetAudioChannels();
483                 if(asset->sample_rate == 0)
484                         asset->sample_rate = stream_info->GetAudioSamplesPerSec();
485                 asset->bits = MAX(16, stream_info->GetAudioBitsPerSample());
486                 asset->audio_length = stream_info->GetStreamFrames();
487                 delete stream_info;
488         }
489 asset->dump();
490         return 0;
491 #endif
492         return 1;
493 }
494
495 int FileAVI::open_arne2_in(Asset *asset)
496 {
497         return 0;
498 }
499
500 int FileAVI::open_arne1_in(Asset *asset)
501 {
502         return 0;
503 }
504
505 int FileAVI::open_lavtools_in(Asset *asset)
506 {
507         return 0;
508 }
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527 int FileAVI::close_file()
528 {
529 #ifdef USE_AVIFILE
530         if(in_fd) delete in_fd;
531         if(out_fd) delete out_fd;
532         if(out_bitmap_info) delete out_bitmap_info;
533 #endif
534         if(temp_audio) delete [] temp_audio;
535         reset();
536         return 0;
537 }
538
539 int FileAVI::cmodel_bc_to_avi(int input)
540 {
541 #ifdef USE_AVIFILE
542         switch(input)
543         {
544                 case BC_YUV422:
545                         return fccYUY2;
546                         break;
547
548                 case BC_YUV420P:
549                         return fccYV12;
550                         break;
551         }
552 #endif
553         return 24;
554 }
555
556 void FileAVI::reset()
557 {
558 #ifdef USE_AVIFILE
559         in_fd = 0;
560         out_fd = 0;
561         out_bitmap_info = 0;
562 #endif
563         temp_audio = 0;
564         temp_allocated = 0;
565 }
566
567 int FileAVI::get_best_colormodel(int driver, int colormodel)
568 {
569         if(colormodel > -1)
570         {
571                 return colormodel;
572         }
573         else
574         {
575                 
576                 return BC_RGB888;
577         }
578 }
579
580
581 void FileAVI::get_parameters(BC_WindowBase *parent_window, 
582                 Asset *asset, 
583                 BC_WindowBase* &format_window,
584                 int audio_options,
585                 int video_options,
586                 const char *locked_compressor)
587 {
588         if(audio_options)
589         {
590                 AVIConfigAudio *window = new AVIConfigAudio(parent_window, asset);
591                 format_window = window;
592                 window->create_objects();
593                 window->run_window();
594                 delete window;
595         }
596         else
597         if(video_options)
598         {
599 //printf("FileAVI::get_parameters 1\n");
600                 AVIConfigVideo *window = new AVIConfigVideo(parent_window,
601                         asset,
602                         locked_compressor);
603                 format_window = window;
604                 window->create_objects();
605                 window->run_window();
606                 delete window;
607         }
608 }
609
610 int FileAVI::set_audio_position(int64_t x)
611 {
612 #ifdef USE_AVIFILE
613 // quicktime sets positions for each track seperately so store position in audio_position
614         if(x >= 0 && x < asset->audio_length)
615                 return astream_in[file->current_layer]->Seek(x);
616 #endif
617         return 1;
618 }
619
620 int FileAVI::set_video_position(int64_t x)
621 {
622 #ifdef USE_AVIFILE
623         if(x >= 0 && x < asset->video_length)
624                 return vstream_in[file->current_layer]->Seek(x);
625 #endif
626         return 1;
627 }
628
629 int FileAVI::read_samples(double *buffer, int64_t len)
630 {
631 #ifdef USE_AVIFILE
632         Unsigned samples_read, bytes_read;
633
634 printf("FileAVI::read_samples 1\n");
635         if(temp_audio && temp_allocated < len * asset->bits / 8 * asset->channels)
636         {
637                 delete [] temp_audio;
638                 temp_allocated = 0;
639         }
640         if(!temp_allocated)
641         {
642                 temp_allocated = len * asset->bits / 8 * asset->channels;
643                 temp_audio = new unsigned char[temp_allocated];
644         }
645
646         astream_in[0]->ReadFrames((void*)temp_audio, 
647                 (unsigned int)temp_allocated,
648                 (unsigned int)len,
649                 samples_read, 
650                 bytes_read);
651         
652 // Extract single channel
653         switch(asset->bits)
654         {
655                 case 16:
656                 {
657                         int16_t *temp_int16 = (int16_t*)temp_audio;
658                         for(int i = 0, j = file->current_channel; 
659                                 i < len;
660                                 i++, j += asset->channels)
661                         {
662                                 buffer[i] = (double)temp_int16[j] / 32767;
663                         }
664                         break;
665                 }
666         }
667
668 #endif
669
670
671         return 0;
672 }
673
674 int FileAVI::read_frame(VFrame *frame)
675 {
676         int result = 0;
677
678 #ifdef USE_AVIFILE
679         vstream_in[file->current_layer]->ReadFrame();
680         CImage *temp_image = vstream_in[file->current_layer]->GetFrame();
681 //printf("FileAVI::read_frame 1 %d %d\n", source_cmodel, frame->get_color_model());
682         switch(source_cmodel)
683         {
684                 case BC_RGB888:
685                         if(frame->get_color_model() == BC_RGB888)
686                                 bcopy(temp_image->Data(), 
687                                         frame->get_data(), 
688                                         VFrame::calculate_data_size(asset->width, 
689                                                 asset->height, 
690                                                 -1, 
691                                                 BC_RGB888));
692                         break;
693         }
694 #endif
695         return result;
696 }
697
698 int64_t FileAVI::compressed_frame_size()
699 {
700         int result = 0;
701         return result;
702 }
703
704 int FileAVI::read_compressed_frame(VFrame *buffer)
705 {
706         int64_t result = 0;
707
708         return result;
709 }
710
711 int FileAVI::write_compressed_frame(VFrame *buffer)
712 {
713         int result = 0;
714
715         return result;
716 }
717
718 int FileAVI::write_frames(VFrame ***frames, int len)
719 {
720         return 0;
721 }
722
723
724 int FileAVI::write_samples(double **buffer, int64_t len)
725 {
726         return 0;
727 }
728
729
730
731
732
733 AVIConfigAudio::AVIConfigAudio(BC_WindowBase *parent_window, Asset *asset)
734  : BC_Window(PROGRAM_NAME ": Audio compression",
735         parent_window->get_abs_cursor_x(1),
736         parent_window->get_abs_cursor_y(1),
737         calculate_w(asset->format),
738         calculate_h(asset->format))
739 {
740         this->parent_window = parent_window;
741         this->asset = asset;
742 }
743
744 AVIConfigAudio::~AVIConfigAudio()
745 {
746 }
747
748 int AVIConfigAudio::calculate_w(int format)
749 {
750         switch(format)
751         {
752                 case FILE_AVI_AVIFILE: return 400; break;
753                 case FILE_AVI_ARNE2: return 250; break;
754         }
755         return 0;
756 }
757
758 int AVIConfigAudio::calculate_h(int format)
759 {
760         switch(format)
761         {
762                 case FILE_AVI_AVIFILE: return 200; break;
763                 case FILE_AVI_ARNE2: return 100; break;
764         }
765         return 0;
766 }
767
768 void AVIConfigAudio::create_objects()
769 {
770         switch(asset->format)
771         {
772 #ifdef USE_AVIFILE
773                 case FILE_AVI_AVIFILE:
774                 {
775                         generate_codeclist();
776
777                         int x = 10, y = 10;
778                         BC_Title *title;
779                         add_subwindow(title = new BC_Title(x, y, _("Codec: ")));
780                         list = new AVIACodecList(this, x, y);
781                         list->create_objects();
782                         y += list->get_h();
783                         break;
784                 }
785 #endif
786
787                 case FILE_AVI_ARNE2:
788                         add_subwindow(new BC_Title(10, 10, _("Compressor: 16 bit PCM")));
789                         break;
790         }
791
792         add_subwindow(new BC_OKButton(this));
793 }
794
795 int AVIConfigAudio::close_event()
796 {
797         return 1;
798 }
799
800 int AVIConfigAudio::generate_codeclist()
801 {
802         FileAVI::initialize_avifile();
803         codec_items.remove_all_objects();
804
805         switch(asset->format)
806         {
807 #ifdef USE_AVIFILE
808                 case FILE_AVI_AVIFILE:
809                         for(avm::vector<CodecInfo>::iterator i = audio_codecs.begin();
810                                 i < audio_codecs.end();
811                                 i++)
812                         {
813                                 if(i->direction & CodecInfo::Encode)
814                                 {
815                                         codec_items.append(new BC_ListBoxItem((char*)i->GetName()));
816                                 }
817                         }
818                         break;
819 #endif
820         }
821
822         return 0;
823 }
824
825 void AVIConfigAudio::update_codecs()
826 {
827         
828 }
829
830
831
832
833
834
835
836
837
838 AVIACodecList::AVIACodecList(AVIConfigAudio *gui, int x, int y)
839  : BC_PopupTextBox(gui,
840                 &gui->codec_items,
841                 FileAVI::fourcc_to_acodec(gui->asset->acodec, gui->string),
842                 x, 
843                 y,
844                 200,
845                 400)
846 {
847         this->gui = gui;
848 }
849
850 AVIACodecList::~AVIACodecList()
851 {
852 }
853
854 int AVIACodecList::handle_event()
855 {
856         strcpy(gui->asset->acodec, 
857                 FileAVI::acodec_to_fourcc(get_text(), gui->string));
858         return 1;
859 }
860
861
862
863
864
865 AVIConfigVideo::AVIConfigVideo(BC_WindowBase *parent_window, 
866                 Asset *asset, 
867                 const char *locked_compressor)
868  : BC_Window(PROGRAM_NAME ": Video Compression",
869         parent_window->get_abs_cursor_x(1),
870         parent_window->get_abs_cursor_y(1),
871         calculate_w(asset->format),
872         calculate_h(asset->format))
873 {
874         this->parent_window = parent_window;
875         this->asset = asset;
876         this->locked_compressor = locked_compressor;
877         reset();
878 }
879
880 AVIConfigVideo::~AVIConfigVideo()
881 {
882         codec_items.remove_all_objects();
883         attribute_items[0].remove_all_objects();
884         attribute_items[1].remove_all_objects();
885 }
886
887 void AVIConfigVideo::reset()
888 {
889         attributes = 0;
890         attribute = 0;
891 }
892
893 int AVIConfigVideo::calculate_w(int format)
894 {
895         switch(format)
896         {
897                 case FILE_AVI_AVIFILE: return 400;
898                 case FILE_AVI_ARNE2: return 250;
899         }
900         return 0;
901 }
902
903 int AVIConfigVideo::calculate_h(int format)
904 {
905         switch(format)
906         {
907                 case FILE_AVI_AVIFILE: return 320;
908                 case FILE_AVI_ARNE2: return 100;
909         }
910         return 0;
911 }
912
913 void AVIConfigVideo::create_objects()
914 {
915         switch(asset->format)
916         {
917 #ifdef USE_AVIFILE
918                 case FILE_AVI_AVIFILE:
919                 {
920                         generate_codeclist();
921                         generate_attributelist();
922
923                         int x = 10, y = 10, x1 = 90;
924                         BC_Title *title;
925                         add_subwindow(title = new BC_Title(x, y, _("Codec: ")));
926                         list = new AVIVCodecList(this, x1, y);
927                         list->create_objects();
928                         y += list->get_h() + 5;
929
930                         add_subwindow(title = new BC_Title(x, y, _("Attributes:")));
931                         add_subwindow(attributes = new AVIVAttributeList(this, x1, y));
932                         y += attributes->get_h() + 5;
933
934                         add_subwindow(new BC_Title(x, y, _("Value:")));
935                         add_subwindow(attribute = new AVIVAttribute(this, x1, y));
936                         break;
937                 }
938 #endif
939
940                 case FILE_AVI_ARNE2:
941                         add_subwindow(new BC_Title(10, 10, _("Compressor: Consumer DV")));
942                         break;
943         }
944
945         add_subwindow(new BC_OKButton(this));
946 }
947
948 int AVIConfigVideo::close_event()
949 {
950         return 1;
951 }
952
953 int AVIConfigVideo::generate_codeclist()
954 {
955         FileAVI::initialize_avifile();
956         switch(asset->format)
957         {
958                 case FILE_AVI_AVIFILE:
959 #ifdef USE_AVIFILE
960 // Construct codec item list
961                         for(avm::vector<CodecInfo>::iterator i = video_codecs.begin();
962                                 i < video_codecs.end();
963                                 i++)
964                         {
965                                 if(i->direction & CodecInfo::Encode)
966                                 {
967                                         codec_items.append(new BC_ListBoxItem((char*)i->GetName()));
968                                 }
969                         }
970 #endif
971                         break;
972         }
973
974         return 0;
975 }
976
977 void AVIConfigVideo::generate_attributelist()
978 {
979 #ifdef USE_AVIFILE
980 // Remember selection number
981         int selection_number = attributes ? attributes->get_selection_number(0, 0) : -1;
982         attribute_items[0].remove_all_objects();
983         attribute_items[1].remove_all_objects();
984         FileAVI::initialize_avifile();
985
986         for(avm::vector<CodecInfo>::iterator i = video_codecs.begin();
987                 i < video_codecs.end();
988                 i++)
989         {
990                 if(!memcmp((char*)&i->fourcc, asset->vcodec, 4))
991                 {
992                         avm::vector<AttributeInfo>& attributes = i->encoder_info;
993
994                         for(avm::vector<AttributeInfo>::const_iterator j = attributes.begin();
995                                 j != attributes.end();
996                                 j++)
997                         {
998                                 char *name = (char*)j->GetName();
999                                 char value[BCTEXTLEN];
1000                                 value[0] = 0;
1001
1002 //printf("AVIConfigVideo::generate_attributelist %d\n", j->kind);
1003                                 switch(j->kind)
1004                                 {
1005                                         case AttributeInfo::Integer:
1006                                         {
1007                                                 int temp = 0;
1008                                                 Creators::GetCodecAttr(*i, name, temp);
1009                                                 sprintf(value, "%d", temp);
1010                                                 break;
1011                                         }
1012
1013                                         case AttributeInfo::Select:
1014                                         {
1015                                                 int temp = 0;
1016                                                 Creators::GetCodecAttr(*i, name, temp);
1017                                                 sprintf(value, "%d ( %s )", temp, j->options[temp].c_str());
1018                                                 break;
1019                                         }
1020
1021                                         case AttributeInfo::String:
1022                                         {
1023                                                 const char * temp = 0;
1024                                                 Creators::GetCodecAttr(*i, name, &temp);
1025                                                 if(temp) strncpy(value, temp, BCTEXTLEN);
1026                                                 break;
1027                                 }
1028                                 }
1029
1030                                 attribute_items[0].append(new BC_ListBoxItem(name));
1031                                 attribute_items[1].append(new BC_ListBoxItem(value));
1032
1033                                 int current_number = j - attributes.begin();
1034                                 if(current_number == selection_number)
1035                                 {
1036                                         attribute_items[0].values[current_number]->set_selected(1);
1037                                         attribute_items[1].values[current_number]->set_selected(1);
1038                                 }
1039                         }
1040                 }
1041         }
1042 #endif
1043 }
1044
1045 const char* AVIConfigVideo::get_current_attribute_text()
1046 {
1047         BC_ListBoxItem *item = attributes->get_selection(0, 0);
1048
1049         if(item)
1050         {
1051                 return item->get_text();
1052         }
1053         else
1054                 return "";
1055 }
1056
1057 const char* AVIConfigVideo::get_current_attribute_value()
1058 {
1059         BC_ListBoxItem *item = attributes->get_selection(1, 0);
1060
1061         if(item)
1062         {
1063                 return item->get_text();
1064         }
1065         else
1066                 return "";
1067 }
1068
1069 void AVIConfigVideo::set_current_attribute(const char *text)
1070 {
1071 #ifdef USE_AVIFILE
1072         int number = attributes->get_selection_number(0, 0);
1073
1074         if(number >= 0)
1075         {
1076                 FileAVI::initialize_avifile();
1077
1078                 for(avm::vector<CodecInfo>::iterator i = video_codecs.begin();
1079                         i < video_codecs.end();
1080                         i++)
1081                 {
1082                         if(!memcmp((char*)&i->fourcc, asset->vcodec, 4))
1083                         {
1084                                 avm::vector<AttributeInfo>& attributes = i->encoder_info;
1085                                 AttributeInfo& attribute = attributes[number];
1086
1087                                 switch(attribute.kind)
1088                                 {
1089                                         case AttributeInfo::Integer:
1090                                                 Creators::SetCodecAttr(*i, attribute.GetName(), atol(text));
1091                                                 break;
1092
1093                                         case AttributeInfo::Select:
1094                                                 Creators::SetCodecAttr(*i, attribute.GetName(), atol(text));
1095                                                 break;
1096
1097                                         case AttributeInfo::String:
1098                                                 Creators::SetCodecAttr(*i, attribute.GetName(), text);
1099                                                 break;
1100                                 }
1101                         }
1102                 }
1103
1104
1105                 update_attribute(1);
1106         }
1107 #endif
1108 }
1109
1110
1111
1112 void AVIConfigVideo::update_attribute(int recursive)
1113 {
1114         generate_attributelist();
1115         attributes->update(attribute_items,
1116                                                 0,
1117                                                 0,
1118                                                 2,
1119                                                 attributes->get_xposition(),
1120                                                 attributes->get_yposition(),
1121                                                 0,
1122                                                 1);
1123
1124         if(!recursive) attribute->update(get_current_attribute_value());
1125 }
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135 AVIVCodecList::AVIVCodecList(AVIConfigVideo *gui, int x, int y)
1136  : BC_PopupTextBox(gui,
1137                 &gui->codec_items,
1138                 FileAVI::fourcc_to_vcodec(gui->asset->vcodec, gui->string),
1139                 x,
1140                 y,
1141                 280,
1142                 400)
1143 {
1144         this->gui = gui;
1145 }
1146
1147 AVIVCodecList::~AVIVCodecList()
1148 {
1149 }
1150
1151 int AVIVCodecList::handle_event()
1152 {
1153         strcpy(gui->asset->vcodec, FileAVI::vcodec_to_fourcc(get_text(), gui->string));
1154         gui->update_attribute(0);
1155         return 1;
1156 }
1157
1158
1159
1160 AVIVAttributeList::AVIVAttributeList(AVIConfigVideo *gui, int x, int y)
1161  : BC_ListBox(x,
1162                 y,
1163                 300,
1164                 200,
1165                 LISTBOX_TEXT,
1166                 gui->attribute_items,
1167                 0,
1168                 0,
1169                 2)
1170 {
1171         this->gui = gui;
1172 }
1173
1174 int AVIVAttributeList::handle_event()
1175 {
1176         gui->update_attribute(0);
1177         return 1;
1178 }
1179
1180 int AVIVAttributeList::selection_changed()
1181 {
1182         gui->update_attribute(0);
1183         return 1;
1184 }
1185
1186
1187
1188
1189 AVIVAttribute::AVIVAttribute(AVIConfigVideo *gui, int x, int y)
1190  : BC_TextBox(x, y, 300, 1, gui->get_current_attribute_value())
1191 {
1192         this->gui = gui;
1193 }
1194
1195 int AVIVAttribute::handle_event()
1196 {
1197         gui->set_current_attribute(get_text());
1198         return 1;
1199 }
1200
1201
1202