11 # include <cdio/cdda.h>
12 # include <cdio/paranoia.h>
13 #endif //def HAVE_CDIO
21 #include <QApplication>
45 #include <mythtv/libmythui/mythscreenstack.h>
46 #include <mythtv/libmythui/mythprogressdialog.h>
58 #include "editmetadata.h"
64 #ifndef cdrom_paranoia
65 #define cdrom_paranoia cdrom_paranoia_t
66 #endif // cdrom_paranoia
68 #ifndef CD_FRAMESIZE_RAW
69 # define CD_FRAMESIZE_RAW CDIO_CD_FRAMESIZE_RAW
70 #endif // CD_FRAMESIZE_RAW
74 (QEvent::Type) QEvent::registerEventType();
76 (QEvent::Type) QEvent::registerEventType();
78 (QEvent::Type) QEvent::registerEventType();
80 (QEvent::Type) QEvent::registerEventType();
82 (QEvent::Type) QEvent::registerEventType();
84 (QEvent::Type) QEvent::registerEventType();
86 (QEvent::Type) QEvent::registerEventType();
88 (QEvent::Type) QEvent::registerEventType();
90 (QEvent::Type) QEvent::registerEventType();
92 (QEvent::Type) QEvent::registerEventType();
94 (QEvent::Type) QEvent::registerEventType();
97 MThread(
"CDScanner"), m_parent(ripper)
111 MThread(
"CDEjector"), m_parent(ripper)
127 QByteArray devname = cddevice.toAscii();
128 cdrom_drive *device = cdda_identify(devname.constData(), 0, NULL);
132 LOG(VB_GENERAL, LOG_ERR,
133 QString(
"Error: %1('%2',track=%3) failed at cdda_identify()").
134 arg(__func__).arg(cddevice).arg(tracknum));
138 if (cdda_open(device))
140 LOG(VB_GENERAL, LOG_ERR,
141 QString(
"Error: %1('%2',track=%3) failed at cdda_open() - cdda not supported").
142 arg(__func__).arg(cddevice).arg(tracknum));
148 if (cdda_track_audiop (device, tracknum))
150 cdda_verbose_set(device, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT);
151 long int start = cdda_track_firstsector(device, tracknum);
152 long int end = cdda_track_lastsector( device, tracknum);
154 return end - start + 1;
156 LOG(VB_GENERAL, LOG_ERR,
157 QString(
"Error: cdrip - cdda_track_audiop(%1) returned 0").arg(cddevice));
173 QVector<RipTrack*> *tracks,
int quality) :
175 m_parent(parent), m_quit(
false),
176 m_CDdevice(device), m_quality(quality),
177 m_tracks(tracks), m_totalSectors(0),
178 m_totalSectorsDone(0), m_lastTrackPct(0),
181 #ifdef WIN32 // libcdio needs the drive letter with no path
224 QApplication::postEvent(
227 QApplication::postEvent(
230 QApplication::postEvent(
240 for (
int trackno = 0; trackno <
m_tracks->size(); trackno++)
250 QString lcd_tots = QObject::tr(
"Importing ") + tots;
251 QList<LCDTextItem> textItems;
253 lcd_tots,
"Generic",
false));
254 lcd->switchToGeneric(textItems);
260 std::auto_ptr<Encoder> encoder;
262 for (
int trackno = 0; trackno <
m_tracks->size(); trackno++)
267 QApplication::postEvent(
270 QString(
"Track %1 of %2")
271 .arg(trackno + 1).arg(
m_tracks->size())));
273 QApplication::postEvent(
277 track =
m_tracks->at(trackno)->metadata;
281 textstatus = track->
Title();
282 QApplication::postEvent(
286 QApplication::postEvent(
289 QApplication::postEvent(
303 if (encodertype ==
"mp3")
307 titleTrack, mp3usevbr));
323 if (!encoder->isValid())
325 QApplication::postEvent(
329 "Encoder failed to open file for writing"));
330 LOG(VB_GENERAL, LOG_ERR,
"MythMusic: Encoder failed"
331 " to open file for writing");
341 QApplication::postEvent(
344 "Failed to create encoder"));
345 LOG(VB_GENERAL, LOG_ERR,
"MythMusic: No encoder, failing");
369 if (!PostRipCDScript.isEmpty())
372 QApplication::postEvent(
381 QByteArray devname = cddevice.toAscii();
382 cdrom_drive *device = cdda_identify(devname.constData(), 0, NULL);
386 LOG(VB_GENERAL, LOG_ERR,
387 QString(
"cdda_identify failed for device '%1', "
388 "CDRipperThread::ripTrack(tracknum = %2) exiting.")
389 .arg(cddevice).arg(tracknum));
393 if (cdda_open(device))
395 LOG(VB_MEDIA, LOG_INFO,
396 QString(
"Error: %1('%2',track=%3) failed at cdda_open() - cdda not supported")
397 .arg(__func__).arg(cddevice).arg(tracknum));
402 cdda_verbose_set(device, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT);
403 long int start = cdda_track_firstsector(device, tracknum);
404 long int end = cdda_track_lastsector(device, tracknum);
405 LOG(VB_MEDIA, LOG_INFO, QString(
"%1(%2,track=%3) start=%4 end=%5")
406 .arg(__func__).arg(cddevice).arg(tracknum).arg(start).arg(end));
408 cdrom_paranoia *paranoia = paranoia_init(device);
410 paranoia_modeset(paranoia, PARANOIA_MODE_FULL |
411 PARANOIA_MODE_NEVERSKIP);
413 paranoia_modeset(paranoia, PARANOIA_MODE_OVERLAP);
415 paranoia_seek(paranoia, start, SEEK_SET);
417 long int curpos =
start;
420 QApplication::postEvent(
431 if (encoder->
addSamples(buffer, CD_FRAMESIZE_RAW))
448 QApplication::postEvent(
452 QApplication::postEvent(
458 int newTrackPct = (
int) (100.0 / (
double) ((double) (end - start + 1) /
459 (double) (curpos - start)));
463 QApplication::postEvent(
467 QApplication::postEvent(
477 lcd->setGenericProgress(fProgress);
489 paranoia_free(paranoia);
492 return (curpos - start + 1) * CD_FRAMESIZE_RAW;
510 m_compilationCheck(NULL),
515 m_switchTitleArtist(NULL),
518 m_searchArtistButton(NULL),
519 m_searchAlbumButton(NULL),
520 m_searchGenreButton(NULL),
524 m_somethingwasripped(
false),
525 m_mediaMonitorActive(
false),
529 m_ejectThread(NULL), m_scanThread(NULL)
588 LOG(VB_GENERAL, LOG_ERR,
589 "Missing theme elements for screen 'cdripper'");
619 QTimer::singleShot(500,
this, SLOT(
startScanCD()));
629 bool handled =
false;
633 for (
int i = 0; i < actions.size() && !handled; i++)
635 QString
action = actions[i];
638 if (action ==
"EDIT" || action ==
"INFO")
657 QString message = QObject::tr(
"Scanning CD. Please Wait ...");
672 bool isCompilation =
false;
695 isCompilation =
true;
712 QString title = metadata->
Title();
746 LOG(VB_MEDIA, LOG_INFO, QString(
"Ripper::%1 CD='%2'").
762 QVector<RipTrack*>::iterator it;
766 if (track && !track->
isNew)
787 QString artist = metadata->
Artist();
788 QString album = metadata->
Album();
789 QString title = metadata->
Title();
792 QString queryString(
"SELECT song_id, "
793 "CONCAT_WS('/', music_directories.path, music_songs.filename) AS filename "
795 "LEFT JOIN music_artists"
796 " ON music_songs.artist_id=music_artists.artist_id "
797 "LEFT JOIN music_albums"
798 " ON music_songs.album_id=music_albums.album_id "
799 "LEFT JOIN music_directories "
800 " ON music_songs.directory_id=music_directories.directory_id "
801 "WHERE artist_name REGEXP \'");
802 QString token = artist;
803 token.replace(QRegExp(
"(/|\\\\|:|\'|\\,|\\!|\\(|\\)|\"|\\?|\\|)"),
806 queryString += token +
"\' AND " +
"album_name REGEXP \'";
808 token.replace(QRegExp(
"(/|\\\\|:|\'|\\,|\\!|\\(|\\)|\"|\\?|\\|)"),
810 queryString += token +
"\' AND " +
"name REGEXP \'";
812 token.replace(QRegExp(
"(/|\\\\|:|\'|\\,|\\!|\\(|\\)|\"|\\?|\\|)"),
814 queryString += token +
"\' ORDER BY artist_name, album_name,"
815 " name, song_id, filename LIMIT 1";
826 int trackID = query.
value(0).toInt();
830 if (!QFile::remove(filename))
832 LOG(VB_GENERAL, LOG_NOTICE, QString(
"Ripper::deleteExistingTrack() "
833 "Could not delete %1")
840 deleteQuery.
prepare(
"DELETE FROM music_songs"
841 " WHERE song_id = :SONG_ID");
842 deleteQuery.
bindValue(
":SONG_ID", trackID);
843 if (!deleteQuery.
exec())
866 for (
int trackno = 0; trackno <
m_tracks->size(); ++trackno)
868 data =
m_tracks->at(trackno)->metadata;
897 for (
int trackno = 0; trackno <
m_tracks->size(); ++trackno)
899 data =
m_tracks->at(trackno)->metadata;
916 for (
int trackno = 0; trackno <
m_tracks->size(); ++trackno)
918 data =
m_tracks->at(trackno)->metadata;
936 for (
int trackno = 0; trackno <
m_tracks->size(); ++trackno)
938 data =
m_tracks->at(trackno)->metadata;
941 data->
setYear(newyear.toInt());
956 for (
int trackno = 0; trackno <
m_tracks->size(); ++trackno)
958 data =
m_tracks->at(trackno)->metadata;
976 for (
int trackno = 0; trackno <
m_tracks->size(); ++trackno)
979 data =
m_tracks->at(trackno)->metadata;
1007 for (
int track = 0; track <
m_tracks->size(); ++track)
1009 data =
m_tracks->at(track)->metadata;
1038 if (statusDialog->
Create())
1040 connect(statusDialog, SIGNAL(Result(
bool)), SLOT(
RipComplete(
bool)));
1044 delete statusDialog;
1061 lcd->switchToTime();
1070 QString message = tr(
"Ejecting CD. Please Wait ...");
1090 LOG(VB_MEDIA, LOG_INFO, __PRETTY_FUNCTION__);
1095 LOG(VB_MEDIA, LOG_INFO, QString(
"Ripper::%1 '%2'").
1137 item->
SetData(qVariantFromValue(track));
1149 item->
SetText(QString::number(metadata->
Track()),
"track");
1153 int length = track->
length / 1000;
1160 s.sprintf(
"%02d:%02d", min, sec);
1174 QString msg = tr(
"Select an Artist");
1180 if (!searchDlg->
Create())
1186 connect(searchDlg, SIGNAL(haveResult(QString)), SLOT(
setArtist(QString)));
1198 QString msg = tr(
"Select an Album");
1204 if (!searchDlg->
Create())
1210 connect(searchDlg, SIGNAL(haveResult(QString)), SLOT(
setAlbum(QString)));
1222 QString msg = tr(
"Select a Genre");
1233 if (!searchDlg->
Create())
1239 connect(searchDlg, SIGNAL(haveResult(QString)), SLOT(
setGenre(QString)));
1266 if (!editDialog->
Create())
1284 QVariant
data = QVariant::fromValue(track);
1319 QString msg = tr(
"This track has been disabled because it is already "
1320 "present in the database.\n"
1321 "Do you want to permanently delete the existing "
1336 menu->
AddButton(tr(
"Yes, Delete"), QVariant::fromValue(track));
1342 QVector<RipTrack*>::iterator it;
1368 if (dce->
GetId() ==
"conflictmenu")
1381 track->
isNew =
true;
1403 QVector<RipTrack*> *tracks,
int quality)
1405 m_tracks(tracks), m_quality(quality),
1406 m_CDdevice(device), m_overallText(NULL),
1407 m_trackText(NULL), m_statusText(NULL),
1408 m_overallPctText(NULL), m_trackPctText(NULL),
1409 m_overallProgress(NULL), m_trackProgress(NULL),
1410 m_ripperThread(NULL)
1420 lcd->switchToTime();
1449 bool handled =
false;
1450 QStringList actions;
1453 for (
int i = 0; i < actions.size() && !handled; i++)
1455 QString
action = actions[i];
1459 if (action ==
"ESCAPE" &&
1463 ShowOkPopup(tr(
"Cancel ripping the CD?"),
this, NULL,
true);
1550 ShowOkPopup(tr(
"The encoder failed to create the file.\n"
1551 "Do you have write permissions"
1552 " for the music directory?"));
1557 LOG(VB_GENERAL, LOG_ERR,
"Received an unknown event type!");