4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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.
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.
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
23 #include "bcdisplayinfo.h"
25 #include "cdripwindow.h"
28 #include "mainprogress.h"
29 #include "mwindow.inc"
33 #include <sys/ioctl.h>
34 #include <sys/types.h>
38 PluginClient* new_plugin(PluginServer *server)
40 return new CDRipMain(server);
44 CDRipMain::CDRipMain(PluginServer *server)
45 : PluginAClient(server)
49 CDRipMain::~CDRipMain()
53 const char* CDRipMain::plugin_title() { return _("CD Ripper"); }
54 int CDRipMain::is_realtime() { return 0; }
55 int CDRipMain::is_multichannel() { return 1; }
58 int CDRipMain::load_defaults()
60 // set the default directory
62 sprintf(directory, "%scdripper.rc", BCASTDIR);
65 defaults = new BC_Hash(directory);
68 track1 = defaults->get("TRACK1", 1);
69 min1 = defaults->get("MIN1", 0);
70 sec1 = defaults->get("SEC1", 0);
71 track2 = defaults->get("TRACK2", 2);
72 min2 = defaults->get("MIN2", 0);
73 sec2 = defaults->get("SEC2", 0);
74 sprintf(device, "/dev/cdrom");
75 defaults->get("DEVICE", device);
76 startlba = defaults->get("STARTLBA", 0);
77 endlba = defaults->get("ENDLBA", 0);
81 int CDRipMain::save_defaults()
83 defaults->update("TRACK1", track1);
84 defaults->update("MIN1", min1);
85 defaults->update("SEC1", sec1);
86 defaults->update("TRACK2", track2);
87 defaults->update("MIN2", min2);
88 defaults->update("SEC2", sec2);
89 defaults->update("DEVICE", device);
90 defaults->update("STARTLBA", startlba);
91 defaults->update("ENDLBA", endlba);
96 int CDRipMain::get_parameters()
103 while(result2 && !result)
107 //printf("CDRipMain::get_parameters 1\n");
108 CDRipWindow window(this, info.get_abs_cursor_x(), info.get_abs_cursor_y());
109 //printf("CDRipMain::get_parameters 2\n");
110 window.create_objects();
111 //printf("CDRipMain::get_parameters 3\n");
112 result = window.run_window();
113 //printf("CDRipMain::get_parameters 4\n");
115 if(!result) result2 = get_toc();
116 //printf("CDRipMain::get_parameters 5 %d\n", result);
118 PluginAClient::sample_rate = 44100;
122 int CDRipMain::open_drive()
124 if((cdrom = open(device, O_RDONLY)) < 0)
127 ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
128 info.get_abs_cursor_x(),
129 info.get_abs_cursor_y());
130 window.create_objects(_("Can't open cdrom drive."));
135 ioctl(cdrom, CDROMSTART); // start motor
139 int CDRipMain::close_drive()
141 ioctl(cdrom, CDROMSTOP);
146 int CDRipMain::get_toc()
149 int result = 0, i, tracks;
150 struct cdrom_tochdr hdr;
151 struct cdrom_tocentry entry[100];
154 result = open_drive();
156 if(ioctl(cdrom, CDROMREADTOCHDR, &hdr) < 0)
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 total from table of contents."));
167 for(i = 0; i < hdr.cdth_trk1; i++)
169 entry[i].cdte_track = 1 + i;
170 entry[i].cdte_format = CDROM_LBA;
171 if(ioctl(cdrom, CDROMREADTOCENTRY, &entry[i]) < 0)
173 ioctl(cdrom, CDROMSTOP);
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 entry."));
185 entry[i].cdte_track = CDROM_LEADOUT;
186 entry[i].cdte_format = CDROM_LBA;
187 if(ioctl(cdrom, CDROMREADTOCENTRY, &entry[i]) < 0)
189 ioctl(cdrom, CDROMSTOP);
191 ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
192 info.get_abs_cursor_x(),
193 info.get_abs_cursor_y());
194 window.create_objects(_("Can't get table of contents leadout."));
200 tracks = hdr.cdth_trk1+1;
202 if(track1 <= 0 || track1 > tracks)
204 ioctl(cdrom, CDROMSTOP);
206 ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
207 info.get_abs_cursor_x(),
208 info.get_abs_cursor_y());
209 window.create_objects(_("Start track is out of range."));
214 // Clamp to highest track
220 if(track2 < track1 || track2 <= 0)
222 ioctl(cdrom, CDROMSTOP);
224 ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
225 info.get_abs_cursor_x(),
226 info.get_abs_cursor_y());
227 window.create_objects(_("End track is out of range."));
232 if(track1 == track2 && min2 == 0 && sec2 == 0)
234 ioctl(cdrom, CDROMSTOP);
236 ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
237 info.get_abs_cursor_x(),
238 info.get_abs_cursor_y());
239 window.create_objects(_("End position is out of range."));
244 startlba = endlba = 0;
247 startlba = entry[track1 - 1].cdte_addr.lba;
248 startlba += (min1 * 44100 * 4 * 60 + sec1 * 44100 * 4) / FRAMESIZE;
250 endlba = entry[track2 - 1].cdte_addr.lba;
253 endlba += (min2 * 44100 * 4 * 60 + sec2 * 44100 * 4) / FRAMESIZE;
257 //printf("CDRipMain::get_toc %jd %jd\n", startlba, endlba);
262 int CDRipMain::start_loop()
267 //printf("CDRipMain::start_loop 1\n");
269 FRAME = 4; // 2 bytes 2 channels
270 previewing = 3; // defeat bug in hardware
271 fragment_length = PluginClient::in_buffer_size * FRAME;
272 fragment_length /= NFRAMES * FRAMESIZE;
273 fragment_length *= NFRAMES * FRAMESIZE;
274 total_length = (endlba - startlba) * FRAMESIZE / fragment_length + previewing + 1;
275 result = open_drive();
276 //printf("CDRipMain::start_loop 1 %d\n", interactive);
278 // thread out progress
281 char string[BCTEXTLEN];
282 sprintf(string, "%s...", plugin_title());
283 progress = start_progress(string, total_length);
285 //printf("CDRipMain::start_loop 1\n");
287 // get still more CD parameters
290 startlba_fragment = startlba - fragment_length * previewing / FRAMESIZE;
291 buffer = new char[fragment_length];
292 arg.addr.lba = startlba_fragment;
293 arg.addr_format = CDROM_LBA;
294 arg.nframes = NFRAMES;
295 //printf("CDRipMain::start_loop 2\n");
301 int CDRipMain::stop_loop()
305 progress->stop_progress();
314 int CDRipMain::process_loop(Samples **plugin_buffer, int64_t &write_length)
317 //printf("CDRipMain::process_loop 1\n");
320 if(arg.addr.lba < endlba && !endofselection)
322 if(arg.addr.lba + fragment_length / FRAMESIZE > endlba)
324 fragment_length = (endlba - arg.addr.lba) / NFRAMES;
325 fragment_length *= NFRAMES * FRAMESIZE;
328 //printf("CDRipMain::process_loop 2 %d %jd\n", arg.addr.lba, endlba);
330 for(i = 0; i < fragment_length;
331 i += NFRAMES * FRAMESIZE,
332 arg.addr.lba += NFRAMES)
334 arg.buf = (unsigned char*)&buffer[i];
335 for(attempts = 0; attempts < 3; attempts++)
337 if(!(ioctl(cdrom, CDROMREADAUDIO, &arg)))
342 if(attempts == 2 && !previewing) printf("Can't read CD audio.\n");
345 //printf("CDRipMain::process_loop 3\n");
347 if(arg.addr.lba > startlba)
349 // convert to doubles
350 fragment_samples = fragment_length / FRAME;
351 for(j = 0; j < 2 && j < PluginClient::total_in_buffers; j++)
353 buffer_channel = (int16_t*)buffer + j;
354 output_buffer = plugin_buffer[j]->get_data();
355 for(k = 0, l = 0; l < fragment_samples; k += 2, l++)
357 output_buffer[l] = buffer_channel[k];
358 output_buffer[l] /= 0x7fff;
362 write_length = fragment_samples;
364 //printf("CDRipMain::process_loop 5 %d\n", interactive);
369 if(!result) result = progress->update(currentlength);
371 //printf("CDRipMain::process_loop 6\n");
375 //printf("CDRipMain::process_loop 7\n");
380 //printf("CDRipMain::process_loop 8 %d %d\n", endofselection, result);
381 return endofselection || result;