Fixed initialisation of tf in file_open(). Without setting the memory to 0,
[cinelerra_cv/mob.git] / plugins / cdripper / cdripper.C
blob915f578cfe50168ee8bc8f6f09b780b4310048fc
1 #include "errorbox.h"
2 #include "bcdisplayinfo.h"
3 #include "cdripper.h"
4 #include "cdripwindow.h"
5 #include "bchash.h"
6 #include "mainprogress.h"
7 #include "mwindow.inc"
9 #include <fcntl.h>
10 #include <sys/ioctl.h>
11 #include <sys/types.h>
12 #include <unistd.h>
14 #include <libintl.h>
15 #define _(String) gettext(String)
16 #define gettext_noop(String) String
17 #define N_(String) gettext_noop (String)
19 PluginClient* new_plugin(PluginServer *server)
21         return new CDRipMain(server);
25 CDRipMain::CDRipMain(PluginServer *server)
26  : PluginAClient(server)
28         load_defaults();
31 CDRipMain::~CDRipMain()
33         save_defaults();
34         delete defaults;
37 char* CDRipMain::plugin_title() { return N_("CD Ripper"); }
38 int CDRipMain::is_realtime() { return 0; }
39 int CDRipMain::is_multichannel() { return 1; }
42 int CDRipMain::load_defaults()
44 // set the default directory
45         char directory[1024];
46         sprintf(directory, "%scdripper.rc", BCASTDIR);
48 // load the defaults
49         defaults = new BC_Hash(directory);
50         defaults->load();
52         track1 = defaults->get("TRACK1", 1);
53         min1 = defaults->get("MIN1", 0);
54         sec1 = defaults->get("SEC1", 0);
55         track2 = defaults->get("TRACK2", 2);
56         min2 = defaults->get("MIN2", 0);
57         sec2 = defaults->get("SEC2", 0);
58         sprintf(device, "/dev/cdrom");
59         defaults->get("DEVICE", device);
60         startlba = defaults->get("STARTLBA", 0);
61         endlba = defaults->get("ENDLBA", 0);
62         return 0;
65 int CDRipMain::save_defaults()
67         defaults->update("TRACK1", track1);
68         defaults->update("MIN1", min1);
69         defaults->update("SEC1", sec1);
70         defaults->update("TRACK2", track2);
71         defaults->update("MIN2", min2);
72         defaults->update("SEC2", sec2);
73         defaults->update("DEVICE", device);
74         defaults->update("STARTLBA", startlba);
75         defaults->update("ENDLBA", endlba);
76         defaults->save();
77         return 0;
80 int CDRipMain::get_parameters()
82         int result, result2;
84         result = 0;
85         result2 = 1;
87         while(result2 && !result)
88         {
89                 {
90                         BC_DisplayInfo info;
91 //printf("CDRipMain::get_parameters 1\n");
92                         CDRipWindow window(this, info.get_abs_cursor_x(), info.get_abs_cursor_y());
93 //printf("CDRipMain::get_parameters 2\n");
94                         window.create_objects();
95 //printf("CDRipMain::get_parameters 3\n");
96                         result = window.run_window();
97 //printf("CDRipMain::get_parameters 4\n");
98                 }
99                 if(!result) result2 = get_toc();
100 //printf("CDRipMain::get_parameters 5 %d\n", result);
101         }
102         PluginAClient::sample_rate = 44100;
103         return result;
106 int CDRipMain::open_drive()
108         if((cdrom = open(device, O_RDONLY)) < 0)
109         {
110                 BC_DisplayInfo info;
111                 ErrorBox window(PROGRAM_NAME ": CD Ripper",
112                         info.get_abs_cursor_x(), 
113                         info.get_abs_cursor_y());
114                 window.create_objects(_("Can't open cdrom drive."));
115                 window.run_window();
116                 return 1;
117         }
119         ioctl(cdrom, CDROMSTART);         // start motor
120         return 0;
123 int CDRipMain::close_drive()
125         ioctl(cdrom, CDROMSTOP);
126         close(cdrom);
127         return 0;
130 int CDRipMain::get_toc()
132 // test CD
133         int result = 0, i, tracks;
134         struct cdrom_tochdr hdr;
135         struct cdrom_tocentry entry[100];
136         BC_DisplayInfo info;
137         
138         result = open_drive();
139         
140         if(ioctl(cdrom, CDROMREADTOCHDR, &hdr) < 0)
141         {
142                 close(cdrom);
143                 ErrorBox window(PROGRAM_NAME ": CD Ripper",
144                         info.get_abs_cursor_x(), 
145                         info.get_abs_cursor_y());
146                 window.create_objects(_("Can't get total from table of contents."));
147                 window.run_window();
148                 result = 1;
149         }
151         for(i = 0; i < hdr.cdth_trk1; i++)
152         {
153                 entry[i].cdte_track = 1 + i;
154                 entry[i].cdte_format = CDROM_LBA;
155                 if(ioctl(cdrom, CDROMREADTOCENTRY, &entry[i]) < 0)
156                 {
157                         ioctl(cdrom, CDROMSTOP);
158                         close(cdrom);
159                         ErrorBox window(PROGRAM_NAME ": CD Ripper",
160                                 info.get_abs_cursor_x(), 
161                                 info.get_abs_cursor_y());
162                         window.create_objects(_("Can't get table of contents entry."));
163                         window.run_window();
164                         result = 1;
165                         break;
166                 }
167         }
169         entry[i].cdte_track = CDROM_LEADOUT;
170         entry[i].cdte_format = CDROM_LBA;
171         if(ioctl(cdrom, CDROMREADTOCENTRY, &entry[i]) < 0)
172         {
173                 ioctl(cdrom, CDROMSTOP);
174                 close(cdrom);
175                 ErrorBox window(PROGRAM_NAME ": CD Ripper",
176                         info.get_abs_cursor_x(), 
177                         info.get_abs_cursor_y());
178                 window.create_objects(_("Can't get table of contents leadout."));
179                 window.run_window();
180                 result = 1;
181         }
182                         
183                         
184         tracks = hdr.cdth_trk1+1;
186         if(track1 <= 0 || track1 > tracks)
187         {
188                 ioctl(cdrom, CDROMSTOP);
189                 close(cdrom);
190                 ErrorBox window(PROGRAM_NAME ": CD Ripper",
191                         info.get_abs_cursor_x(), 
192                         info.get_abs_cursor_y());
193                 window.create_objects(_("Start track is out of range."));
194                 window.run_window();
195                 result = 1;
196         }
198 // Clamp to highest track
199         if(track2 > tracks)
200         {
201                 track2 = tracks;
202         }
203         
204         if(track2 < track1 || track2 <= 0)
205         {
206                 ioctl(cdrom, CDROMSTOP);
207                 close(cdrom);
208                 ErrorBox window(PROGRAM_NAME ": CD Ripper",
209                         info.get_abs_cursor_x(), 
210                         info.get_abs_cursor_y());
211                 window.create_objects(_("End track is out of range."));
212                 window.run_window();
213                 result = 1;
214         }
215         
216         if(track1 == track2 && min2 == 0 && sec2 == 0)
217         {
218                 ioctl(cdrom, CDROMSTOP);
219                 close(cdrom);
220                 ErrorBox window(PROGRAM_NAME ": CD Ripper",
221                         info.get_abs_cursor_x(), 
222                         info.get_abs_cursor_y());
223                 window.create_objects(_("End position is out of range."));
224                 window.run_window();
225                 result = 1;
226         }
228         startlba = endlba = 0;
229         if(!result)
230         {
231                 startlba = entry[track1 - 1].cdte_addr.lba;
232                 startlba += (min1 * 44100 * 4 * 60 + sec1 * 44100 * 4) / FRAMESIZE;
234                 endlba = entry[track2 - 1].cdte_addr.lba;
235                 if(track2 < tracks)
236                 {
237                         endlba += (min2 * 44100 * 4 * 60 + sec2 * 44100 * 4) / FRAMESIZE;
238                 }
239         }
241 //printf("CDRipMain::get_toc %ld %ld\n", startlba, endlba);
242         close_drive();
243         return result;
246 int CDRipMain::start_loop()
248 // get CD parameters
249         int result = 0;
251 //printf("CDRipMain::start_loop 1\n");
252         result = get_toc();
253         FRAME = 4;    // 2 bytes 2 channels
254         previewing = 3;     // defeat bug in hardware
255         fragment_length = PluginClient::in_buffer_size * FRAME;
256         fragment_length /= NFRAMES * FRAMESIZE;
257         fragment_length *= NFRAMES * FRAMESIZE;
258         total_length = (endlba - startlba) * FRAMESIZE / fragment_length + previewing + 1;
259         result = open_drive();
260 //printf("CDRipMain::start_loop 1 %d\n", interactive);
262 // thread out progress
263         if(interactive)
264         {
265                 char string[BCTEXTLEN];
266                 sprintf(string, "%s...", plugin_title());
267                 progress = start_progress(string, total_length);
268         }
269 //printf("CDRipMain::start_loop 1\n");
271 // get still more CD parameters
272         endofselection = 0;
273         currentlength = 0;
274         startlba_fragment = startlba - fragment_length * previewing / FRAMESIZE;
275         buffer = new char[fragment_length];
276         arg.addr.lba = startlba_fragment;
277         arg.addr_format = CDROM_LBA;
278         arg.nframes = NFRAMES;
279 //printf("CDRipMain::start_loop 2\n");
281         return result;
285 int CDRipMain::stop_loop()
287         if(interactive)
288         {
289                 progress->stop_progress();
290                 delete progress;
291         }
293         delete buffer;
294         close_drive();
295         return 0;
298 int CDRipMain::process_loop(double **plugin_buffer, int64_t &write_length)
300         int result = 0;
301 //printf("CDRipMain::process_loop 1\n");
303 // render it
304         if(arg.addr.lba < endlba && !endofselection)
305         {
306                 if(arg.addr.lba + fragment_length / FRAMESIZE > endlba)
307                 {
308                         fragment_length = (endlba - arg.addr.lba) / NFRAMES;
309                         fragment_length *= NFRAMES * FRAMESIZE;
310                         endofselection = 1;
311                 }
312 //printf("CDRipMain::process_loop 2 %d %d\n", arg.addr.lba, endlba);
314                 for(i = 0; i < fragment_length; 
315                         i += NFRAMES * FRAMESIZE,
316                         arg.addr.lba += NFRAMES)
317                 {
318                         arg.buf = (unsigned char*)&buffer[i];
319                         for(attempts = 0; attempts < 3; attempts++)
320                         {
321                                 if(!(ioctl(cdrom, CDROMREADAUDIO, &arg)))
322                                 {
323                                         attempts = 3;
324                                 }
325                                 else
326                                 if(attempts == 2 && !previewing) printf("Can't read CD audio.\n");
327                         }
328                 }
329 //printf("CDRipMain::process_loop 3\n");
331                 if(arg.addr.lba > startlba)
332                 {
333 // convert to doubles
334                         fragment_samples = fragment_length / FRAME;
335                         for(j = 0; j < 2 && j < PluginClient::total_in_buffers; j++)
336                         {
337                                 buffer_channel = (int16_t*)buffer + j;
338                                 output_buffer = plugin_buffer[j];
339                                 for(k = 0, l = 0; l < fragment_samples; k += 2, l++)
340                                 {
341                                         output_buffer[l] = buffer_channel[k];
342                                         output_buffer[l] /= 0x7fff;
343                                 }
344                         }
346                         write_length = fragment_samples;
347                 }
348 //printf("CDRipMain::process_loop 5 %d\n", interactive);
350                 currentlength++;
351                 if(interactive)
352                 {
353                         if(!result) result = progress->update(currentlength);
354                 }
355 //printf("CDRipMain::process_loop 6\n");
356         }
357         else
358         {
359 //printf("CDRipMain::process_loop 7\n");
360                 endofselection = 1;
361                 write_length = 0;
362         }
364 //printf("CDRipMain::process_loop 8 %d %d\n", endofselection, result);
365         return endofselection || result;