summaryrefslogtreecommitdiffstats
path: root/kaudiocreator/ripper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kaudiocreator/ripper.cpp')
-rw-r--r--kaudiocreator/ripper.cpp263
1 files changed, 263 insertions, 0 deletions
diff --git a/kaudiocreator/ripper.cpp b/kaudiocreator/ripper.cpp
new file mode 100644
index 00000000..2dd8795d
--- /dev/null
+++ b/kaudiocreator/ripper.cpp
@@ -0,0 +1,263 @@
+/**
+ * This file is part of the KAudioCreator package
+ * Copyright (C) 2003 Benjamin C Meyer (ben+kaudiocreator at meyerhome 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 library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "ripper.h"
+#include "prefs.h"
+
+#include <qfile.h>
+#include <qtimer.h>
+#include <ktempfile.h>
+#include <kmessagebox.h>
+#include <knotifyclient.h>
+#include <kstandarddirs.h>
+#include <kio/scheduler.h>
+
+/**
+ * Constructor, load settings.
+ */
+Ripper::Ripper( QObject* parent, const char* name) : QObject(parent,name) {
+ loadSettings();
+}
+
+/**
+ * Loads the settings
+ */
+void Ripper::loadSettings(){
+ for(uint i=0; i<(uint)Prefs::maxWavFiles(); i++)
+ tendToNewJobs();
+}
+
+/**
+ * Deconstructor, remove pending jobs, remove current jobs, save settings.
+ */
+Ripper::~Ripper(){
+ pendingJobs.clear();
+ QMap<KIO::Job*, Job*>::Iterator it;
+ for( it = jobs.begin(); it != jobs.end(); ++it ){
+ KIO::Job* ioJob = it.key();
+ Job *job = it.data();
+ delete job;
+
+ if(ioJob){
+ KIO::FileCopyJob *copyJob = static_cast<KIO::FileCopyJob*> (ioJob);
+ disconnect(copyJob, SIGNAL(result(KIO::Job*)), this, SLOT(copyJobResult(KIO::Job*)));
+ disconnect(copyJob, SIGNAL(percent ( KIO::Job *, unsigned long)), this, SLOT(updateProgress ( KIO::Job *, unsigned long)));
+ QString fileDestination = (copyJob->destURL()).path();
+ copyJob->kill();
+ QFile file( fileDestination );
+ file.remove();
+ }
+ }
+ jobs.clear();
+}
+
+/**
+ * @return The number of active jobs
+ */
+int Ripper::activeJobCount() {
+ return jobs.count();
+}
+
+/**
+ * @return The number of pending jobs
+ */
+int Ripper::pendingJobCount() {
+ return pendingJobs.count();
+}
+
+/**
+ * Cancel and remove the job with the matching id.
+ * Remove it from the local collection of jobs, delete the temp file if
+ * there is one.
+ * @param id the id number of the job to remove.
+ */
+void Ripper::removeJob(int id){
+ QMap<KIO::Job*, Job*>::Iterator it;
+ for( it = jobs.begin(); it != jobs.end(); ++it ){
+ if(it.data()->id == id){
+ KIO::FileCopyJob *copyJob = dynamic_cast<KIO::FileCopyJob*> (it.key());
+ if(copyJob){
+ QString fileDestination = (copyJob->destURL()).path();
+ copyJob->kill();
+ // This here is such a hack, shouldn't kill() do this, or why isn't there a stop()?
+ // TODO add to copyJob a stop() function.
+ QFile file( fileDestination );
+ if(file.exists())
+ file.remove();
+ else {
+ QFile f( fileDestination+".part" );
+ f.remove();
+ }
+ }
+ jobs.remove(it.key());
+ break;
+ }
+ }
+ Job *job = pendingJobs.first();
+ while(job){
+ if(job->id == id)
+ break;
+ job = pendingJobs.next();
+ }
+ if(job){
+ pendingJobs.remove(job);
+ delete job;
+ }
+ //qDebug(QString("Done removing Job:%1").arg(id).latin1());
+ tendToNewJobs();
+}
+
+/**
+ * Begin to rip the track specified in job.
+ * @param job the new job that this module should take over.
+ * @param job the new job that we need to handle.
+ */
+void Ripper::ripTrack(Job *job){
+ if(!job)
+ return;
+ emit(addJob(job, i18n("Ripping: %1 - %2").arg(job->track_artist).arg(job->track_title)));
+ pendingJobs.append(job);
+ tendToNewJobs();
+}
+
+/**
+ * See if there are are new jobs to attend too. If we are all loaded up
+ * then just loop.
+ */
+void Ripper::tendToNewJobs(){
+ if(pendingJobs.count() == 0){
+ emit jobsChanged();
+ return;
+ }
+
+ // If we are currently ripping the max try again in a little bit.
+ if(jobs.count() >= (uint)Prefs::maxWavFiles()){
+ emit jobsChanged();
+ return;
+ }
+
+ Job *job = pendingJobs.first();
+ if(!job)
+ return;
+ pendingJobs.remove(job);
+
+ QMap<QString, QString> map;
+ QString defaultTempDir;
+ if(Prefs::enableTempDir())
+ defaultTempDir = Prefs::tempDir();
+ else
+ defaultTempDir = locateLocal("tmp", "");
+ // For cases like "/tmp" where there is a missing /
+ defaultTempDir = KURL(defaultTempDir).path(1);
+ KTempFile tmp( defaultTempDir, ".wav" );
+ tmp.setAutoDelete(true);
+
+ QString wavFile;
+ QString args = job->device;
+ if(!args.isEmpty())
+ args = QString("?device=%1").arg(args);
+ args = args+"&fileNameTemplate=Track %{number}";
+ if(job->track < 10)
+ wavFile = QString("audiocd:/Wav/Track 0%1.wav%2").arg(job->track).arg(args);
+ else
+ wavFile = QString("audiocd:/Wav/Track %1.wav%2").arg(job->track).arg(args);
+
+ KURL source(wavFile);
+ KURL dest(tmp.name());
+
+ KIO::FileCopyJob *copyJob = new KIO::FileCopyJob(source, dest, 0644, false, true, false, false);
+ jobs.insert(copyJob, job);
+ connect(copyJob, SIGNAL(result(KIO::Job*)), this, SLOT(copyJobResult(KIO::Job*)));
+ connect(copyJob, SIGNAL(percent ( KIO::Job *, unsigned long)), this, SLOT(updateProgress ( KIO::Job *, unsigned long)));
+
+ emit jobsChanged();
+}
+
+/**
+ * Copies the data from the KIO Job. Uses this data to fill in the
+ * information dialog.
+ * @param copyjob the IO job to copy from
+ */
+void Ripper::copyJobResult(KIO::Job *copyjob){
+ if(!copyjob)
+ return;
+ KIO::FileCopyJob *copyJob = dynamic_cast<KIO::FileCopyJob*> (copyjob);
+ KNotifyClient::event("track ripped");
+
+ if(jobs.find(copyjob) == jobs.end())
+ return;
+ Job *newJob = jobs[copyjob];
+ jobs.remove(copyjob);
+
+ if(Prefs::beepAfterRip())
+ KNotifyClient::beep();
+
+ if ( copyJob->error() == 0 ){
+ emit updateProgress(newJob->id, 100);
+ newJob->location = copyJob->destURL().path();
+ emit( encodeWav(newJob));
+ }
+ else{
+ copyJob->showErrorDialog(0);
+ QFile file( (copyJob->destURL()).path());
+ file.remove();
+ emit updateProgress(newJob->id, -1);
+ delete newJob;
+ newJob = 0;
+ }
+
+ if(newJob && newJob->lastSongInAlbum){
+ if(Prefs::autoEjectAfterRip()){
+ // Don't eject device if a pending job has that device
+ Job *job = pendingJobs.first();
+ while( job ){
+ if( job->device == newJob->device )
+ break;
+ job = pendingJobs.next();
+ }
+ if( !job ){
+ deviceToEject = newJob->device;
+ QTimer::singleShot( Prefs::autoEjectDelay()*1000 + 500, this, SLOT(ejectNow()));
+ }
+ }
+ KNotifyClient::event("cd ripped");
+ }
+ tendToNewJobs();
+}
+
+void Ripper::ejectNow(){
+ emit eject(deviceToEject);
+}
+
+/**
+ * Update the progress of the file copy.
+ * @param job the current ioslave job in progress
+ * @param percent the current percent that the ioslave has done.
+ */
+void Ripper::updateProgress( KIO::Job *job, unsigned long percent){
+ if(job){
+ Job *ripJob = (jobs[job]);
+ if(ripJob)
+ emit updateProgress(ripJob->id, percent);
+ }
+}
+
+#include "ripper.moc"
+