264 changes: 168 additions & 96 deletions mythplugins/mythmusic/mythmusic/cdrip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ using namespace std;
#include <QRegExp>
#include <QKeyEvent>
#include <QEvent>
#include <QFile>

// MythTV plugin includes
#include <mythcontext.h>
#include <mythdb.h>
#include <lcddevice.h>
#include <mythmediamonitor.h>
#include <dialogbox.h>

// MythUI
#include <mythdialogbox.h>
Expand Down Expand Up @@ -669,7 +669,6 @@ void Ripper::ScanFinished()
m_tracks->clear();

bool isCompilation = false;
bool newTune = true;
if (m_decoder)
{
QString label;
Expand All @@ -679,8 +678,6 @@ void Ripper::ScanFinished()
m_albumName.clear();
m_genreName.clear();
m_year.clear();
bool yesToAll = false;
bool noToAll = false;

for (int trackno = 0; trackno < m_decoder->getNumTracks(); trackno++)
{
Expand All @@ -691,7 +688,6 @@ void Ripper::ScanFinished()
{
ripTrack->metadata = metadata;
ripTrack->length = metadata->Length();
ripTrack->active = true;

if (metadata->Compilation())
{
Expand All @@ -713,73 +709,12 @@ void Ripper::ScanFinished()
m_year = QString::number(metadata->Year());

QString title = metadata->Title();
newTune = isNewTune(m_artistName, m_albumName, title);
ripTrack->isNew = isNewTune(m_artistName, m_albumName, title);

ripTrack->active = ripTrack->isNew;

m_tracks->push_back(ripTrack);

if (newTune)
{
m_tracks->push_back(ripTrack);
}
else
{
if (yesToAll)
{
deleteTrack(m_artistName, m_albumName, title);
m_tracks->push_back(ripTrack);
}
else if (noToAll)
{
delete ripTrack;
delete metadata;
continue;
}
else
{
DialogBox *dlg = new DialogBox(
GetMythMainWindow(),
tr("Artist: %1\n"
"Album: %2\n"
"Track: %3\n\n"
"This track is already in the database. \n"
"Do you want to remove the existing track?")
.arg(m_artistName).arg(m_albumName).arg(title));

dlg->AddButton("No");
dlg->AddButton("No To All");
dlg->AddButton("Yes");
dlg->AddButton("Yes To All");
DialogCode res = dlg->exec();
dlg->deleteLater();
dlg = NULL;

if (kDialogCodeButton0 == res)
{
delete ripTrack;
delete metadata;
}
else if (kDialogCodeButton1 == res)
{
noToAll = true;
delete ripTrack;
delete metadata;
}
else if (kDialogCodeButton2 == res)
{
deleteTrack(m_artistName, m_albumName, title);
m_tracks->push_back(ripTrack);
}
else if (kDialogCodeButton3 == res)
{
yesToAll = true;
deleteTrack(m_artistName, m_albumName, title);
m_tracks->push_back(ripTrack);
}
else // treat cancel as no
{
delete ripTrack;
delete metadata;
}
}
}
}
else
delete ripTrack;
Expand Down Expand Up @@ -821,8 +756,37 @@ void Ripper::scanCD(void)
m_decoder->setDevice(m_CDdevice);
}

void Ripper::deleteTrack(QString& artist, QString& album, QString& title)
void Ripper::deleteAllExistingTracks(void)
{
QVector<RipTrack*>::iterator it;
for (it = m_tracks->begin(); it < m_tracks->end(); ++it)
{
RipTrack *track = (*it);
if (track && !track->isNew)
{
if (deleteExistingTrack(track))
{
track->isNew = true;
toggleTrackActive(track);
}
}
}
}

bool Ripper::deleteExistingTrack(RipTrack *track)
{
if (!track)
return false;

Metadata *metadata = track->metadata;

if (!metadata)
return false;

QString artist = metadata->Artist();
QString album = metadata->Album();
QString title = metadata->Title();

MSqlQuery query(MSqlQuery::InitCon());
QString queryString("SELECT song_id, "
"CONCAT_WS('/', music_directories.path, music_songs.filename) AS filename "
Expand All @@ -847,31 +811,43 @@ void Ripper::deleteTrack(QString& artist, QString& album, QString& title)
token.replace(QRegExp("(/|\\\\|:|\'|\\,|\\!|\\(|\\)|\"|\\?|\\|)"),
QString("."));
queryString += token + "\' ORDER BY artist_name, album_name,"
" name, song_id, filename";
" name, song_id, filename LIMIT 1";
query.prepare(queryString);

if (!query.exec() || !query.isActive())
{
MythDB::DBError("Search music database", query);
return;
return false;
}

while (query.next())
if (query.next())
{
int trackID = query.value(0).toInt();
QString filename = query.value(1).toString();
QString filename = gMusicData->musicDir + query.value(1).toString();

// delete file
QFile::remove(gMusicData->musicDir + filename);
if (!QFile::remove(filename))
{
LOG(VB_GENERAL, LOG_NOTICE, QString("Ripper::deleteExistingTrack() "
"Could not delete %1")
.arg(filename));
return false;
}

// remove database entry
MSqlQuery deleteQuery(MSqlQuery::InitCon());
deleteQuery.prepare("DELETE FROM music_songs"
" WHERE song_id = :SONG_ID");
deleteQuery.bindValue(":SONG_ID", trackID);
if (!deleteQuery.exec())
{
MythDB::DBError("Delete Track", deleteQuery);
return false;
}
return true;
}

return false;
}

bool Ripper::somethingWasRipped()
Expand Down Expand Up @@ -1045,7 +1021,7 @@ void Ripper::switchTitlesAndArtists()

void Ripper::startRipper(void)
{
if (m_tracks->size() == 0)
if (m_tracks->isEmpty())
{
ShowOkPopup(tr("There are no tracks to rip?"));
return;
Expand Down Expand Up @@ -1136,7 +1112,7 @@ void Ripper::ejectCD()

void Ripper::updateTrackList(void)
{
if (m_tracks->size() == 0)
if (m_tracks->isEmpty())
return;

QString tmptitle;
Expand All @@ -1157,7 +1133,12 @@ void Ripper::updateTrackList(void)

item->setCheckable(true);

item->SetData(qVariantFromValue(metadata));
item->SetData(qVariantFromValue(track));

if (track->isNew)
item->DisplayState("new", "yes");
else
item->DisplayState("new", "no");

if (track->active)
item->setChecked(MythUIButtonListItem::FullChecked);
Expand Down Expand Up @@ -1266,10 +1247,15 @@ void Ripper::setGenre(QString genre)

void Ripper::showEditMetadataDialog(MythUIButtonListItem *item)
{
if (!item || m_tracks->size() == 0)
if (!item || m_tracks->isEmpty())
return;

Metadata *editMeta = qVariantValue<Metadata *>(item->GetData());
RipTrack *track = qVariantValue<RipTrack *>(item->GetData());

if (!track)
return;

Metadata *editMeta = track->metadata;

MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();

Expand All @@ -1292,13 +1278,29 @@ void Ripper::metadataChanged(void)
updateTrackList();
}

void Ripper::toggleTrackActive(RipTrack* track)
{
QVariant data = QVariant::fromValue(track);
MythUIButtonListItem *item = m_trackList->GetItemByData(data);
if (item)
{
toggleTrackActive(item);
}
}

void Ripper::toggleTrackActive(MythUIButtonListItem *item)
{
if (m_tracks->size() == 0 || !item)
if (m_tracks->isEmpty() || !item)
return;

RipTrack *track = m_tracks->at(m_trackList->GetItemPos(item));

if (!track->active && !track->isNew)
{
ShowConflictMenu(track);
return;
}

track->active = !track->active;

if (track->active)
Expand All @@ -1309,6 +1311,31 @@ void Ripper::toggleTrackActive(MythUIButtonListItem *item)
updateTrackLengths();
}

void Ripper::ShowConflictMenu(RipTrack* track)
{
MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");

QString msg = tr("This track has been disabled because it is already "
"present in the database.\n"
"Do you want to permanently delete the existing "
"file(s)?");
MythDialogBox *menu = new MythDialogBox(msg, popupStack, "conflictmenu",
true);

if (menu->Create())
popupStack->AddScreen(menu);
else
{
delete menu;
return;
}

menu->SetReturnEvent(this, "conflictmenu");
menu->AddButton(tr("No, Cancel"));
menu->AddButton(tr("Yes, Delete"), QVariant::fromValue(track));
menu->AddButton(tr("Yes, Delete All"));
}

void Ripper::updateTrackLengths()
{
QVector<RipTrack*>::iterator it;
Expand All @@ -1331,6 +1358,44 @@ void Ripper::updateTrackLengths()
}
}

void Ripper::customEvent(QEvent* event)
{
if (event->type() == DialogCompletionEvent::kEventType)
{
DialogCompletionEvent *dce = static_cast<DialogCompletionEvent *>(event);

if (dce->GetId() == "conflictmenu")
{
int buttonNum = dce->GetResult();
RipTrack *track = qVariantValue<RipTrack *>(dce->GetData());

switch (buttonNum)
{
case 0:
// Do nothing
break;
case 1:
if (deleteExistingTrack(track))
{
track->isNew = true;
toggleTrackActive(track);
}
break;
case 2:
deleteAllExistingTracks();
break;
default:
break;
}
}

return;
}

MythUIType::customEvent(event);
}


///////////////////////////////////////////////////////////////////////////////

RipStatus::RipStatus(MythScreenStack *parent, const QString &device,
Expand Down Expand Up @@ -1393,20 +1458,13 @@ bool RipStatus::keyPressEvent(QKeyEvent *event)
handled = true;


if (action == "ESCAPE")
if (action == "ESCAPE" &&
m_ripperThread && m_ripperThread->isRunning())
{
if (m_ripperThread && m_ripperThread->isRunning())
{
if (MythPopupBox::showOkCancelPopup(GetMythMainWindow(),
"Stop Rip?",
tr("Are you sure you want to cancel ripping the CD?"),
false))
{
m_ripperThread->cancel();
m_ripperThread->wait();
Close();
}
}
MythConfirmationDialog *dialog =
ShowOkPopup(tr("Cancel ripping the CD?"), this, NULL, true);
if (dialog)
dialog->SetReturnEvent(this, "stop_ripping");
}
else
handled = false;
Expand All @@ -1420,6 +1478,20 @@ bool RipStatus::keyPressEvent(QKeyEvent *event)

void RipStatus::customEvent(QEvent *event)
{
if (event->type() == DialogCompletionEvent::kEventType)
{
DialogCompletionEvent *dce = static_cast<DialogCompletionEvent *>(event);

if (dce->GetId() == "stop_ripping")
{
m_ripperThread->cancel();
m_ripperThread->wait();
Close();
}

return;
}

RipStatusEvent *rse = dynamic_cast<RipStatusEvent *> (event);

if (!rse)
Expand Down
9 changes: 8 additions & 1 deletion mythplugins/mythmusic/mythmusic/cdrip.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,11 @@ typedef struct
Metadata *metadata;
bool active;
int length;
bool isNew;
} RipTrack;

Q_DECLARE_METATYPE(RipTrack *)

class RipStatus;

class CDRipperThread: public MThread
Expand Down Expand Up @@ -86,6 +89,7 @@ class Ripper : public MythScreenType

bool Create(void);
bool keyPressEvent(QKeyEvent *);
void customEvent(QEvent *);

bool somethingWasRipped();
void scanCD(void);
Expand Down Expand Up @@ -118,9 +122,12 @@ class Ripper : public MythScreenType
void ripFinished(void);

private:
void deleteTrack(QString& artist, QString& album, QString& title);
bool deleteExistingTrack(RipTrack *track);
void deleteAllExistingTracks(void);
void updateTrackList(void);
void updateTrackLengths(void);
void toggleTrackActive(RipTrack *);
void ShowConflictMenu(RipTrack *);

CdDecoder *m_decoder;

Expand Down