Browse Source

2020-01-30 Fred Gleason <fredg@paravelsystems.com>

* Renamed the 'RDCddbRecord' class to 'RDDiscRecord'.
	* Removed support for CD-TEXT from the CD rippers.
	* Removed the icedax(1) dependency.
pull/537/head
Fred Gleason 3 years ago
parent
commit
cbe375adf0
  1. 4
      ChangeLog
  2. 4
      INSTALL
  3. 3
      configure.ac
  4. 2
      importers/Makefile.am
  5. 2
      lib/Makefile.am
  6. 8
      lib/lib.pro
  7. 23
      lib/librd_cs.ts
  8. 23
      lib/librd_de.ts
  9. 23
      lib/librd_es.ts
  10. 23
      lib/librd_fr.ts
  11. 23
      lib/librd_nb.ts
  12. 23
      lib/librd_nn.ts
  13. 23
      lib/librd_pt_BR.ts
  14. 12
      lib/rdcddblookup.cpp
  15. 11
      lib/rdcddblookup.h
  16. 278
      lib/rdcddbrecord.cpp
  17. 4
      lib/rdcdplayer.cpp
  18. 6
      lib/rdcdplayer.h
  19. 37
      lib/rdcut.cpp
  20. 267
      lib/rddisclookup.cpp
  21. 22
      lib/rddisclookup.h
  22. 314
      lib/rddiscrecord.cpp
  23. 61
      lib/rddiscrecord.h
  24. 2
      rdlibrary/audio_cart.cpp
  25. 10
      rdlibrary/cdripper.cpp
  26. 7
      rdlibrary/cdripper.h
  27. 6
      rdlibrary/disk_ripper.cpp
  28. 4
      rdlibrary/disk_ripper.h
  29. 2
      rivendell.spec.in
  30. 19
      tests/readcd_test.cpp

4
ChangeLog

@ -19443,3 +19443,7 @@
2020-01-29 Fred Gleason <fredg@paravelsystems.com>
* Refactored the 'RDCddbLookup' class into 'RDCddbLookup' and
'RDDiscLookup'.
2020-01-30 Fred Gleason <fredg@paravelsystems.com>
* Renamed the 'RDCddbRecord' class to 'RDDiscRecord'.
* Removed support for CD-TEXT from the CD rippers.
* Removed the icedax(1) dependency.

4
INSTALL

@ -7,10 +7,6 @@ system before building Rivendell:
Apache Web Server
Included with most distros, or available from: http://www.apache.org/.
Cdda2Wav
A CD ripper engine. Included in most distributions, but also available from
http://www.cdda2wav.de/.
Expat
A stream-oriented XML parser library. Available at https://libexpat.github.io/.

3
configure.ac

@ -172,18 +172,15 @@ else
AC_SUBST(USERMODE_PKG,"usermode usermode-gtk")
AC_SUBST(MYSQL_PKG,"mariadb")
AC_SUBST(QT4_MYSQL_PKG,"qt-mysql")
AC_SUBST(CDDA2WAV_PKG,"icedax")
else
if test $ar_distro_major -ge 6 ; then
AC_SUBST(USERMODE_PKG,"usermode")
AC_SUBST(MYSQL_PKG,"mysql")
AC_SUBST(QT4_MYSQL_PKG,"qt4-mysql")
AC_SUBST(CDDA2WAV_PKG,"icedax")
else
AC_SUBST(USERMODE_PKG,"usermode")
AC_SUBST(MYSQL_PKG,"mysql")
AC_SUBST(QT4_MYSQL_PKG,"qt-MySQL")
AC_SUBST(CDDA2WAV_PKG,"")
fi
fi
fi

2
importers/Makefile.am

@ -45,7 +45,7 @@ panel_copy_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ @QT4_LIBS@ @MUSICBRAINZ_LIBS@ -lQt3S
dist_rdcatch_copy_SOURCES = rdcatch_copy.cpp rdcatch_copy.h
nodist_rdcatch_copy_SOURCES = moc_rdcatch_copy.cpp
rdcatch_copy_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ @QT4_LIBS@ -lQt3Support
rdcatch_copy_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ @QT4_LIBS@ @MUSICBRAINZ_LIBS@ -lQt3Support
dist_rivendell_filter_SOURCES = rivendell_filter.cpp rivendell_filter.h
nodist_rivendell_filter_SOURCES = moc_rivendell_filter.cpp

2
lib/Makefile.am

