4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5 * Copyright (C) 2003-2016 Cinelerra CV contributors
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "bcdisplayinfo.h"
26 #include "cdripwindow.h"
30 #include "mainprogress.h"
31 #include "mwindow.inc"
35 #include <sys/ioctl.h>
36 #include <sys/types.h>
40 PluginClient* new_plugin(PluginServer *server)
42 return new CDRipMain(server);
46 CDRipMain::CDRipMain(PluginServer *server)
47 : PluginAClient(server)
51 CDRipMain::~CDRipMain()
55 const char* CDRipMain::plugin_title() { return N_("CD Ripper"); }
56 int CDRipMain::is_realtime() { return 0; }
57 int CDRipMain::is_multichannel() { return 1; }
60 int CDRipMain::load_defaults()
62 // set the default directory
64 sprintf(directory, "%s/cdripper.rc", File::get_config_path());
67 defaults = new BC_Hash(directory);
70 track1 = defaults->get("TRACK1", 1);
71 min1 = defaults->get("MIN1", 0);
72 sec1 = defaults->get("SEC1", 0);
73 track2 = defaults->get("TRACK2", 2);
74 min2 = defaults->get("MIN2", 0);
75 sec2 = defaults->get("SEC2", 0);
76 sprintf(device, "/dev/cdrom");
77 defaults->get("DEVICE", device);
78 startlba = defaults->get("STARTLBA", 0);
79 endlba = defaults->get("ENDLBA", 0);
83 int CDRipMain::save_defaults()
85 defaults->update("TRACK1", track1);
86 defaults->update("MIN1", min1);
87 defaults->update("SEC1", sec1);
88 defaults->update("TRACK2", track2);
89 defaults->update("MIN2", min2);
90 defaults->update("SEC2", sec2);
91 defaults->update("DEVICE", device);
92 defaults->update("STARTLBA", startlba);
93 defaults->update("ENDLBA", endlba);
98 int CDRipMain::get_parameters()
105 while(result2 && !result)
109 //printf("CDRipMain::get_parameters 1\n");
110 CDRipWindow window(this, info.get_abs_cursor_x(), info.get_abs_cursor_y());
111 //printf("CDRipMain::get_parameters 2\n");
112 window.create_objects();
113 //printf("CDRipMain::get_parameters 3\n");
114 result = window.run_window();
115 //printf("CDRipMain::get_parameters 4\n");
117 if(!result) result2 = get_toc();
118 //printf("CDRipMain::get_parameters 5 %d\n", result);
120 PluginAClient::sample_rate = 44100;
124 int CDRipMain::open_drive()
126 if((cdrom = open(device, O_RDONLY)) < 0)
129 ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
130 info.get_abs_cursor_x(),
131 info.get_abs_cursor_y());
132 window.create_objects(_("Can't open cdrom drive."));
137 ioctl(cdrom, CDROMSTART); // start motor
141 int CDRipMain::close_drive()
143 ioctl(cdrom, CDROMSTOP);
148 int CDRipMain::get_toc()
151 int result = 0, i, tracks;
152 struct cdrom_tochdr hdr;
153 struct cdrom_tocentry entry[100];
156 result = open_drive();
158 if(ioctl(cdrom, CDROMREADTOCHDR, &hdr) < 0)
161 ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
162 info.get_abs_cursor_x(),
163 info.get_abs_cursor_y());
164 window.create_objects(_("Can't get total from table of contents."));
169 for(i = 0; i < hdr.cdth_trk1; i++)
171 entry[i].cdte_track = 1 + i;
172 entry[i].cdte_format = CDROM_LBA;
173 if(ioctl(cdrom, CDROMREADTOCENTRY, &entry[i]) < 0)
175 ioctl(cdrom, CDROMSTOP);
177 ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
178 info.get_abs_cursor_x(),
179 info.get_abs_cursor_y());
180 window.create_objects(_("Can't get table of contents entry."));
187 entry[i].cdte_track = CDROM_LEADOUT;
188 entry[i].cdte_format = CDROM_LBA;
189 if(ioctl(cdrom, CDROMREADTOCENTRY, &entry[i]) < 0)
191 ioctl(cdrom, CDROMSTOP);
193 ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
194 info.get_abs_cursor_x(),
195 info.get_abs_cursor_y());
196 window.create_objects(_("Can't get table of contents leadout."));
202 tracks = hdr.cdth_trk1+1;
204 if(track1 <= 0 || track1 > tracks)
206 ioctl(cdrom, CDROMSTOP);
208 ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
209 info.get_abs_cursor_x(),
210 info.get_abs_cursor_y());
211 window.create_objects(_("Start track is out of range."));
216 // Clamp to highest track
222 if(track2 < track1 || track2 <= 0)
224 ioctl(cdrom, CDROMSTOP);
226 ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
227 info.get_abs_cursor_x(),
228 info.get_abs_cursor_y());
229 window.create_objects(_("End track is out of range."));
234 if(track1 == track2 && min2 == 0 && sec2 == 0)
236 ioctl(cdrom, CDROMSTOP);
238 ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
239 info.get_abs_cursor_x(),
240 info.get_abs_cursor_y());
241 window.create_objects(_("End position is out of range."));
246 startlba = endlba = 0;
249 startlba = entry[track1 - 1].cdte_addr.lba;
250 startlba += (min1 * 44100 * 4 * 60 + sec1 * 44100 * 4) / FRAMESIZE;
252 endlba = entry[track2 - 1].cdte_addr.lba;
255 endlba += (min2 * 44100 * 4 * 60 + sec2 * 44100 * 4) / FRAMESIZE;
259 //printf("CDRipMain::get_toc %jd %jd\n", startlba, endlba);
264 int CDRipMain::start_loop()
269 //printf("CDRipMain::start_loop 1\n");
271 FRAME = 4; // 2 bytes 2 channels
272 previewing = 3; // defeat bug in hardware
273 fragment_length = PluginClient::in_buffer_size * FRAME;
274 fragment_length /= NFRAMES * FRAMESIZE;
275 fragment_length *= NFRAMES * FRAMESIZE;
276 total_length = (endlba - startlba) * FRAMESIZE / fragment_length + previewing + 1;
277 result = open_drive();
278 //printf("CDRipMain::start_loop 1 %d\n", interactive);
280 // thread out progress
283 char string[BCTEXTLEN];
284 sprintf(string, "%s...", plugin_title());
285 progress = start_progress(string, total_length);
287 //printf("CDRipMain::start_loop 1\n");
289 // get still more CD parameters
292 startlba_fragment = startlba - fragment_length * previewing / FRAMESIZE;
293 buffer = new char[fragment_length];
294 arg.addr.lba = startlba_fragment;
295 arg.addr_format = CDROM_LBA;
296 arg.nframes = NFRAMES;
297 //printf("CDRipMain::start_loop 2\n");
303 int CDRipMain::stop_loop()
307 progress->stop_progress();
316 int CDRipMain::process_loop(Samples **plugin_buffer, int64_t &write_length)
319 //printf("CDRipMain::process_loop 1\n");
322 if(arg.addr.lba < endlba && !endofselection)
324 if(arg.addr.lba + fragment_length / FRAMESIZE > endlba)
326 fragment_length = (endlba - arg.addr.lba) / NFRAMES;
327 fragment_length *= NFRAMES * FRAMESIZE;
330 //printf("CDRipMain::process_loop 2 %d %jd\n", arg.addr.lba, endlba);
332 for(i = 0; i < fragment_length;
333 i += NFRAMES * FRAMESIZE,
334 arg.addr.lba += NFRAMES)
336 arg.buf = (unsigned char*)&buffer[i];
337 for(attempts = 0; attempts < 3; attempts++)
339 if(!(ioctl(cdrom, CDROMREADAUDIO, &arg)))
344 if(attempts == 2 && !previewing) printf("Can't read CD audio.\n");
347 //printf("CDRipMain::process_loop 3\n");
349 if(arg.addr.lba > startlba)
351 // convert to doubles
352 fragment_samples = fragment_length / FRAME;
353 for(j = 0; j < 2 && j < PluginClient::total_in_buffers; j++)
355 buffer_channel = (int16_t*)buffer + j;
356 output_buffer = plugin_buffer[j]->get_data();
357 for(k = 0, l = 0; l < fragment_samples; k += 2, l++)
359 output_buffer[l] = buffer_channel[k];
360 output_buffer[l] /= 0x7fff;
364 write_length = fragment_samples;
366 //printf("CDRipMain::process_loop 5 %d\n", interactive);
371 if(!result) result = progress->update(currentlength);
373 //printf("CDRipMain::process_loop 6\n");
377 //printf("CDRipMain::process_loop 7\n");
382 //printf("CDRipMain::process_loop 8 %d %d\n", endofselection, result);
383 return endofselection || result;