Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.git] / cinelerra-5.1 / plugins / cdripper / cdripper.C
diff --git a/cinelerra-5.1/plugins/cdripper/cdripper.C b/cinelerra-5.1/plugins/cdripper/cdripper.C
new file mode 100644 (file)
index 0000000..d6e07d6
--- /dev/null
@@ -0,0 +1,382 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "errorbox.h"
+#include "bcdisplayinfo.h"
+#include "cdripper.h"
+#include "cdripwindow.h"
+#include "bchash.h"
+#include "language.h"
+#include "mainprogress.h"
+#include "mwindow.inc"
+#include "samples.h"
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+
+PluginClient* new_plugin(PluginServer *server)
+{
+       return new CDRipMain(server);
+}
+
+
+CDRipMain::CDRipMain(PluginServer *server)
+ : PluginAClient(server)
+{
+}
+
+CDRipMain::~CDRipMain()
+{
+}
+
+const char* CDRipMain::plugin_title() { return _("CD Ripper"); }
+int CDRipMain::is_realtime() { return 0; }
+int CDRipMain::is_multichannel() { return 1; }
+
+
+int CDRipMain::load_defaults()
+{
+// set the default directory
+       char directory[1024];
+       sprintf(directory, "%scdripper.rc", BCASTDIR);
+
+// load the defaults
+       defaults = new BC_Hash(directory);
+       defaults->load();
+
+       track1 = defaults->get("TRACK1", 1);
+       min1 = defaults->get("MIN1", 0);
+       sec1 = defaults->get("SEC1", 0);
+       track2 = defaults->get("TRACK2", 2);
+       min2 = defaults->get("MIN2", 0);
+       sec2 = defaults->get("SEC2", 0);
+       sprintf(device, "/dev/cdrom");
+       defaults->get("DEVICE", device);
+       startlba = defaults->get("STARTLBA", 0);
+       endlba = defaults->get("ENDLBA", 0);
+       return 0;
+}
+
+int CDRipMain::save_defaults()
+{
+       defaults->update("TRACK1", track1);
+       defaults->update("MIN1", min1);
+       defaults->update("SEC1", sec1);
+       defaults->update("TRACK2", track2);
+       defaults->update("MIN2", min2);
+       defaults->update("SEC2", sec2);
+       defaults->update("DEVICE", device);
+       defaults->update("STARTLBA", startlba);
+       defaults->update("ENDLBA", endlba);
+       defaults->save();
+       return 0;
+}
+
+int CDRipMain::get_parameters()
+{
+       int result, result2;
+
+       result = 0;
+       result2 = 1;
+
+       while(result2 && !result)
+       {
+               {
+                       BC_DisplayInfo info;
+//printf("CDRipMain::get_parameters 1\n");
+                       CDRipWindow window(this, info.get_abs_cursor_x(), info.get_abs_cursor_y());
+//printf("CDRipMain::get_parameters 2\n");
+                       window.create_objects();
+//printf("CDRipMain::get_parameters 3\n");
+                       result = window.run_window();
+//printf("CDRipMain::get_parameters 4\n");
+               }
+               if(!result) result2 = get_toc();
+//printf("CDRipMain::get_parameters 5 %d\n", result);
+       }
+       PluginAClient::sample_rate = 44100;
+       return result;
+}
+
+int CDRipMain::open_drive()
+{
+       if((cdrom = open(device, O_RDONLY)) < 0)
+       {
+               BC_DisplayInfo info;
+               ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
+                       info.get_abs_cursor_x(), 
+                       info.get_abs_cursor_y());
+               window.create_objects(_("Can't open cdrom drive."));
+               window.run_window();
+               return 1;
+       }
+
+       ioctl(cdrom, CDROMSTART);         // start motor
+       return 0;
+}
+
+int CDRipMain::close_drive()
+{
+       ioctl(cdrom, CDROMSTOP);
+       close(cdrom);
+       return 0;
+}
+
+int CDRipMain::get_toc()
+{
+// test CD
+       int result = 0, i, tracks;
+       struct cdrom_tochdr hdr;
+       struct cdrom_tocentry entry[100];
+       BC_DisplayInfo info;
+       
+       result = open_drive();
+       
+       if(ioctl(cdrom, CDROMREADTOCHDR, &hdr) < 0)
+       {
+               close(cdrom);
+               ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
+                       info.get_abs_cursor_x(), 
+                       info.get_abs_cursor_y());
+               window.create_objects(_("Can't get total from table of contents."));
+               window.run_window();
+               result = 1;
+       }
+
+       for(i = 0; i < hdr.cdth_trk1; i++)
+       {
+               entry[i].cdte_track = 1 + i;
+               entry[i].cdte_format = CDROM_LBA;
+               if(ioctl(cdrom, CDROMREADTOCENTRY, &entry[i]) < 0)
+               {
+                       ioctl(cdrom, CDROMSTOP);
+                       close(cdrom);
+                       ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
+                               info.get_abs_cursor_x(), 
+                               info.get_abs_cursor_y());
+                       window.create_objects(_("Can't get table of contents entry."));
+                       window.run_window();
+                       result = 1;
+                       break;
+               }
+       }
+
+       entry[i].cdte_track = CDROM_LEADOUT;
+       entry[i].cdte_format = CDROM_LBA;
+       if(ioctl(cdrom, CDROMREADTOCENTRY, &entry[i]) < 0)
+       {
+               ioctl(cdrom, CDROMSTOP);
+               close(cdrom);
+               ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
+                       info.get_abs_cursor_x(), 
+                       info.get_abs_cursor_y());
+               window.create_objects(_("Can't get table of contents leadout."));
+               window.run_window();
+               result = 1;
+       }
+                       
+                       
+       tracks = hdr.cdth_trk1+1;
+
+       if(track1 <= 0 || track1 > tracks)
+       {
+               ioctl(cdrom, CDROMSTOP);
+               close(cdrom);
+               ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
+                       info.get_abs_cursor_x(), 
+                       info.get_abs_cursor_y());
+               window.create_objects(_("Start track is out of range."));
+               window.run_window();
+               result = 1;
+       }
+
+// Clamp to highest track
+       if(track2 > tracks)
+       {
+               track2 = tracks;
+       }
+       
+       if(track2 < track1 || track2 <= 0)
+       {
+               ioctl(cdrom, CDROMSTOP);
+               close(cdrom);
+               ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
+                       info.get_abs_cursor_x(), 
+                       info.get_abs_cursor_y());
+               window.create_objects(_("End track is out of range."));
+               window.run_window();
+               result = 1;
+       }
+       
+       if(track1 == track2 && min2 == 0 && sec2 == 0)
+       {
+               ioctl(cdrom, CDROMSTOP);
+               close(cdrom);
+               ErrorBox window(_(PROGRAM_NAME ": CD Ripper"),
+                       info.get_abs_cursor_x(), 
+                       info.get_abs_cursor_y());
+               window.create_objects(_("End position is out of range."));
+               window.run_window();
+               result = 1;
+       }
+
+       startlba = endlba = 0;
+       if(!result)
+       {
+               startlba = entry[track1 - 1].cdte_addr.lba;
+               startlba += (min1 * 44100 * 4 * 60 + sec1 * 44100 * 4) / FRAMESIZE;
+
+               endlba = entry[track2 - 1].cdte_addr.lba;
+               if(track2 < tracks)
+               {
+                       endlba += (min2 * 44100 * 4 * 60 + sec2 * 44100 * 4) / FRAMESIZE;
+               }
+       }
+
+//printf("CDRipMain::get_toc %jd %jd\n", startlba, endlba);
+       close_drive();
+       return result;
+}
+
+int CDRipMain::start_loop()
+{
+// get CD parameters
+       int result = 0;
+
+//printf("CDRipMain::start_loop 1\n");
+       result = get_toc();
+       FRAME = 4;    // 2 bytes 2 channels
+       previewing = 3;     // defeat bug in hardware
+       fragment_length = PluginClient::in_buffer_size * FRAME;
+       fragment_length /= NFRAMES * FRAMESIZE;
+       fragment_length *= NFRAMES * FRAMESIZE;
+       total_length = (endlba - startlba) * FRAMESIZE / fragment_length + previewing + 1;
+       result = open_drive();
+//printf("CDRipMain::start_loop 1 %d\n", interactive);
+
+// thread out progress
+       if(interactive)
+       {
+               char string[BCTEXTLEN];
+               sprintf(string, "%s...", plugin_title());
+               progress = start_progress(string, total_length);
+       }
+//printf("CDRipMain::start_loop 1\n");
+
+// get still more CD parameters
+       endofselection = 0;
+       currentlength = 0;
+       startlba_fragment = startlba - fragment_length * previewing / FRAMESIZE;
+       buffer = new char[fragment_length];
+       arg.addr.lba = startlba_fragment;
+       arg.addr_format = CDROM_LBA;
+       arg.nframes = NFRAMES;
+//printf("CDRipMain::start_loop 2\n");
+
+       return result;
+}
+
+
+int CDRipMain::stop_loop()
+{
+       if(interactive)
+       {
+               progress->stop_progress();
+               delete progress;
+       }
+
+       delete buffer;
+       close_drive();
+       return 0;
+}
+
+int CDRipMain::process_loop(Samples **plugin_buffer, int64_t &write_length)
+{
+       int result = 0;
+//printf("CDRipMain::process_loop 1\n");
+
+// render it
+       if(arg.addr.lba < endlba && !endofselection)
+       {
+               if(arg.addr.lba + fragment_length / FRAMESIZE > endlba)
+               {
+                       fragment_length = (endlba - arg.addr.lba) / NFRAMES;
+                       fragment_length *= NFRAMES * FRAMESIZE;
+                       endofselection = 1;
+               }
+//printf("CDRipMain::process_loop 2 %d %jd\n", arg.addr.lba, endlba);
+
+               for(i = 0; i < fragment_length; 
+                       i += NFRAMES * FRAMESIZE,
+                       arg.addr.lba += NFRAMES)
+               {
+                       arg.buf = (unsigned char*)&buffer[i];
+                       for(attempts = 0; attempts < 3; attempts++)
+                       {
+                               if(!(ioctl(cdrom, CDROMREADAUDIO, &arg)))
+                               {
+                                       attempts = 3;
+                               }
+                               else
+                               if(attempts == 2 && !previewing) printf("Can't read CD audio.\n");
+                       }
+               }
+//printf("CDRipMain::process_loop 3\n");
+
+               if(arg.addr.lba > startlba)
+               {
+// convert to doubles
+                       fragment_samples = fragment_length / FRAME;
+                       for(j = 0; j < 2 && j < PluginClient::total_in_buffers; j++)
+                       {
+                               buffer_channel = (int16_t*)buffer + j;
+                               output_buffer = plugin_buffer[j]->get_data();
+                               for(k = 0, l = 0; l < fragment_samples; k += 2, l++)
+                               {
+                                       output_buffer[l] = buffer_channel[k];
+                                       output_buffer[l] /= 0x7fff;
+                               }
+                       }
+
+                       write_length = fragment_samples;
+               }
+//printf("CDRipMain::process_loop 5 %d\n", interactive);
+
+               currentlength++;
+               if(interactive)
+               {
+                       if(!result) result = progress->update(currentlength);
+               }
+//printf("CDRipMain::process_loop 6\n");
+       }
+       else
+       {
+//printf("CDRipMain::process_loop 7\n");
+               endofselection = 1;
+               write_length = 0;
+       }
+
+//printf("CDRipMain::process_loop 8 %d %d\n", endofselection, result);
+       return endofselection || result;
+}