// delete a send later job // CSendLaterJob::~CSendLaterJob() { if (fSuccess || fFailed) { if ((sendLater->haveErrorPopups() && fFailed) || (sendLater->haveSuccessPopups() && fSuccess)) { bool fShowPopup = true; if (fFailed && bCode == JOB_REMOVABLE) // no popups for jobs removed on user's request fShowPopup = false; /* * show a popup notification, unless they are disabled */ if (PluginConfig.g_PopupAvail && fShowPopup) { TCHAR *tszName = pcli->pfnGetContactDisplayName(hContact, 0); POPUPDATAT ppd = {0}; ppd.lchContact = hContact; mir_sntprintf(ppd.lptzContactName, MAX_CONTACTNAME, _T("%s"), tszName ? tszName : TranslateT("'(Unknown Contact)'")); TCHAR *msgPreview = Utils::GetPreviewWithEllipsis(reinterpret_cast<TCHAR *>(&pBuf[lstrlenA((char *)pBuf) + 1]), 100); if (fSuccess) { mir_sntprintf(ppd.lptzText, MAX_SECONDLINE, TranslateT("A send later job completed successfully.\nThe original message: %s"), msgPreview); mir_free(msgPreview); } else if (fFailed) { mir_sntprintf(ppd.lptzText, MAX_SECONDLINE, TranslateT("A send later job failed to complete.\nThe original message: %s"), msgPreview); mir_free(msgPreview); } /* * use message settings (timeout/colors) for success popups */ ppd.colorText = fFailed ? RGB(255, 245, 225) : nen_options.colTextMsg; ppd.colorBack = fFailed ? RGB(191, 0, 0) : nen_options.colBackMsg; ppd.PluginWindowProc = reinterpret_cast<WNDPROC>(Utils::PopupDlgProcError); ppd.lchIcon = fFailed ? PluginConfig.g_iconErr : PluginConfig.g_IconMsgEvent; ppd.PluginData = (void*)hContact; ppd.iSeconds = fFailed ? -1 : nen_options.iDelayMsg; PUAddPopupT(&ppd); } } if (fFailed && (bCode == JOB_AGE || bCode == JOB_REMOVABLE) && szId[0] == 'S') cleanDB(); mir_free(sendBuffer); mir_free(pBuf); } }
/*! * \brief Scan a directory recursively for music and albumart. * Inserts, updates and removes any files any files found in the * database. * * \param directory Directory to scan * * \returns Nothing. */ void FileScanner::SearchDir(QString &directory) { m_startdir = directory; MusicLoadedMap music_files; MusicLoadedMap::Iterator iter; MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); QString message = QObject::tr("Searching for music files"); MythUIBusyDialog *busy = new MythUIBusyDialog(message, popupStack, "musicscanbusydialog"); if (busy->Create()) popupStack->AddScreen(busy, false); else busy = NULL; BuildFileList(m_startdir, music_files, 0); if (busy) busy->Close(); ScanMusic(music_files); ScanArtwork(music_files); message = QObject::tr("Updating music database"); MythUIProgressDialog *file_checking = new MythUIProgressDialog(message, popupStack, "scalingprogressdialog"); if (file_checking->Create()) { popupStack->AddScreen(file_checking, false); file_checking->SetTotal(music_files.size()); } else { delete file_checking; file_checking = NULL; } /* This can be optimised quite a bit by consolidating all commands via a lot of refactoring. 1) group all files of the same decoder type, and don't create/delete a Decoder pr. AddFileToDB. Or make Decoders be singletons, it should be a fairly simple change. 2) RemoveFileFromDB should group the remove into one big SQL. 3) UpdateFileInDB, same as 1. */ uint counter = 0; for (iter = music_files.begin(); iter != music_files.end(); iter++) { if (*iter == kFileSystem) AddFileToDB(iter.key()); else if (*iter == kDatabase) RemoveFileFromDB(iter.key ()); else if (*iter == kNeedUpdate) UpdateFileInDB(iter.key()); if (file_checking) { file_checking->SetProgress(++counter); qApp->processEvents(); } } if (file_checking) file_checking->Close(); // Cleanup orphaned entries from the database cleanDB(); }
/*! * \brief Scan a list of directories recursively for music and albumart. * Inserts, updates and removes any files any files found in the * database. * * \param dirList List of directories to scan * * \returns Nothing. */ void MusicFileScanner::SearchDirs(const QStringList &dirList) { QString host = gCoreContext->GetHostName(); if (IsRunning()) { // check how long the scanner has been running // if it's more than 60 minutes assume something went wrong QString lastRun = gCoreContext->GetSetting("MusicScannerLastRunStart", ""); if (!lastRun.isEmpty()) { QDateTime dtLastRun = QDateTime::fromString(lastRun, Qt::ISODate); if (dtLastRun.isValid()) { if (MythDate::current() > dtLastRun.addSecs(60*60)) { LOG(VB_GENERAL, LOG_INFO, "Music file scanner has been running for more than 60 minutes. Lets reset and try again"); gCoreContext->SendMessage(QString("MUSIC_SCANNER_ERROR %1 %2").arg(host).arg("Stalled")); // give the user time to read the notification before restarting the scan sleep(5); } else { LOG(VB_GENERAL, LOG_INFO, "Music file scanner is already running"); gCoreContext->SendMessage(QString("MUSIC_SCANNER_ERROR %1 %2").arg(host).arg("Already_Running")); return; } } } } //TODO: could sanity check the directory exists and is readable here? LOG(VB_GENERAL, LOG_INFO, "Music file scanner started"); gCoreContext->SendMessage(QString("MUSIC_SCANNER_STARTED %1").arg(host)); updateLastRunStart(); QString status = QString("running"); updateLastRunStatus(status); m_tracksTotal = m_tracksAdded = m_tracksUnchanged = m_tracksRemoved = m_tracksUpdated = 0; m_coverartTotal = m_coverartAdded = m_coverartUnchanged = m_coverartRemoved = m_coverartUpdated = 0; MusicLoadedMap music_files; MusicLoadedMap art_files; MusicLoadedMap::Iterator iter; for (int x = 0; x < dirList.count(); x++) { QString startDir = dirList[x]; m_startDirs.append(startDir + '/'); LOG(VB_GENERAL, LOG_INFO, QString("Searching '%1' for music files").arg(startDir)); BuildFileList(startDir, music_files, art_files, 0); } m_tracksTotal = music_files.count(); m_coverartTotal = art_files.count(); ScanMusic(music_files); ScanArtwork(art_files); LOG(VB_GENERAL, LOG_INFO, "Updating database"); /* This can be optimised quite a bit by consolidating all commands via a lot of refactoring. 1) group all files of the same decoder type, and don't create/delete a Decoder pr. AddFileToDB. Or make Decoders be singletons, it should be a fairly simple change. 2) RemoveFileFromDB should group the remove into one big SQL. 3) UpdateFileInDB, same as 1. */ for (iter = music_files.begin(); iter != music_files.end(); iter++) { if ((*iter).location == MusicFileScanner::kFileSystem) AddFileToDB(iter.key(), (*iter).startDir); else if ((*iter).location == MusicFileScanner::kDatabase) RemoveFileFromDB(iter.key(), (*iter).startDir); else if ((*iter).location == MusicFileScanner::kNeedUpdate) { UpdateFileInDB(iter.key(), (*iter).startDir); ++m_tracksUpdated; } } for (iter = art_files.begin(); iter != art_files.end(); iter++) { if ((*iter).location == MusicFileScanner::kFileSystem) AddFileToDB(iter.key(), (*iter).startDir); else if ((*iter).location == MusicFileScanner::kDatabase) RemoveFileFromDB(iter.key(), (*iter).startDir); else if ((*iter).location == MusicFileScanner::kNeedUpdate) { UpdateFileInDB(iter.key(), (*iter).startDir); ++m_coverartUpdated; } } // Cleanup orphaned entries from the database cleanDB(); QString trackStatus = QString("total tracks found: %1 (unchanged: %2, added: %3, removed: %4, updated %5)") .arg(m_tracksTotal).arg(m_tracksUnchanged).arg(m_tracksAdded) .arg(m_tracksRemoved).arg(m_tracksUpdated); QString coverartStatus = QString("total coverart found: %1 (unchanged: %2, added: %3, removed: %4, updated %5)") .arg(m_coverartTotal).arg(m_coverartUnchanged).arg(m_coverartAdded) .arg(m_coverartRemoved).arg(m_coverartUpdated); LOG(VB_GENERAL, LOG_INFO, "Music file scanner finished "); LOG(VB_GENERAL, LOG_INFO, trackStatus); LOG(VB_GENERAL, LOG_INFO, coverartStatus); gCoreContext->SendMessage(QString("MUSIC_SCANNER_FINISHED %1 %2 %3 %4 %5") .arg(host).arg(m_tracksTotal).arg(m_tracksAdded) .arg(m_coverartTotal).arg(m_coverartAdded)); updateLastRunEnd(); status = QString("success - %1 - %2").arg(trackStatus).arg(coverartStatus); updateLastRunStatus(status); }