File indexing completed on 2024-04-28 04:48:24

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 CDDACDIO_HEADER
0009 #define CDDACDIO_HEADER
0010 
0011 #include <QObject>
0012 #include <QString>
0013 
0014 #include <KLocalizedString>
0015 
0016 extern "C" {
0017 #include <cdio/cdio.h>
0018 #include <cdio/mmc.h>
0019 #include <cdio/paranoia/paranoia.h>
0020 }
0021 
0022 #define SECTORS_PER_SECOND 75
0023 #define FRAMES_PER_SECOND 75
0024 
0025 #define CD_FRAMESIZE_SAMPLES 588
0026 
0027 enum DriveCapability {
0028     CLOSE_TRAY = 0,
0029     EJECT,
0030     LOCK,
0031     SELECT_SPEED,
0032     SELECT_DISC,
0033     READ_MULTI_SESSION,
0034     MEDIA_CHANGED,
0035     READ_CDDA,
0036     C2_ERRS,
0037     READ_MODE2_FORM1,
0038     READ_MODE2_FORM2,
0039     READ_MCN,
0040     READ_ISRC
0041 };
0042 
0043 typedef QSet<DriveCapability> DriveCapabilities;
0044 
0045 class CDDACDIO : public QObject
0046 {
0047     Q_OBJECT
0048 
0049 public:
0050     explicit CDDACDIO(QObject *parent = nullptr);
0051     ~CDDACDIO() override;
0052 
0053     bool init(const QString &deviceFile = "/dev/cdrom");
0054     void reset();
0055 
0056     const QString getDeviceFile() const;
0057     const QString getVendor() const;
0058     const QString getModel() const;
0059     const QString getRevision() const;
0060 
0061     const DriveCapabilities getDriveCapabilities() const;
0062 
0063     void enableParanoiaFullMode(const bool enabled = true);
0064     void enableParanoiaNeverSkip(const bool never_skip = true);
0065     void setParanoiaMaxRetries(int max_retries); /* default: 20 */
0066 
0067     qint16 *paranoiaRead(void (*callback)(long, paranoia_cb_mode_t));
0068     int paranoiaSeek(const int sector, qint32 mode);
0069     bool paranoiaError(QString &errorMsg);
0070 
0071     bool mediaChanged();
0072 
0073     int firstSectorOfTrack(const int track);
0074     int lastSectorOfTrack(const int track);
0075 
0076     int firstSectorOfDisc();
0077     int lastSectorOfDisc();
0078 
0079     int firstTrackNum();
0080     int lastTrackNum();
0081 
0082     int numOfTracks();
0083     int numOfAudioTracks();
0084 
0085     int length();
0086     int numOfFrames(); // whole disc
0087     int lengthOfAudioTracks(); // length of all audio tracks in seconds
0088     int numOfFramesOfAudioTracks();
0089 
0090     // sum of skipped frames of non-audio tracks
0091     // (usually used to calculate overall percent)
0092     int numOfSkippedFrames(int n = 100);
0093 
0094     int lengthOfTrack(const int track); // in seconds
0095     int numOfFramesOfTrack(const int track);
0096     qreal sizeOfTrack(const int track); // in MiB
0097     int frameOffsetOfTrack(const int track);
0098 
0099     bool isAudioTrack(const int track);
0100     bool isDataTrack(const int track);
0101     bool isLastTrack(const int track);
0102 
0103     bool isAudioDisc(); // all tracks are audio tracks?
0104 
0105     // First element is first track after lead-in, list of offsets, last element offset of lead-out
0106     QList<quint32> discSignature();
0107 
0108     const QStringList prettyTOC();
0109 
0110     const QString getMCN();
0111     const QString getISRC(const int track);
0112     void fetchAndCacheSubchannelInfo();
0113 
0114     bool isPreemphasis(const int track);
0115 
0116     const QString msfOfTrack(const int track);
0117 
0118     static const QString LSN2MSF(const int lsn, const QChar frameSeparator = QChar(':'))
0119     {
0120         qreal length = (qreal)(lsn) / (qreal)FRAMES_PER_SECOND;
0121         int min = (int)length / 60;
0122         int sec = (int)length % 60;
0123         int frames = lsn - (((min * 60) + sec) * FRAMES_PER_SECOND);
0124         return QString("%1:%2%3%4").arg(min, 2, 10, QChar('0')).arg(sec, 2, 10, QChar('0')).arg(frameSeparator).arg(frames, 2, 10, QChar('0'));
0125     }
0126 
0127 Q_SIGNALS:
0128     void error(const QString &message, const QString &details = QString());
0129 
0130 private:
0131     cdrom_drive_t *drive;
0132     cdrom_paranoia_t *paranoia;
0133     CdIo_t *cdio;
0134 
0135     QString device_file;
0136 
0137     QString vendor;
0138     QString model;
0139     QString revision;
0140 
0141     int paranoia_mode;
0142     bool paranoia_never_skip;
0143     int paranoia_max_retries;
0144 
0145     DriveCapabilities capabilities;
0146 
0147     QString mcn;
0148     QMap<int, QString> track_isrcs;
0149 
0150     void p_detect_hardware();
0151     void p_free();
0152 };
0153 
0154 #endif