00001 #include "errorbox.h"
00002 #include "bcdisplayinfo.h"
00003 #include "cdripper.h"
00004 #include "cdripwindow.h"
00005 #include "bchash.h"
00006 #include "mainprogress.h"
00007 #include "mwindow.inc"
00008
00009 #include <fcntl.h>
00010 #include <sys/ioctl.h>
00011 #include <sys/types.h>
00012 #include <unistd.h>
00013
00014 #include <libintl.h>
00015 #define _(String) gettext(String)
00016 #define gettext_noop(String) String
00017 #define N_(String) gettext_noop (String)
00018
00019 PluginClient* new_plugin(PluginServer *server)
00020 {
00021 return new CDRipMain(server);
00022 }
00023
00024
00025 CDRipMain::CDRipMain(PluginServer *server)
00026 : PluginAClient(server)
00027 {
00028 load_defaults();
00029 }
00030
00031 CDRipMain::~CDRipMain()
00032 {
00033 save_defaults();
00034 delete defaults;
00035 }
00036
00037 char* CDRipMain::plugin_title() { return N_("CD Ripper"); }
00038 int CDRipMain::is_realtime() { return 0; }
00039 int CDRipMain::is_multichannel() { return 1; }
00040
00041
00042 int CDRipMain::load_defaults()
00043 {
00044
00045 char directory[1024];
00046 sprintf(directory, "%scdripper.rc", BCASTDIR);
00047
00048
00049 defaults = new BC_Hash(directory);
00050 defaults->load();
00051
00052 track1 = defaults->get("TRACK1", 1);
00053 min1 = defaults->get("MIN1", 0);
00054 sec1 = defaults->get("SEC1", 0);
00055 track2 = defaults->get("TRACK2", 2);
00056 min2 = defaults->get("MIN2", 0);
00057 sec2 = defaults->get("SEC2", 0);
00058 sprintf(device, "/dev/cdrom");
00059 defaults->get("DEVICE", device);
00060 startlba = defaults->get("STARTLBA", 0);
00061 endlba = defaults->get("ENDLBA", 0);
00062 return 0;
00063 }
00064
00065 int CDRipMain::save_defaults()
00066 {
00067 defaults->update("TRACK1", track1);
00068 defaults->update("MIN1", min1);
00069 defaults->update("SEC1", sec1);
00070 defaults->update("TRACK2", track2);
00071 defaults->update("MIN2", min2);
00072 defaults->update("SEC2", sec2);
00073 defaults->update("DEVICE", device);
00074 defaults->update("STARTLBA", startlba);
00075 defaults->update("ENDLBA", endlba);
00076 defaults->save();
00077 return 0;
00078 }
00079
00080 int CDRipMain::get_parameters()
00081 {
00082 int result, result2;
00083
00084 result = 0;
00085 result2 = 1;
00086
00087 while(result2 && !result)
00088 {
00089 {
00090 BC_DisplayInfo info;
00091
00092 CDRipWindow window(this, info.get_abs_cursor_x(), info.get_abs_cursor_y());
00093
00094 window.create_objects();
00095
00096 result = window.run_window();
00097
00098 }
00099 if(!result) result2 = get_toc();
00100
00101 }
00102 PluginAClient::sample_rate = 44100;
00103 return result;
00104 }
00105
00106 int CDRipMain::open_drive()
00107 {
00108 if((cdrom = open(device, O_RDONLY)) < 0)
00109 {
00110 BC_DisplayInfo info;
00111 ErrorBox window(PROGRAM_NAME ": CD Ripper",
00112 info.get_abs_cursor_x(),
00113 info.get_abs_cursor_y());
00114 window.create_objects(_("Can't open cdrom drive."));
00115 window.run_window();
00116 return 1;
00117 }
00118
00119 ioctl(cdrom, CDROMSTART);
00120 return 0;
00121 }
00122
00123 int CDRipMain::close_drive()
00124 {
00125 ioctl(cdrom, CDROMSTOP);
00126 close(cdrom);
00127 return 0;
00128 }
00129
00130 int CDRipMain::get_toc()
00131 {
00132
00133 int result = 0, i, tracks;
00134 struct cdrom_tochdr hdr;
00135 struct cdrom_tocentry entry[100];
00136 BC_DisplayInfo info;
00137
00138 result = open_drive();
00139
00140 if(ioctl(cdrom, CDROMREADTOCHDR, &hdr) < 0)
00141 {
00142 close(cdrom);
00143 ErrorBox window(PROGRAM_NAME ": CD Ripper",
00144 info.get_abs_cursor_x(),
00145 info.get_abs_cursor_y());
00146 window.create_objects(_("Can't get total from table of contents."));
00147 window.run_window();
00148 result = 1;
00149 }
00150
00151 for(i = 0; i < hdr.cdth_trk1; i++)
00152 {
00153 entry[i].cdte_track = 1 + i;
00154 entry[i].cdte_format = CDROM_LBA;
00155 if(ioctl(cdrom, CDROMREADTOCENTRY, &entry[i]) < 0)
00156 {
00157 ioctl(cdrom, CDROMSTOP);
00158 close(cdrom);
00159 ErrorBox window(PROGRAM_NAME ": CD Ripper",
00160 info.get_abs_cursor_x(),
00161 info.get_abs_cursor_y());
00162 window.create_objects(_("Can't get table of contents entry."));
00163 window.run_window();
00164 result = 1;
00165 break;
00166 }
00167 }
00168
00169 entry[i].cdte_track = CDROM_LEADOUT;
00170 entry[i].cdte_format = CDROM_LBA;
00171 if(ioctl(cdrom, CDROMREADTOCENTRY, &entry[i]) < 0)
00172 {
00173 ioctl(cdrom, CDROMSTOP);
00174 close(cdrom);
00175 ErrorBox window(PROGRAM_NAME ": CD Ripper",
00176 info.get_abs_cursor_x(),
00177 info.get_abs_cursor_y());
00178 window.create_objects(_("Can't get table of contents leadout."));
00179 window.run_window();
00180 result = 1;
00181 }
00182
00183
00184 tracks = hdr.cdth_trk1+1;
00185
00186 if(track1 <= 0 || track1 > tracks)
00187 {
00188 ioctl(cdrom, CDROMSTOP);
00189 close(cdrom);
00190 ErrorBox window(PROGRAM_NAME ": CD Ripper",
00191 info.get_abs_cursor_x(),
00192 info.get_abs_cursor_y());
00193 window.create_objects(_("Start track is out of range."));
00194 window.run_window();
00195 result = 1;
00196 }
00197
00198
00199 if(track2 > tracks)
00200 {
00201 track2 = tracks;
00202 }
00203
00204 if(track2 < track1 || track2 <= 0)
00205 {
00206 ioctl(cdrom, CDROMSTOP);
00207 close(cdrom);
00208 ErrorBox window(PROGRAM_NAME ": CD Ripper",
00209 info.get_abs_cursor_x(),
00210 info.get_abs_cursor_y());
00211 window.create_objects(_("End track is out of range."));
00212 window.run_window();
00213 result = 1;
00214 }
00215
00216 if(track1 == track2 && min2 == 0 && sec2 == 0)
00217 {
00218 ioctl(cdrom, CDROMSTOP);
00219 close(cdrom);
00220 ErrorBox window(PROGRAM_NAME ": CD Ripper",
00221 info.get_abs_cursor_x(),
00222 info.get_abs_cursor_y());
00223 window.create_objects(_("End position is out of range."));
00224 window.run_window();
00225 result = 1;
00226 }
00227
00228 startlba = endlba = 0;
00229 if(!result)
00230 {
00231 startlba = entry[track1 - 1].cdte_addr.lba;
00232 startlba += (min1 * 44100 * 4 * 60 + sec1 * 44100 * 4) / FRAMESIZE;
00233
00234 endlba = entry[track2 - 1].cdte_addr.lba;
00235 if(track2 < tracks)
00236 {
00237 endlba += (min2 * 44100 * 4 * 60 + sec2 * 44100 * 4) / FRAMESIZE;
00238 }
00239 }
00240
00241
00242 close_drive();
00243 return result;
00244 }
00245
00246 int CDRipMain::start_loop()
00247 {
00248
00249 int result = 0;
00250
00251
00252 result = get_toc();
00253 FRAME = 4;
00254 previewing = 3;
00255 fragment_length = PluginClient::in_buffer_size * FRAME;
00256 fragment_length /= NFRAMES * FRAMESIZE;
00257 fragment_length *= NFRAMES * FRAMESIZE;
00258 total_length = (endlba - startlba) * FRAMESIZE / fragment_length + previewing + 1;
00259 result = open_drive();
00260
00261
00262
00263 if(interactive)
00264 {
00265 char string[BCTEXTLEN];
00266 sprintf(string, "%s...", plugin_title());
00267 progress = start_progress(string, total_length);
00268 }
00269
00270
00271
00272 endofselection = 0;
00273 currentlength = 0;
00274 startlba_fragment = startlba - fragment_length * previewing / FRAMESIZE;
00275 buffer = new char[fragment_length];
00276 arg.addr.lba = startlba_fragment;
00277 arg.addr_format = CDROM_LBA;
00278 arg.nframes = NFRAMES;
00279
00280
00281 return result;
00282 }
00283
00284
00285 int CDRipMain::stop_loop()
00286 {
00287 if(interactive)
00288 {
00289 progress->stop_progress();
00290 delete progress;
00291 }
00292
00293 delete buffer;
00294 close_drive();
00295 return 0;
00296 }
00297
00298 int CDRipMain::process_loop(double **plugin_buffer, int64_t &write_length)
00299 {
00300 int result = 0;
00301
00302
00303
00304 if(arg.addr.lba < endlba && !endofselection)
00305 {
00306 if(arg.addr.lba + fragment_length / FRAMESIZE > endlba)
00307 {
00308 fragment_length = (endlba - arg.addr.lba) / NFRAMES;
00309 fragment_length *= NFRAMES * FRAMESIZE;
00310 endofselection = 1;
00311 }
00312
00313
00314 for(i = 0; i < fragment_length;
00315 i += NFRAMES * FRAMESIZE,
00316 arg.addr.lba += NFRAMES)
00317 {
00318 arg.buf = (unsigned char*)&buffer[i];
00319 for(attempts = 0; attempts < 3; attempts++)
00320 {
00321 if(!(ioctl(cdrom, CDROMREADAUDIO, &arg)))
00322 {
00323 attempts = 3;
00324 }
00325 else
00326 if(attempts == 2 && !previewing) printf("Can't read CD audio.\n");
00327 }
00328 }
00329
00330
00331 if(arg.addr.lba > startlba)
00332 {
00333
00334 fragment_samples = fragment_length / FRAME;
00335 for(j = 0; j < 2 && j < PluginClient::total_in_buffers; j++)
00336 {
00337 buffer_channel = (int16_t*)buffer + j;
00338 output_buffer = plugin_buffer[j];
00339 for(k = 0, l = 0; l < fragment_samples; k += 2, l++)
00340 {
00341 output_buffer[l] = buffer_channel[k];
00342 output_buffer[l] /= 0x7fff;
00343 }
00344 }
00345
00346 write_length = fragment_samples;
00347 }
00348
00349
00350 currentlength++;
00351 if(interactive)
00352 {
00353 if(!result) result = progress->update(currentlength);
00354 }
00355
00356 }
00357 else
00358 {
00359
00360 endofselection = 1;
00361 write_length = 0;
00362 }
00363
00364
00365 return endofselection || result;
00366 }