@ -84,7 +84,6 @@ dist_librd_la_SOURCES = dbversion.h\
rdcatch_conf.cpp rdcatch_conf.h\
rdcatch_connect.cpp rdcatch_connect.h\
rdcddblookup.cpp rdcddblookup.h\
rdcddbrecord.cpp rdcddbrecord.h\
rdcdplayer.cpp rdcdplayer.h\
rdcdripper.cpp rdcdripper.h\
rdcheck_version.cpp rdcheck_version.h\
@ -112,6 +111,7 @@ dist_librd_la_SOURCES = dbversion.h\
rddelete.cpp rddelete.h\
rddialog.cpp rddialog.h\
rddisclookup.cpp rddisclookup.h\
rddiscrecord.cpp rddiscrecord.h\
rddownload.cpp rddownload.h\
rddropbox.cpp rddropbox.h\
rdedit_audio.cpp rdedit_audio.h\

8
lib/lib.pro

@ -2,7 +2,7 @@
#
# The lib/ QMake project file for Rivendell.
#
# (C) Copyright 2003-2018 Fred Gleason <fredg@paravelsystems.com>
# (C) Copyright 2003-2020 Fred Gleason <fredg@paravelsystems.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
@ -57,7 +57,7 @@ SOURCES += rdcartdrag.cpp
SOURCES += rdcatch_connect.cpp
SOURCES += rdcddblookup.cpp
SOURCES += rdcdplayer.cpp
SOURCES += rdcddbrecord.cpp
SOURCES += rddiscrecord.cpp
SOURCES += rdcheck_version.cpp
SOURCES += rdclock.cpp
SOURCES += rdcmd_cache.cpp
@ -75,6 +75,7 @@ SOURCES += rddatedecode.cpp
SOURCES += rddatepicker.cpp
SOURCES += rddatetime.cpp
SOURCES += rddb.cpp
SOURCES += rddisclookup.cpp
SOURCES += rddbheartbeat.cpp
SOURCES += rddebug.cpp
SOURCES += rddeck.cpp
@ -189,7 +190,8 @@ HEADERS += rdcartdrag.h
HEADERS += rdcatch_connect.h
HEADERS += rdcddblookup.h
HEADERS += rdcdplayer.h
HEADERS += rdcddbrecord.h
HEADERS += rddiscrecord.h
HEADERS += rddisclookup.h
HEADERS += rdcheck_version.h
HEADERS += rdclock.h
HEADERS += rdcmd_cache.h

23
lib/librd_cs.ts

@ -1418,6 +1418,29 @@ vozรญk</translation>
<translation>Ne</translation>
</message>
</context>
<context>
<name>RDDiscLookup</name>
<message>
<source>Multiple Matches Found!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>OK</source>
<translation type="unfinished">OK</translation>
</message>
<message>
<source>Cancel</source>
<translation type="unfinished">Zruลกit</translation>
</message>
<message>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unable to read CD.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RDEditAudio</name>
<message>

23
lib/librd_de.ts

@ -1408,6 +1408,29 @@ Cart</source>
<translation>So</translation>
</message>
</context>
<context>
<name>RDDiscLookup</name>
<message>
<source>Multiple Matches Found!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>OK</source>
<translation type="unfinished">OK</translation>
</message>
<message>
<source>Cancel</source>
<translation type="unfinished">Abbrechen</translation>
</message>
<message>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unable to read CD.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RDEditAudio</name>
<message>

23
lib/librd_es.ts

@ -1405,6 +1405,29 @@ Cartucho</translation>
<translation>Do</translation>
</message>
</context>
<context>
<name>RDDiscLookup</name>
<message>
<source>Multiple Matches Found!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>OK</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cancel</source>
<translation type="unfinished">Cancelar</translation>
</message>
<message>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unable to read CD.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RDEditAudio</name>
<message>

23
lib/librd_fr.ts

@ -1242,6 +1242,29 @@ Cart</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RDDiscLookup</name>
<message>
<source>Multiple Matches Found!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>OK</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unable to read CD.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RDEditAudio</name>
<message>

23
lib/librd_nb.ts

@ -1403,6 +1403,29 @@ Cart</source>
<translation>Su</translation>
</message>
</context>
<context>
<name>RDDiscLookup</name>
<message>
<source>Multiple Matches Found!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>OK</source>
<translation type="unfinished">OK</translation>
</message>
<message>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unable to read CD.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RDEditAudio</name>
<message>

23
lib/librd_nn.ts

@ -1403,6 +1403,29 @@ Cart</source>
<translation>Su</translation>
</message>
</context>
<context>
<name>RDDiscLookup</name>
<message>
<source>Multiple Matches Found!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>OK</source>
<translation type="unfinished">OK</translation>
</message>
<message>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unable to read CD.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RDEditAudio</name>
<message>

23
lib/librd_pt_BR.ts

