prevent popup deactivation while button_down
[goodguy/history.git] / cinelerra-5.0 / cinelerra / fileflac.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 <errno.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include "FLAC/stream_decoder.h"
28 #include "FLAC/stream_encoder.h"
29
30 #define IS_FILEFLAC
31 #include "asset.h"
32 #include "bcsignals.h"
33 #include "bitspopup.h"
34 #include "byteorder.h"
35 #include "clip.h"
36 #include "file.h"
37 #include "fileflac.h"
38 #include "filesystem.h"
39 #include "guicast.h"
40 #include "language.h"
41 #include "mwindow.inc"
42
43
44 FileFLAC::FileFLAC(Asset *asset, File *file)
45  : FileBase(asset, file)
46 {
47         reset_parameters();
48         if(asset->format == FILE_UNKNOWN) asset->format = FILE_FLAC;
49         asset->byte_order = 0;
50 }
51
52 FileFLAC::~FileFLAC()
53 {
54         close_file();
55 }
56
57 void FileFLAC::get_parameters(BC_WindowBase *parent_window, 
58         Asset *asset, 
59         BC_WindowBase* &format_window,
60         int audio_options,
61         int video_options)
62 {
63         if(audio_options)
64         {
65                 FLACConfigAudio *window = new FLACConfigAudio(parent_window, asset);
66                 format_window = window;
67                 window->create_objects();
68                 window->run_window();
69                 delete window;
70         }
71 }
72
73
74
75 int FileFLAC::check_sig(Asset *asset, char *test)
76 {
77         if(test[0] == 'f' &&
78                 test[1] == 'L' &&
79                 test[2] == 'a' &&
80                 test[3] == 'C')
81         {
82                 return 1;
83         }
84         else
85         {
86                 return 0;
87         }
88 }
89
90 int FileFLAC::reset_parameters_derived()
91 {
92         pcm_history = 0;
93         flac_decode = 0;
94         flac_encode = 0;
95         temp_buffer = 0;
96         temp_allocated = 0;
97         temp_channels = 0;
98         initialized = 0;
99         is_reading = 0;
100         return 0;
101 }
102
103
104 static FLAC__StreamDecoderWriteStatus write_callback(
105         const FLAC__StreamDecoder *decoder, 
106         const FLAC__Frame *frame, 
107         const FLAC__int32 * const buffer[], 
108         void *client_data)
109 {
110         FileFLAC *ptr = (FileFLAC*)client_data;
111
112         if(!ptr->initialized)
113         {
114                 ptr->initialized = 1;
115                 ptr->asset->audio_data = 1;
116                 ptr->asset->channels = FLAC__stream_decoder_get_channels(ptr->flac_decode);
117                 ptr->asset->bits = FLAC__stream_decoder_get_bits_per_sample(ptr->flac_decode);
118                 ptr->asset->sample_rate = FLAC__stream_decoder_get_sample_rate(ptr->flac_decode);
119                 ptr->asset->audio_length = FLAC__stream_decoder_get_total_samples(ptr->flac_decode);
120                 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
121         }
122         else
123         if(ptr->is_reading)
124         {
125                 int fragment = FLAC__stream_decoder_get_blocksize(ptr->flac_decode);
126                 ptr->samples_read += fragment;
127 //printf("write_callback 2 %d\n", fragment);
128
129                 if(ptr->temp_allocated < fragment)
130                 {
131                         if(ptr->temp_buffer)
132                         {
133                                 for(int i = 0; i < ptr->temp_channels; i++)
134                                 {
135                                         delete [] ptr->temp_buffer[i];
136                                 }
137                                 delete [] ptr->temp_buffer;
138                         }
139
140                         ptr->temp_channels = ptr->asset->channels;
141                         ptr->temp_buffer = new int32_t*[ptr->temp_channels];
142                         for(int i = 0; i < ptr->temp_channels; i++)
143                         {
144                                 ptr->temp_buffer[i] = new int32_t[fragment];
145                         }
146                         ptr->temp_allocated = fragment;
147                 }
148
149                 float audio_max = (float)0x7fff;
150                 if(FLAC__stream_decoder_get_bits_per_sample(ptr->flac_decode) == 24)
151                         audio_max = (float)0x7fffff;
152
153                 int nchannels = FLAC__stream_decoder_get_channels(ptr->flac_decode);
154                 if( nchannels > ptr->temp_channels ) nchannels = ptr->temp_channels;
155                 for(int j = 0; j < nchannels; j++)
156                 {
157                         float *dst = (float*)ptr->temp_buffer[j];
158                         int32_t *src = (int32_t*)buffer[j];
159                         for(int i = 0; i < fragment; i++)
160                         {
161                                 *dst++ = (float)*src++ / audio_max;
162                         }
163                 }
164
165                 ptr->append_history((float**)ptr->temp_buffer, fragment);
166
167 //printf("write_callback 3\n");
168                 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
169         }
170
171         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
172 }
173
174
175 static void metadata_callback(const FLAC__StreamDecoder *decoder, 
176         const FLAC__StreamMetadata *metadata, 
177         void *client_data)
178 {
179 //      printf("metadata_callback\n");
180 }
181
182 static void error_callback(const FLAC__StreamDecoder *decoder, 
183         FLAC__StreamDecoderErrorStatus status, 
184         void *client_data)
185 {
186 //      printf("error_callback\n");
187 }
188
189
190
191
192
193 int FileFLAC::open_file(int rd, int wr)
194 {
195         int result = 0;
196
197         if(rd)
198         {
199                 file_bytes = FileSystem::get_size(asset->path);
200                 flac_decode = FLAC__stream_decoder_new();
201                 FLAC__stream_decoder_init_file(flac_decode,
202                         asset->path,
203                         write_callback,
204                         metadata_callback,
205                         error_callback,
206                         this);
207
208                 initialized = 0;
209                 while(!initialized)
210                 {
211                         if(!FLAC__stream_decoder_process_single(flac_decode)) break;
212                 }
213
214                 if(!initialized) 
215                         result = 1;
216                 else
217                 {
218                         FLAC__stream_decoder_seek_absolute(flac_decode, 0);
219                 }
220         }
221
222         if(wr)
223         {
224                 flac_encode = FLAC__stream_encoder_new();
225                 FLAC__stream_encoder_set_channels(flac_encode, asset->channels);
226                 FLAC__stream_encoder_set_bits_per_sample(flac_encode, asset->bits);
227                 FLAC__stream_encoder_set_sample_rate(flac_encode, asset->sample_rate);
228                 FLAC__stream_encoder_init_file(flac_encode, 
229                         asset->path, 
230                         0, 
231                         0);
232         }
233
234         return result;
235 }
236
237
238 int FileFLAC::close_file_derived()
239 {
240         if(flac_decode)
241         {
242                 FLAC__stream_decoder_finish(flac_decode);
243                 FLAC__stream_decoder_delete(flac_decode);
244         }
245         
246         if(flac_encode)
247         {
248                 FLAC__stream_encoder_finish(flac_encode);
249                 FLAC__stream_encoder_delete(flac_encode);
250         }
251
252
253         if(temp_buffer)
254         {
255                 for(int i = 0; i < temp_channels; i++)
256                         delete [] temp_buffer[i];
257                 delete [] temp_buffer;
258         }
259         return 0;
260 }
261
262
263 int FileFLAC::write_samples(double **buffer, int64_t len)
264 {
265 // Create temporary buffer of samples
266         if(temp_allocated < len)
267         {
268                 if(temp_buffer)
269                 {
270                         for(int i = 0; i < asset->channels; i++)
271                         {
272                                 delete [] temp_buffer[i];
273                         }
274                         delete [] temp_buffer;
275                 }
276
277                 temp_buffer = new int32_t*[asset->channels];
278                 for(int i = 0; i < asset->channels; i++)
279                 {
280                         temp_buffer[i] = new int32_t[len];
281                 }
282                 temp_allocated = len;
283         }
284
285         float audio_max = (float)0x7fff;
286
287         switch(asset->bits)
288         {
289                 case 24:
290                         audio_max = (float)0x7fffff;
291                         break;
292         }
293
294         for(int i = 0; i < asset->channels; i++)
295         {
296                 int32_t *dst = temp_buffer[i];
297                 double *src = buffer[i];
298                 for(int j = 0; j < len; j++)
299                 {
300                         double sample = *src++ * audio_max;
301                         CLAMP(sample, -audio_max, audio_max);
302                         *dst++ = (int32_t)sample;
303                 }
304         }
305         
306         int result = FLAC__stream_encoder_process(flac_encode, 
307                 temp_buffer, 
308                 len);
309
310         return !result;
311 }
312
313 int FileFLAC::read_samples(double *buffer, int64_t len)
314 {
315         int result = 0;
316         update_pcm_history(len);
317         
318         if(decode_end != decode_start)
319         {
320                 FLAC__stream_decoder_seek_absolute(flac_decode, decode_start);
321                 decode_end = decode_start;
322         }
323
324         samples_read = 0;
325         is_reading = 1;
326
327         while(samples_read < decode_len)
328         {
329                 FLAC__uint64 position;
330                 FLAC__stream_decoder_get_decode_position(flac_decode, &position);
331 // EOF
332                 if((int64_t)position >= file_bytes) break;
333                 if(!FLAC__stream_decoder_process_single(flac_decode)) {
334                         result = 1;
335                         break;
336                 }
337         }
338         is_reading = 0;
339
340         if(!result)
341         {
342                 read_history(buffer, 
343                         file->current_sample, 
344                         file->current_channel,
345                         len);
346         }
347
348 //printf("FileFLAC::read_samples 10\n");
349         return result;
350 }
351
352
353
354
355
356
357
358
359
360
361 FLACConfigAudio::FLACConfigAudio(BC_WindowBase *parent_window, 
362         Asset *asset)
363  : BC_Window(_(PROGRAM_NAME ": Audio Compression"),
364         parent_window->get_abs_cursor_x(1),
365         parent_window->get_abs_cursor_y(1),
366         350,
367         170,
368         -1,
369         -1,
370         0,
371         0,
372         1)
373 {
374         this->parent_window = parent_window;
375         this->asset = asset;
376 }
377
378 FLACConfigAudio::~FLACConfigAudio()
379 {
380 }
381
382 void FLACConfigAudio::create_objects()
383 {
384         int x = 10, y = 10;
385         lock_window("FLACConfigAudio::create_objects");
386         bits_popup = new BitsPopup(this, x, y, &asset->bits, 0, 0, 0, 0, 0);
387         bits_popup->create_objects();
388
389         add_subwindow(new BC_OKButton(this));
390         show_window(1);
391         unlock_window();
392 }
393
394 int FLACConfigAudio::close_event()
395 {
396         set_done(0);
397         return 1;
398 }
399