/** * 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., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "ripper.h" #include "prefs.h" #include #include #include #include #include #include #include /** * Constructor, load settings. */ Ripper::Ripper( TQObject* tqparent, const char* name) : TQObject(tqparent,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(); TQMap::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 (ioJob); disconnect(copyJob, TQT_SIGNAL(result(KIO::Job*)), this, TQT_SLOT(copyJobResult(KIO::Job*))); disconnect(copyJob, TQT_SIGNAL(percent ( KIO::Job *, unsigned long)), this, TQT_SLOT(updateProgress ( KIO::Job *, unsigned long))); TQString fileDestination = (copyJob->destURL()).path(); copyJob->kill(); TQFile 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){ TQMap::Iterator it; for( it = jobs.begin(); it != jobs.end(); ++it ){ if(it.data()->id == id){ KIO::FileCopyJob *copyJob = dynamic_cast (it.key()); if(copyJob){ TQString 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. TQFile file( fileDestination ); if(file.exists()) file.remove(); else { TQFile 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(TQString("Done removing Job:%1").tqarg(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").tqarg(job->track_artist).tqarg(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); TQMap map; TQString 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); TQString wavFile; TQString args = job->device; if(!args.isEmpty()) args = TQString("?device=%1").tqarg(args); args = args+"&fileNameTemplate=Track %{number}"; if(job->track < 10) wavFile = TQString("audiocd:/Wav/Track 0%1.wav%2").tqarg(job->track).tqarg(args); else wavFile = TQString("audiocd:/Wav/Track %1.wav%2").tqarg(job->track).tqarg(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, TQT_SIGNAL(result(KIO::Job*)), this, TQT_SLOT(copyJobResult(KIO::Job*))); connect(copyJob, TQT_SIGNAL(percent ( KIO::Job *, unsigned long)), this, TQT_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 (copyjob); KNotifyClient::event("track ripped"); if(jobs.tqfind(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); TQFile 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; TQTimer::singleShot( Prefs::autoEjectDelay()*1000 + 500, this, TQT_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"