@ -1409,6 +1409,29 @@ Cartรฃo</translation>
<translation>Dom</translation>
</message>
</context>
<context>
<name>RDDiscLookup</name>
<message>
<source>Multiple Matches Found!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>OK</source>
<translation type="unfinished">OK</translation>
</message>
<message>
<source>Cancel</source>
<translation type="unfinished">Cancelar</translation>
</message>
<message>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unable to read CD.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RDEditAudio</name>
<message>

12
lib/rdcddblookup.cpp

@ -1,6 +1,6 @@
// rdcddblookup.cpp
//
// A Qt class for accessing the FreeDB CD Database.
// RDDiscLookup instance class for accessing the FreeDB CD Database.
//
// (C) Copyright 2003-2020 Fred Gleason <fredg@paravelsystems.com>
//
@ -54,12 +54,14 @@ RDCddbLookup::~RDCddbLookup()
}
void RDCddbLookup::lookupRecord()
QString RDCddbLookup::sourceName() const
{
if(cddbRecord()->tracks()==0) {
return;
}
return QString("FreeDB");
}
void RDCddbLookup::lookupRecord()
{
lookup_username=rda->user()->name();
lookup_hostname=rda->libraryConf()->cddbServer();
lookup_appname="rivendell";

11
lib/rdcddblookup.h

@ -1,8 +1,8 @@
// rdcddblookup.h
//
// A Qt class for accessing the FreeDB CD Database.
// RDDiscLookup instance class for accessing the FreeDB CD Database.
//
// (C) Copyright 2003-2019 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2003-2020 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Library General Public License
@ -31,7 +31,7 @@
#include <qtcpsocket.h>
#include <rddisclookup.h>
#include <rdcddbrecord.h>
#include <rddiscrecord.h>
#include <rddialog.h>
//
@ -45,12 +45,15 @@ class RDCddbLookup : public RDDiscLookup
public:
RDCddbLookup(const QString &caption,FILE *profile_msgs,QWidget *parent=0);
~RDCddbLookup();
void lookupRecord();
QString sourceName() const;
private slots:
void readyReadData();
void errorData(QAbstractSocket::SocketError);
protected:
void lookupRecord();
private:
void FinishCddbLookup(RDCddbLookup::Result res);
QString DecodeString(QString &str);

278
lib/rdcddbrecord.cpp

@ -1,278 +0,0 @@
// rdcddbrecord.cpp
//
// A Container Class for CDDB Data.
//
// (C) Copyright 2003,2016 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Library General Public License
// version 2 as published by the Free Software Foundation.
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include <rdcddbrecord.h>
RDCddbRecord::RDCddbRecord()
{
clear();
}
void RDCddbRecord::clear()
{
cddb_tracks=0;
cddb_disc_id=0;
cddb_disc_length=0;
cddb_disc_title="";
cddb_disc_artist="";
cddb_disc_album="";
cddb_disc_author="";
cddb_disc_year=0;
cddb_disc_genre="";
cddb_disc_extended="";
cddb_disc_playorder="";
for(int i=0;i<CDROM_LEADOUT;i++) {
cddb_track_title[i]="";
cddb_track_extended[i]="";
cddb_track_artist[i]="";
cddb_track_isrc[i]="";
cddb_track_offset[i]=0;
}
}
int RDCddbRecord::tracks() const
{
return cddb_tracks;
}
void RDCddbRecord::setTracks(int num)
{
cddb_tracks=num;
}
unsigned RDCddbRecord::discLength() const
{
return cddb_disc_length;
}
void RDCddbRecord::setDiscLength(unsigned len)
{
cddb_disc_length=len;
}
unsigned RDCddbRecord::discId() const
{
return cddb_disc_id;
}
void RDCddbRecord::setDiscId(unsigned id)
{
cddb_disc_id=id;
}
QString RDCddbRecord::discTitle() const
{
return cddb_disc_title;
}
void RDCddbRecord::setDiscTitle(QString title)
{
int n;
cddb_disc_title=title;
if((n=title.find(" / "))!=-1) {
cddb_disc_artist=title.left(n);
cddb_disc_album=title.right(title.length()-n-3);
cddb_disc_author="";
}
else {
cddb_disc_album=title;
cddb_disc_artist=title;
cddb_disc_author="";
}
}
QString RDCddbRecord::discArtist() const
{
return cddb_disc_artist;
}
void RDCddbRecord::setDiscArtist(QString artist)
{
cddb_disc_artist=artist;
}
QString RDCddbRecord::discAlbum() const
{
return cddb_disc_album;
}
void RDCddbRecord::setDiscAlbum(QString album)
{
cddb_disc_album=album;
}
QString RDCddbRecord::discAuthor() const
{
return cddb_disc_author;
}
void RDCddbRecord::setDiscAuthor(QString author)
{
cddb_disc_author=author;
}
unsigned RDCddbRecord::discYear() const
{
return cddb_disc_year;
}
void RDCddbRecord::setDiscYear(unsigned year)
{
cddb_disc_year=year;
}
QString RDCddbRecord::discGenre() const
{
return cddb_disc_genre;
}
void RDCddbRecord::setDiscGenre(QString genre)
{
cddb_disc_genre=genre;
}
QString RDCddbRecord::discExtended() const
{
return cddb_disc_extended;
}
void RDCddbRecord::setDiscExtended(QString text)
{
cddb_disc_extended=text;
}
QString RDCddbRecord::discPlayOrder() const
{
return cddb_disc_playorder;
}
void RDCddbRecord::setDiscPlayOrder(QString order)
{
cddb_disc_playorder=order;
}
unsigned RDCddbRecord::trackOffset(int track) const
{
if(track<CDROM_LEADOUT) {
return cddb_track_offset[track];
}
return 0;
}
void RDCddbRecord::setTrackOffset(int track,unsigned frames)
{
if(track<CDROM_LEADOUT) {
cddb_track_offset[track]=frames;
}
}
QString RDCddbRecord::trackTitle(int track) const
{
if(track<CDROM_LEADOUT) {
return cddb_track_title[track];
}
return QString();
}
void RDCddbRecord::setTrackTitle(int track,QString title)
{
if(track<CDROM_LEADOUT) {
cddb_track_title[track]=title;
}
}
QString RDCddbRecord::trackExtended(int track) const
{
if(track<CDROM_LEADOUT) {
return cddb_track_extended[track];
}
return QString();
}
void RDCddbRecord::setTrackExtended(int track,QString text)
{
if(track<CDROM_LEADOUT) {
cddb_track_extended[track]=text;
}
}
QString RDCddbRecord::trackArtist(int track) const
{
if(track<CDROM_LEADOUT) {
return cddb_track_artist[track];
}
return QString();
}
void RDCddbRecord::setTrackArtist(int track,QString artist)
{
if(track<CDROM_LEADOUT) {
cddb_track_artist[track]=artist;
}
}
QString RDCddbRecord::isrc(int track) const
{
if(track<CDROM_LEADOUT) {
return cddb_track_isrc[track];
}
return QString();
}
void RDCddbRecord::setIsrc(int track,QString isrc)
{
if(track<CDROM_LEADOUT) {
cddb_track_isrc[track]=isrc;
}
}

4
lib/rdcdplayer.cpp

@ -2,7 +2,7 @@
//
// Abstract a Linux CDROM Device.
//
// (C) Copyright 2002-2019 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2002-2020 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Library General Public License
@ -197,7 +197,7 @@ int RDCdPlayer::rightVolume()
}
void RDCdPlayer::setCddbRecord(RDCddbRecord *rec)
void RDCdPlayer::setCddbRecord(RDDiscRecord *rec)
{
if(cdrom_track_count>0) {
rec->setTracks(cdrom_track_count);

6
lib/rdcdplayer.h

@ -2,7 +2,7 @@
//
// Abstract a Linux CDROM Device.
//
// (C) Copyright 2002-2003,2016 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2002-2020 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Library General Public License
@ -28,7 +28,7 @@
#include <qdialog.h>
#include <qtimer.h>
#include <rdcddbrecord.h>
#include <rddiscrecord.h>
//
// Driver Settings
@ -65,7 +65,7 @@ class RDCdPlayer : public QObject
int rightVolume();
RDCdPlayer::PlayMode playMode() const;
void setPlayMode(RDCdPlayer::PlayMode mode);
void setCddbRecord(RDCddbRecord *);
void setCddbRecord(RDDiscRecord *);
public slots:
void lock();

37
lib/rdcut.cpp

@ -24,22 +24,20 @@
#include <fcntl.h>
#include <qobject.h>
//Added by qt3to4:
#include <Q3Signal>
#include <rd.h>
#include <rdconf.h>
#include <rdwavefile.h>
#include <rdcut.h>
#include <rdtextvalidator.h>
#include <rdconfig.h>
#include <rddb.h>
#include <rdescape_string.h>
#include <rdgroup.h>
#include <rdweb.h>
#include <rdcopyaudio.h>
#include <rdtrimaudio.h>
#include "rd.h"
#include "rdconf.h"
#include "rdconfig.h"
#include "rdcopyaudio.h"
#include "rdcut.h"
#include "rddb.h"
#include "rddisclookup.h"
#include "rdescape_string.h"
#include "rdgroup.h"
#include "rdtextvalidator.h"
#include "rdtrimaudio.h"
#include "rdwavefile.h"
#include "rdweb.h"
//
// Global Classes
@ -222,13 +220,10 @@ QString RDCut::isrc(IsrcFormat fmt) const
{
QString str= RDGetSqlValue("CUTS","CUT_NAME",cut_name,"ISRC").
toString();
if((fmt==RDCut::RawIsrc)||(str.length()!=12)) {
if((fmt==RDCut::RawIsrc)||(!RDDiscLookup::isrcIsValid(str))) {
return str;
}
str.insert(2,"-");
str.insert(6,"-");
str.insert(9,"-");
return str;
return RDDiscLookup::formattedIsrc(str);
}

267
lib/rddisclookup.cpp

@ -22,11 +22,13 @@
#include <stdlib.h>
#include <string.h>
#include <qmessagebox.h>
#include <qtimer.h>
#include <qregexp.h>
#include <qdatetime.h>
#include <qmessagebox.h>
#include <q3process.h>
#include <qregexp.h>
#include <qtimer.h>
#include <discid/discid.h>
#include "rdtempdirectory.h"
#include "rddisclookup.h"
@ -36,6 +38,7 @@ RDDiscLookup::RDDiscLookup(const QString &caption,FILE *profile_msgs,
QWidget *parent)
: RDDialog(parent)
{
lookup_caption=caption;
lookup_profile_msgs=profile_msgs;
lookup_titles_label=new QLabel(tr("Multiple Matches Found!"),this);
@ -51,34 +54,6 @@ RDDiscLookup::RDDiscLookup(const QString &caption,FILE *profile_msgs,
lookup_cancel_button=new QPushButton(tr("Cancel"),this);
lookup_cancel_button->setFont(buttonFont());
connect(lookup_cancel_button,SIGNAL(clicked()),this,SLOT(cancelData()));
//
// Create Temporary Directory
//
char path[PATH_MAX];
strncpy(path,RDTempDirectory::basePath(),PATH_MAX);
strcat(path,"/XXXXXX");
if(mkdtemp(path)==NULL) {
QMessageBox::warning(this,caption+" - "+tr("Ripper Error"),
tr("Unable to create temporary directory!"));
}
else {
lookup_cdda_dir.setPath(path);
}
profile("created temp directory \""+lookup_cdda_dir.path()+"\"");
}
RDDiscLookup::~RDDiscLookup()
{
QStringList files=lookup_cdda_dir.entryList();
for(int i=0;i<files.size();i++) {
if((files[i]!=".")&&(files[i]!="..")) {
lookup_cdda_dir.remove(files[i]);
}
}
rmdir(lookup_cdda_dir.path());
profile("deleted temp directory \""+lookup_cdda_dir.path()+"\"");
}
@ -88,7 +63,7 @@ QSize RDDiscLookup::sizeHint() const
}
void RDDiscLookup::setCddbRecord(RDCddbRecord *rec)
void RDDiscLookup::setCddbRecord(RDDiscRecord *rec)
{
lookup_record=rec;
}
@ -96,21 +71,59 @@ void RDDiscLookup::setCddbRecord(RDCddbRecord *rec)
void RDDiscLookup::lookup()
{
profile("starting CD-TEXT lookup");
if(ReadCdText(lookup_cdda_dir.path(),rda->libraryConf()->ripperDevice())) {
emit lookupDone(RDDiscLookup::ExactMatch);
profile("CD-TEXT lookup success");
if(cddbRecord()->tracks()==0) {
return;
}
profile("CD-TEXT lookup failure");
//
// Get some basic disc parameters (CDDB DiskID, MusicBrainz mbid and,
// if enabled in rdadmin(1), MCN and ISRCs).
//
DiscId *disc=discid_new();
if(rda->libraryConf()->readIsrc()) {
if(discid_read(disc,rda->libraryConf()->ripperDevice().toUtf8())==0) {
QMessageBox::warning(this,caption()+" - "+tr("Error"),
tr("Unable to read CD.")+
"\n["+QString(discid_get_error_msg(disc))+"]");
discid_free(disc);
return;
}
}
else {
if(discid_read_sparse(disc,rda->libraryConf()->ripperDevice().toUtf8(),0)==0) {
QMessageBox::warning(this,caption()+" - "+tr("Error"),
tr("Unable to read CD.")+
"\n["+QString(discid_get_error_msg(disc))+"]");
discid_free(disc);
return;
}
}
cddbRecord()->setDiscId(QString(discid_get_freedb_id(disc)).toUInt(NULL,16));
cddbRecord()->setMbId(discid_get_id(disc));
cddbRecord()->setMbSubmissionUrl(discid_get_submission_url(disc));
if(rda->libraryConf()->readIsrc()) {
cddbRecord()->setMcn(discid_get_mcn(disc));
int first=discid_get_first_track_num(disc);
int last=discid_get_last_track_num(disc);
for(int i=first;i<=last;i++) {
if((i-first)<lookup_record->tracks()) {
cddbRecord()->setIsrc(i-first,
RDDiscLookup::normalizedIsrc(discid_get_track_isrc(disc,i)));
}
}
}
discid_free(disc);
//
// Call the low-level driver to complete the lookup.
//
lookupRecord();
}
bool RDDiscLookup::readIsrc()
QString RDDiscLookup::caption()
{
return ReadIsrcs(lookup_cdda_dir.path(),rda->libraryConf()->ripperDevice());
return lookup_caption;
}
@ -140,7 +153,7 @@ void RDDiscLookup::resizeEvent(QResizeEvent *e)
}
RDCddbRecord *RDDiscLookup::cddbRecord()
RDDiscRecord *RDDiscLookup::cddbRecord()
{
return lookup_record;
}
@ -168,129 +181,93 @@ QStringList *RDDiscLookup::titlesKey()
}
bool RDDiscLookup::ReadCdText(const QString &cdda_dir,const QString &cdda_dev)
bool RDDiscLookup::isrcIsValid(const QString &isrc)
{
RDProfile *title_profile=new RDProfile();
bool ret=false;
QString str;
QString cmd;
//
// Write the Track Title Data to a Temp File
// For formatting rules for International Standard Recording Codes,
// see https://en.wikipedia.org/wiki/International_Standard_Recording_Code
//
QByteArray output;
Q3Process *proc=new Q3Process(this);
proc->addArgument("cdda2wav");
proc->addArgument("-D");
proc->addArgument(cdda_dev);
proc->addArgument("--info-only");
proc->addArgument("-v");
proc->addArgument("titles");
proc->setWorkingDirectory(cdda_dir);
if(!proc->start()) {
delete proc;
profile("cdda2wav failed to start!");
return false;
}
while(proc->isRunning()) {
output=proc->readStderr();
if(output.size()>0) { // Work around icedax(1)'s idiotic user prompt
if(strncmp(output,"load cdrom please and press enter",33)==0) {
proc->kill();
delete proc;
profile("cdda2wav returned \""+output+"\", killing it!");
return false;
}
}
}
if(!proc->normalExit()) {
profile("cdda2wav crashed!");
delete proc;
return false;
}
if(proc->exitStatus()!=0) {
profile("cdda2wav return exit code "+
QString().sprintf("%d",proc->exitStatus()));
delete proc;
// NOTE: This makes no attempt to validate that the Country or Registrant
// codes actually exist in the IFPI registry!
//
QString str=isrc;
bool valid=false;
str.replace("-","");
if(str.length()!=12) {
return false;
}
delete proc;
//
// Read the Track Title Data File
// This could probably be done much more compactly with a regex.
//
for(int i=0;i<lookup_record->tracks();i++) {
title_profile->setSource(cdda_dir+QString().sprintf("/audio_%02d.inf",i+1));
str=title_profile->stringValue("","Albumtitle","");
str.remove("'");
if((!str.isEmpty())&&(str!="''")) {
lookup_record->setDiscTitle(str);
profile("setting DiscTitle to \""+str+"\"");
ret=true;
for(int i=0;i<12;i++) {
QChar::Category category=str.at(i).category();
switch(i) {
case 0: // Country Code
case 1:
valid=(category==QChar::Letter_Uppercase)||
(category==QChar::Letter_Lowercase);
break;
case 2: // Registrant Code
case 3:
case 4:
valid=(category==QChar::Letter_Uppercase)||
(category==QChar::Letter_Lowercase)||
(category==QChar::Number_DecimalDigit);
break;
case 5: // Designation Code
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
valid=(category==QChar::Number_DecimalDigit);
break;
}
str=title_profile->stringValue("","Albumperformer","");
str.remove("'");
if((!str.isEmpty())&&(str!="''")) {
lookup_record->setDiscArtist(str);
profile("setting DiscArtist to \""+str+"\"");
ret=true;
if(!valid) {
return false;
}
}
return true;
}
str=title_profile->stringValue("","Tracktitle","");
str.remove("'");
if((!str.isEmpty())&&(str!="''")) {
lookup_record->setTrackTitle(i,str);
profile("setting TrackTitle "+QString().sprintf("%d",i+1)+" to \""+str+"\"");
ret=true;
}
str=title_profile->stringValue("","Performer","");
str.remove("'");
if((!str.isEmpty())&&(str!="''")) {
lookup_record->setTrackArtist(i,str);
profile("setting TrackArtist "+QString().sprintf("%d",i+1)+" to \""+str+"\"");
ret=true;
QString RDDiscLookup::formattedIsrc(const QString &isrc,bool *ok)
{
if(RDDiscLookup::isrcIsValid(isrc)) {
if(ok!=NULL) {
*ok=true;
}
QString str=isrc;
str.insert(2,"-");
str.insert(6,"-");
str.insert(9,"-");
return str.toUpper();
}
if(ok!=NULL) {
*ok=false;
}
return ret;
return QString();
}
bool RDDiscLookup::ReadIsrcs(const QString &cdda_dir,const QString &cdda_dev)
QString RDDiscLookup::normalizedIsrc(const QString &isrc,bool *ok)
{
int err=0;
RDProfile *title_profile=new RDProfile();
RDProfile *isrc_profile=new RDProfile();
bool ret=false;
QString str;
QString cmd;
//
// Write the ISRC Data to a Temp File
//
cmd=QString("CURDIR=`pwd`;cd ")+
cdda_dir+";cdda2wav -D "+cdda_dev+
" --info-only -v trackid 2> /dev/null;cd $CURDIR";
if((err=system(cmd))!=0) {
return false;
}
//
// Read the ISRC Data File
//
for(int i=0;i<lookup_record->tracks();i++) {
isrc_profile->setSource(cdda_dir+QString().sprintf("/audio_%02d.inf",i+1));
str=isrc_profile->stringValue("","ISRC","");
str.remove("'");
str.remove("-");
if((!str.isEmpty())&&(str!="''")) {
lookup_record->setIsrc(i,str);
ret=true;
if(RDDiscLookup::isrcIsValid(isrc)) {
if(ok!=NULL) {
*ok=true;
}
QString str=isrc;
str.replace("-","");
return str.toUpper();
}
delete title_profile;
delete isrc_profile;
return ret;
if(ok!=NULL) {
*ok=false;
}
return QString();
}

22
lib/rddisclookup.h

@ -25,13 +25,12 @@
#include <stdio.h>
#include <qcombobox.h>
#include <qdir.h>
#include <qlabel.h>
#include <qpushbutton.h>
#include <qstringlist.h>
#include <qtcpsocket.h>
#include <rdcddbrecord.h>
#include <rddiscrecord.h>
#include <rddialog.h>
class RDDiscLookup : public RDDialog
@ -41,44 +40,45 @@ class RDDiscLookup : public RDDialog
enum Result {ExactMatch=0,PartialMatch=1,NoMatch=2,
ProtocolError=3,NetworkError=4};
RDDiscLookup(const QString &caption,FILE *profile_msgs,QWidget *parent=0);
~RDDiscLookup();
QSize sizeHint() const;
void setCddbRecord(RDCddbRecord *);
virtual QString sourceName() const=0;
void setCddbRecord(RDDiscRecord *);
void lookup();
bool readIsrc();
static bool isrcIsValid(const QString &isrc);
static QString formattedIsrc(const QString &isrc,bool *ok=NULL);
static QString normalizedIsrc(const QString &isrc,bool *ok=NULL);
signals:
void lookupDone(RDDiscLookup::Result);
protected slots:
virtual void lookupRecord()=0;
QString caption();
void okData();
void cancelData();
protected:
virtual void lookupRecord()=0;
void resizeEvent(QResizeEvent *e);
RDCddbRecord *cddbRecord();
RDDiscRecord *cddbRecord();
void profile(const QString &msg);
QComboBox *titlesBox();
QStringList *titlesKey();
private:
bool ReadCdText(const QString &cdda_dir,const QString &cdda_dev);
bool ReadIsrcs(const QString &cdda_dir,const QString &cdda_dev);
QLabel *lookup_titles_label;
QComboBox *lookup_titles_box;
QStringList lookup_titles_key;
QPushButton *lookup_ok_button;
QPushButton *lookup_cancel_button;
RDCddbRecord *lookup_record;
RDDiscRecord *lookup_record;
QTcpSocket *lookup_socket;
int lookup_state;
QString lookup_username;
QString lookup_appname;
QString lookup_appver;
QString lookup_hostname;
QDir lookup_cdda_dir;
FILE *lookup_profile_msgs;
QString lookup_caption;
};
#endif // RDDISCLOOKUP_H

314
lib/rddiscrecord.cpp

@ -0,0 +1,314 @@
// rddiscrecord.cpp
//
// Container Class for Compact Disc Metadata
//
// (C) Copyright 2003-2020 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Library General Public License
// version 2 as published by the Free Software Foundation.
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "rddiscrecord.h"
RDDiscRecord::RDDiscRecord()
{
clear();
}
void RDDiscRecord::clear()
{
disc_tracks=0;
disc_disc_id=0;
disc_disc_length=0;
disc_disc_title="";
disc_disc_artist="";
disc_disc_album="";
disc_disc_author="";
disc_disc_year=0;
disc_disc_genre="";
disc_disc_extended="";
disc_disc_playorder="";
for(int i=0;i<CDROM_LEADOUT;i++) {
disc_track_title[i]="";
disc_track_extended[i]="";
disc_track_artist[i]="";
disc_track_isrc[i]="";
disc_track_offset[i]=0;
}
}
int RDDiscRecord::tracks() const
{
return disc_tracks;
}
void RDDiscRecord::setTracks(int num)
{
disc_tracks=num;
}
unsigned RDDiscRecord::discLength() const
{
return disc_disc_length;
}
void RDDiscRecord::setDiscLength(unsigned len)
{
disc_disc_length=len;
}
unsigned RDDiscRecord::discId() const
{
return disc_disc_id;
}
void RDDiscRecord::setDiscId(unsigned id)
{
disc_disc_id=id;
}
QString RDDiscRecord::mcn() const
{
return disc_mcn;
}
void RDDiscRecord::setMcn(const QString &mcn)
{
disc_mcn=mcn;
}
QString RDDiscRecord::mbID() const
{
return disc_mb_id;
}
void RDDiscRecord::setMbId(const QString &str)
{
disc_mb_id=str;
}
QString RDDiscRecord::mbSubmissionUrl() const
{
return disc_mb_submission_url;
}
void RDDiscRecord::setMbSubmissionUrl(const QString &url)
{
disc_mb_submission_url=url;
}
QString RDDiscRecord::discTitle() const
{
return disc_disc_title;
}
void RDDiscRecord::setDiscTitle(QString title)
{
int n;
disc_disc_title=title;
if((n=title.find(" / "))!=-1) {
disc_disc_artist=title.left(n);
disc_disc_album=title.right(title.length()-n-3);
disc_disc_author="";
}
else {
disc_disc_album=title;
disc_disc_artist=title;
disc_disc_author="";
}
}
QString RDDiscRecord::discArtist() const
{
return disc_disc_artist;
}
void RDDiscRecord::setDiscArtist(QString artist)
{
disc_disc_artist=artist;
}
QString RDDiscRecord::discAlbum() const
{
return disc_disc_album;
}
void RDDiscRecord::setDiscAlbum(QString album)
{
disc_disc_album=album;
}
QString RDDiscRecord::discAuthor() const
{
return disc_disc_author;
}
void RDDiscRecord::setDiscAuthor(QString author)
{
disc_disc_author=author;
}
unsigned RDDiscRecord::discYear() const
{
return disc_disc_year;
}
void RDDiscRecord::setDiscYear(unsigned year)
{
disc_disc_year=year;
}
QString RDDiscRecord::discGenre() const
{
return disc_disc_genre;
}
void RDDiscRecord::setDiscGenre(QString genre)
{
disc_disc_genre=genre;
}
QString RDDiscRecord::discExtended() const
{
return disc_disc_extended;
}
void RDDiscRecord::setDiscExtended(QString text)
{
disc_disc_extended=text;
}
QString RDDiscRecord::discPlayOrder() const
{
return disc_disc_playorder;
}
void RDDiscRecord::setDiscPlayOrder(QString order)
{
disc_disc_playorder=order;
}
unsigned RDDiscRecord::trackOffset(int track) const
{
if(track<CDROM_LEADOUT) {
return disc_track_offset[track];
}
return 0;
}
void RDDiscRecord::setTrackOffset(int track,unsigned frames)
{
if(track<CDROM_LEADOUT) {
disc_track_offset[track]=frames;
}
}
QString RDDiscRecord::trackTitle(int track) const
{
if(track<CDROM_LEADOUT) {
return disc_track_title[track];
}
return QString();
}
void RDDiscRecord::setTrackTitle(int track,QString title)
{
if(track<CDROM_LEADOUT) {
disc_track_title[track]=title;
}
}
QString RDDiscRecord::trackExtended(int track) const
{
if(track<CDROM_LEADOUT) {
return disc_track_extended[track];
}
return QString();
}
void RDDiscRecord::setTrackExtended(int track,QString text)
{
if(track<CDROM_LEADOUT) {
disc_track_extended[track]=text;
}
}
QString RDDiscRecord::trackArtist(int track) const
{
if(track<CDROM_LEADOUT) {
return disc_track_artist[track];
}
return QString();
}
void RDDiscRecord::setTrackArtist(int track,QString artist)
{
if(track<CDROM_LEADOUT) {
disc_track_artist[track]=artist;
}
}
QString RDDiscRecord::isrc