File indexing completed on 2024-04-21 04:48:09

0001 /* AUDEX CDDA EXTRACTOR
0002  * SPDX-FileCopyrightText: Copyright (C) 2007 Marco Nelles
0003  * <https://userbase.kde.org/Audex>
0004  *
0005  * SPDX-License-Identifier: GPL-3.0-or-later
0006  */
0007 
0008 #ifndef AUDEX_HEADER
0009 #define AUDEX_HEADER
0010 
0011 #include <QDir>
0012 #include <QQueue>
0013 #include <QStorageInfo>
0014 #include <QString>
0015 #include <QTemporaryDir>
0016 #include <QTimer>
0017 
0018 #include <KLocalizedString>
0019 
0020 #include "models/cddamodel.h"
0021 #include "models/profilemodel.h"
0022 #include "utils/cddaextractthread.h"
0023 #include "utils/cuesheetwriter.h"
0024 #include "utils/discidcalculator.h"
0025 #include "utils/encoderwrapper.h"
0026 #include "utils/hashlist.h"
0027 #include "utils/parameters.h"
0028 #include "utils/playlist.h"
0029 #include "utils/schemeparser.h"
0030 #include "utils/upload.h"
0031 #include "utils/wavefilewriter.h"
0032 
0033 #include "preferences.h"
0034 
0035 class AudexJob : public QObject
0036 {
0037     Q_OBJECT
0038 public:
0039     explicit AudexJob(QObject *parent = nullptr)
0040         : QObject(parent)
0041     {
0042         source_filename = "";
0043         target_filename = "";
0044         _trackno = 0;
0045     }
0046     ~AudexJob() override
0047     {
0048     }
0049     void setSourceFilename(const QString &n)
0050     {
0051         source_filename = n;
0052     }
0053     QString sourceFilename() const
0054     {
0055         return source_filename;
0056     }
0057     void setTargetFilename(const QString &n)
0058     {
0059         target_filename = n;
0060     }
0061     QString targetFilename() const
0062     {
0063         return target_filename;
0064     }
0065     void setTrackNo(const int t)
0066     {
0067         _trackno = t;
0068     }
0069     int trackNo() const
0070     {
0071         return _trackno;
0072     }
0073 
0074 private:
0075     QString source_filename;
0076     QString target_filename;
0077     int _trackno;
0078 };
0079 
0080 class AudexJobs : public QObject
0081 {
0082     Q_OBJECT
0083 public:
0084     explicit AudexJobs(QObject *parent = nullptr)
0085         : QObject(parent)
0086     {
0087         job_in_progress = false;
0088     }
0089     ~AudexJobs() override
0090     {
0091         for (int i = 0; i < cache.count(); i++) {
0092             // make really sure all files are away
0093             QFile file(cache.at(i)->sourceFilename());
0094             if (file.exists())
0095                 file.remove();
0096             delete cache.at(i);
0097         }
0098     }
0099     AudexJob *orderJob()
0100     {
0101         if (job_queue.isEmpty()) {
0102             return nullptr;
0103         } else {
0104             job_in_progress = true;
0105             return job_queue.dequeue();
0106         }
0107     }
0108     void reportJobFinished()
0109     {
0110         job_in_progress = false;
0111     }
0112     bool jobInProgress()
0113     {
0114         return job_in_progress;
0115     }
0116     bool pendingJobs()
0117     {
0118         return (job_queue.count() > 0);
0119     }
0120 public Q_SLOTS:
0121     void addNewJob(const QString &sourceFilename, const QString &targetFilename, const int trackno)
0122     {
0123         auto *j = new AudexJob();
0124         j->setSourceFilename(sourceFilename);
0125         j->setTargetFilename(targetFilename);
0126         j->setTrackNo(trackno);
0127         job_queue.enqueue(j);
0128         cache.append(j);
0129         Q_EMIT newJobAvailable();
0130     }
0131 Q_SIGNALS:
0132     void newJobAvailable();
0133 
0134 private:
0135     QQueue<AudexJob *> job_queue;
0136     QList<AudexJob *> cache;
0137     bool job_in_progress;
0138 };
0139 
0140 class Audex : public QObject
0141 {
0142     Q_OBJECT
0143 
0144 public:
0145     Audex(QWidget *parent, ProfileModel *profile_model, CDDAModel *cdda_model);
0146     ~Audex() override;
0147 
0148     bool prepare();
0149 
0150 public Q_SLOTS:
0151     void start();
0152     void cancel();
0153 
0154     const QStringList &extractLog();
0155     const QStringList &encoderLog();
0156 
0157 private Q_SLOTS:
0158     void start_extract();
0159     void finish_extract();
0160     void start_encode();
0161     void finish_encode();
0162 
0163     void calculate_speed_extract();
0164     void calculate_speed_encode();
0165 
0166     void progress_extract(int percent_of_track, int sector, int overall_sectors_read);
0167     void progress_encode(int percent);
0168 
0169     void write_to_wave(const QByteArray &data);
0170 
0171     void slot_error(const QString &message, const QString &details = QString());
0172     void slot_warning(const QString &message);
0173     void slot_info(const QString &message);
0174 
0175     void check_if_thread_still_running();
0176 
0177 Q_SIGNALS:
0178     void changedExtractTrack(int no, int total, const QString &artist, const QString &title);
0179     void changedEncodeTrack(int no, int total, const QString &filename);
0180 
0181     void progressExtractTrack(int percent);
0182     void progressExtractOverall(int percent);
0183     void progressEncodeTrack(int percent);
0184     void progressEncodeOverall(int percent);
0185 
0186     void speedExtract(double times);
0187     void speedEncode(double times);
0188 
0189     void finished(bool successful);
0190 
0191     void timeout();
0192 
0193     void error(const QString &message, const QString &details = QString());
0194     void warning(const QString &message);
0195     void info(const QString &message);
0196 
0197 private:
0198     QWidget *parent;
0199     ProfileModel *profile_model;
0200     CDDAModel *cdda_model;
0201     EncoderWrapper *encoder_wrapper;
0202     CDDAExtractThread *cdda_extract_thread;
0203     AudexJobs *jobs;
0204     WaveFileWriter *wave_file_writer;
0205     QTemporaryDir tmp_dir;
0206 
0207     QString p_profile_name;
0208     QString p_suffix;
0209     bool p_single_file;
0210 
0211     bool construct_target_filename(QString &targetFilename,
0212                                    int trackno,
0213                                    int cdno,
0214                                    int nooftracks,
0215                                    int gindex,
0216                                    const QString &artist,
0217                                    const QString &title,
0218                                    const QString &tartist,
0219                                    const QString &ttitle,
0220                                    const QString &date,
0221                                    const QString &genre,
0222                                    const QString &isrc,
0223                                    const QString &ext,
0224                                    const QString &basepath,
0225                                    bool fat32_compatible,
0226                                    bool replacespaceswithunderscores,
0227                                    bool _2digitstracknum,
0228                                    bool overwrite_existing_files,
0229                                    bool is_first_track);
0230 
0231     bool construct_target_filename_for_singlefile(QString &targetFilename,
0232                                                   int cdno,
0233                                                   int nooftracks,
0234                                                   const QString &artist,
0235                                                   const QString &title,
0236                                                   const QString &date,
0237                                                   const QString &genre,
0238                                                   const QString &ext,
0239                                                   const QString &basepath,
0240                                                   bool overwrite_existing_files);
0241 
0242     bool check();
0243 
0244     QString target_dir;
0245 
0246     bool p_finished;
0247     bool p_finished_successful;
0248     void request_finish(bool successful);
0249     void execute_finish();
0250 
0251     int process_counter;
0252     bool timeout_done;
0253     int timeout_counter;
0254 
0255     /*PROCESS 1: EXTRACTING*/
0256     QString ex_track_source_filename;
0257     QString ex_track_target_filename;
0258     int ex_track_index;
0259     int ex_track_count;
0260     QTimer *timer_extract;
0261     int current_sector;
0262     int last_measuring_point_sector;
0263     int overall_frames;
0264 
0265     /*PROCESS 2: ENCODING*/
0266     QString en_track_filename;
0267     QString en_track_target_filename;
0268     int en_track_index;
0269     int en_track_count;
0270     QTimer *timer_encode;
0271     int current_encoder_percent;
0272     int last_measuring_point_encoder_percent;
0273 
0274     bool p_prepare_dir(QString &filename, const QString &targetDirIfRelative, const bool overwrite = false);
0275     bool p_mkdir(const QString &absoluteFilePath);
0276     qreal p_size_of_all_files(const QStringList &filenames) const;
0277 };
0278 
0279 #endif