diff options
author | DaveTBlake <oak99sky@yahoo.co.uk> | 2019-03-30 19:01:03 +0000 |
---|---|---|
committer | DaveTBlake <oak99sky@yahoo.co.uk> | 2019-04-06 13:07:55 +0100 |
commit | f7caf87377eead02e259e55ef78655b86b744817 (patch) | |
tree | 873f5ab118abd71a937039401ecdd737f7895506 | |
parent | d135aaad5ff22370e1dc5bfe4c403a330fb4d92f (diff) |
Import music library data on a separate thread from GUI. This allows cancel button on progress dialog to be clicked.
Import song playback history data (play count, lastplayed and ratings) from xml.
-rw-r--r-- | addons/resource.language.en_gb/resources/strings.po | 39 | ||||
-rw-r--r-- | xbmc/music/MusicDatabase.cpp | 348 | ||||
-rw-r--r-- | xbmc/music/MusicDatabase.h | 3 | ||||
-rw-r--r-- | xbmc/music/MusicLibraryQueue.cpp | 40 | ||||
-rw-r--r-- | xbmc/music/MusicLibraryQueue.h | 7 | ||||
-rw-r--r-- | xbmc/music/jobs/CMakeLists.txt | 2 | ||||
-rw-r--r-- | xbmc/music/jobs/MusicLibraryImportJob.cpp | 41 | ||||
-rw-r--r-- | xbmc/music/jobs/MusicLibraryImportJob.h | 42 | ||||
-rw-r--r-- | xbmc/settings/MediaSettings.cpp | 7 |
9 files changed, 496 insertions, 33 deletions
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po index 713cf7bd51..4e239efb2e 100644 --- a/addons/resource.language.en_gb/resources/strings.po +++ b/addons/resource.language.en_gb/resources/strings.po @@ -2987,12 +2987,12 @@ msgctxt "#648" msgid "Import video library" msgstr "" -#: xbmc/music/MusicDatabase.cpp +#. unused? msgctxt "#649" msgid "Importing" msgstr "" -#: xbmc/music/MusicDatabase.cpp +#. unused? msgctxt "#650" msgid "Exporting" msgstr "" @@ -12394,6 +12394,7 @@ msgctxt "#20196" msgid "Export music library" msgstr "" +#: xbmc/music/MusicDatabase.cpp #: system/settings/settings.xml msgctxt "#20197" msgid "Import music library" @@ -21393,7 +21394,39 @@ msgctxt "#38339" msgid "How to apply information provider settings" msgstr "" -#empty strings from id 38340 to 38999 +#empty strings from id 38340 to 38349 + +#. Progress statement when importing music library is processing song playback history data +#: xbmc/music/MusicDatabase.cpp +msgctxt "#38350" +msgid "Importing song playback history" +msgstr "" + +#. Progress statement when importing music library - data matching phase +#: xbmc/music/MusicDatabase.cpp +msgctxt "#38351" +msgid "Matching data" +msgstr "" + +#. Progress statement when importing music library - song history being updated +#: xbmc/music/MusicDatabase.cpp +msgctxt "#38352" +msgid "Updating songs" +msgstr "" + +#. Notification of import success "Importing song history - <number of songs matched> updated out of <total songs in xml> imported songs" +#: xbmc/music/MusicDatabase.cpp +msgctxt "#38353" +msgid "Importing song history - {0:d} updated out of {0:d} imported songs" +msgstr "" + +#. Message when reading the user specified XML for import to library fails +#: xbmc/music/MusicDatabase.cpp +msgctxt "#38354" +msgid "Unable to read xml file" +msgstr "" + +#empty strings from id 38355 to 38999 #: system/settings/settings.xml msgctxt "#39000" diff --git a/xbmc/music/MusicDatabase.cpp b/xbmc/music/MusicDatabase.cpp index 2316551599..1d72b8dd2e 100644 --- a/xbmc/music/MusicDatabase.cpp +++ b/xbmc/music/MusicDatabase.cpp @@ -20,6 +20,8 @@ #include "dialogs/GUIDialogKaiToast.h" #include "dialogs/GUIDialogProgress.h" #include "dialogs/GUIDialogSelect.h" +#include "events/EventLog.h" +#include "events/NotificationEvent.h" #include "FileItem.h" #include "filesystem/Directory.h" #include "filesystem/DirectoryCache.h" @@ -52,6 +54,7 @@ #include "utils/FileUtils.h" #include "utils/LegacyPathTranslation.h" #include "utils/log.h" +#include "utils/MathUtils.h" #include "utils/Random.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" @@ -9906,41 +9909,36 @@ bool CMusicDatabase::ExportSongHistory(TiXmlNode* pNode, CGUIDialogProgress* pro return false; } -void CMusicDatabase::ImportFromXML(const std::string &xmlFile) -{ - CGUIDialogProgress *progress = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogProgress>(WINDOW_DIALOG_PROGRESS); +void CMusicDatabase::ImportFromXML(const std::string& xmlFile, CGUIDialogProgress* progressDialog) +{ try { if (NULL == m_pDB.get()) return; if (NULL == m_pDS.get()) return; CXBMCTinyXML xmlDoc; - if (!xmlDoc.LoadFile(xmlFile)) + if (!xmlDoc.LoadFile(xmlFile) && progressDialog) + { + HELPERS::ShowOKDialogLines(CVariant{ 20197 }, CVariant{ 38354 }); //"Unable to read xml file" return; + } TiXmlElement *root = xmlDoc.RootElement(); if (!root) return; - if (progress) - { - progress->SetHeading(CVariant{20197}); - progress->SetLine(0, CVariant{649}); - progress->SetLine(1, CVariant{330}); - progress->SetLine(2, CVariant{""}); - progress->SetPercentage(0); - progress->Open(); - progress->ShowProgressBar(true); - } - TiXmlElement *entry = root->FirstChildElement(); int current = 0; int total = 0; - // first count the number of items... + int songtotal = 0; + // Count the number of artists, albums and songs while (entry) { if (strnicmp(entry->Value(), "artist", 6)==0 || strnicmp(entry->Value(), "album", 5)==0) total++; + else if (strnicmp(entry->Value(), "song", 4) == 0) + songtotal++; + entry = entry->NextSiblingElement(); } @@ -9988,14 +9986,13 @@ void CMusicDatabase::ImportFromXML(const std::string &xmlFile) current++; } entry = entry ->NextSiblingElement(); - if (progress && total) + if (progressDialog && total) { - progress->SetPercentage(current * 100 / total); - progress->SetLine(2, CVariant{std::move(strTitle)}); - progress->Progress(); - if (progress->IsCanceled()) + progressDialog->SetPercentage(current * 100 / total); + progressDialog->SetLine(2, CVariant{std::move(strTitle)}); + progressDialog->Progress(); + if (progressDialog->IsCanceled()) { - progress->Close(); RollbackTransaction(); return; } @@ -10003,6 +10000,11 @@ void CMusicDatabase::ImportFromXML(const std::string &xmlFile) } CommitTransaction(); + // Import song playback history <song> entries found + if (songtotal > 0) + if (!ImportSongHistory(xmlFile, songtotal, progressDialog)) + return; + CGUIComponent* gui = CServiceBroker::GetGUI(); if (gui) gui->GetInfoManager().GetInfoProviders().GetLibraryInfoProvider().ResetLibraryBools(); @@ -10012,8 +10014,306 @@ void CMusicDatabase::ImportFromXML(const std::string &xmlFile) CLog::Log(LOGERROR, "%s failed", __FUNCTION__); RollbackTransaction(); } - if (progress) - progress->Close(); + if (progressDialog) + progressDialog->Close(); +} + +bool CMusicDatabase::ImportSongHistory(const std::string& xmlFile, const int total, CGUIDialogProgress* progressDialog) +{ + bool bHistSongExists = false; + try + { + CXBMCTinyXML xmlDoc; + if (!xmlDoc.LoadFile(xmlFile)) + return false; + + TiXmlElement* root = xmlDoc.RootElement(); + if (!root) + return false; + + TiXmlElement* entry = root->FirstChildElement(); + int current = 0; + + if (progressDialog) + { + progressDialog->SetLine(1, CVariant{38350}); //"Importing song playback history" + progressDialog->SetLine(2, CVariant{ "" }); + } + + // As can be many songs do in db, not song at a time which would be slow + // Convert xml entries into a SQL bulk insert statement + std::string strSQL; + entry = root->FirstChildElement(); + while (entry) + { + std::string strArtistDisp; + std::string strTitle; + int iTrack; + std::string strFilename; + std::string strMusicBrainzTrackID; + std::string strAlbum; + std::string strMusicBrainzAlbumID; + std::string strAlbumArtistDisp; + int iTimesplayed; + std::string lastplayed; + int iUserrating = 0; + float fRating = 0.0; + int iVotes; + std::string strSQLSong; + if (strnicmp(entry->Value(), "song", 4) == 0) + { + XMLUtils::GetString(entry, "artistdesc", strArtistDisp); + XMLUtils::GetString(entry, "title", strTitle); + XMLUtils::GetInt(entry, "track", iTrack); + XMLUtils::GetString(entry, "filename", strFilename); + XMLUtils::GetString(entry, "musicbrainztrackid", strMusicBrainzTrackID); + XMLUtils::GetString(entry, "albumtitle", strAlbum); + XMLUtils::GetString(entry, "musicbrainzalbumid", strMusicBrainzAlbumID); + XMLUtils::GetString(entry, "albumartistdesc", strAlbumArtistDisp); + XMLUtils::GetInt(entry, "timesplayed", iTimesplayed); + XMLUtils::GetString(entry, "lastplayed", lastplayed); + const TiXmlElement* rElement = entry->FirstChildElement("rating"); + if (rElement) + { + float rating = 0; + float max_rating = 10; + XMLUtils::GetFloat(entry, "rating", rating); + if (rElement->QueryFloatAttribute("max", &max_rating) == TIXML_SUCCESS && max_rating >= 1) + rating *= (10.f / max_rating); // Normalise the value to between 0 and 10 + if (rating > 10.f) + rating = 10.f; + fRating = rating; + } + XMLUtils::GetInt(entry, "votes", iVotes); + const TiXmlElement* userrating = entry->FirstChildElement("userrating"); + if (userrating) + { + float rating = 0; + float max_rating = 10; + XMLUtils::GetFloat(entry, "userrating", rating); + if (userrating->QueryFloatAttribute("max", &max_rating) == TIXML_SUCCESS && max_rating >= 1) + rating *= (10.f / max_rating); // Normalise the value to between 0 and 10 + if (rating > 10.f) + rating = 10.f; + iUserrating = MathUtils::round_int(rating); + } + + strSQLSong = PrepareSQL("(%d, %d, ", current + 1, iTrack); + strSQLSong += PrepareSQL("'%s', '%s', '%s', ", strArtistDisp.c_str(), strTitle.c_str(), strFilename.c_str()); + if (strMusicBrainzTrackID.empty()) + strSQLSong += PrepareSQL("NULL, "); + else + strSQLSong += PrepareSQL("'%s', ", strMusicBrainzTrackID.c_str()); + strSQLSong += PrepareSQL("'%s', '%s', ", strAlbum.c_str(), strAlbumArtistDisp.c_str()); + if (strMusicBrainzAlbumID.empty()) + strSQLSong += PrepareSQL("NULL, "); + else + strSQLSong += PrepareSQL("'%s', ", strMusicBrainzAlbumID.c_str()); + strSQLSong += PrepareSQL("%d, ", iTimesplayed); + if (lastplayed.empty()) + strSQLSong += PrepareSQL("NULL, "); + else + strSQLSong += PrepareSQL("'%s', ", lastplayed.c_str()); + strSQLSong += PrepareSQL("%.1f, %d, %d, -1, -1)", fRating, iVotes, iUserrating); + + if (current > 0) + strSQLSong = ", " + strSQLSong; + strSQL += strSQLSong; + current++; + } + + entry = entry->NextSiblingElement(); + + if ((current % 100) == 0 && progressDialog) + { + progressDialog->SetPercentage(current * 100 / total); + progressDialog->SetLine(3, CVariant{ std::move(strTitle) }); + progressDialog->Progress(); + if (progressDialog->IsCanceled()) + return false; + } + } + + CLog::Log(LOGINFO, "{0}: Create temporary HistSong table and insert {1} records", __FUNCTION__, total); + /* Can not use CREATE TEMPORARY TABLE as MySQL does not support updates of + song table using correlated subqueries to a temp table. An updatable join + to temp table would work in MySQL but SQLite not support updatable joins. + */ + m_pDS->exec("CREATE TABLE HistSong (" + "idSongSrc INTEGER primary key, " + "strAlbum varchar(256), " + "strMusicBrainzAlbumID text, " + "strAlbumArtistDisp text, " + "strArtistDisp text, strTitle varchar(512), " + "iTrack INTEGER, strFileName text, strMusicBrainzTrackID text, " + "iTimesPlayed INTEGER, lastplayed varchar(20) default NULL, " + "rating FLOAT NOT NULL DEFAULT 0, votes INTEGER NOT NULL DEFAULT 0, " + "userrating INTEGER NOT NULL DEFAULT 0, " + "idAlbum INTEGER, idSong INTEGER)"); + bHistSongExists = true; + + strSQL = "INSERT INTO HistSong (idSongSrc, iTrack, strArtistDisp, strTitle, " + "strFileName, strMusicBrainzTrackID, " + "strAlbum, strAlbumArtistDisp, strMusicBrainzAlbumID, " + " iTimesPlayed, lastplayed, rating, votes, userrating, idAlbum, idSong) VALUES " + strSQL; + m_pDS->exec(strSQL); + + if (progressDialog) + { + progressDialog->SetLine(2, CVariant{38351}); //"Matching data" + progressDialog->SetLine(3, CVariant{ "" }); + progressDialog->Progress(); + if (progressDialog->IsCanceled()) + { + m_pDS->exec("DROP TABLE HistSong"); + return false; + } + } + + BeginTransaction(); + // Match albums first on mbid then artist string and album title, setting idAlbum + strSQL = "UPDATE HistSong " + "SET idAlbum = (SELECT album.idAlbum FROM album " + "WHERE album.strMusicBrainzAlbumID = HistSong.strMusicBrainzAlbumID) " + "WHERE EXISTS(SELECT 1 FROM album " + "WHERE album.strMusicBrainzAlbumID = HistSong.strMusicBrainzAlbumID) AND idAlbum < 0"; + m_pDS->exec(strSQL); + + strSQL = "UPDATE HistSong " + "SET idAlbum = (SELECT album.idAlbum FROM album " + "WHERE HistSong.strAlbumArtistDisp = album.strArtistDisp AND HistSong.strAlbum = album.strAlbum) " + "WHERE EXISTS(SELECT 1 FROM album " + "WHERE HistSong.strAlbumArtistDisp = album.strArtistDisp AND HistSong.strAlbum = album.strAlbum)" + "AND idAlbum < 0"; + m_pDS->exec(strSQL); + if (progressDialog) + { + progressDialog->Progress(); + if (progressDialog->IsCanceled()) + { + RollbackTransaction(); + m_pDS->exec("DROP TABLE HistSong"); + return false; + } + } + + // Match songs on first on idAlbum, track and mbid, then idAlbum, track and title, setting idSong + strSQL = "UPDATE HistSong " + "SET idSong = (SELECT idsong FROM song " + "WHERE HistSong.idAlbum = song.idAlbum AND " + "HistSong.iTrack = song.iTrack AND " + "HistSong.strMusicBrainzTrackID = song.strMusicBrainzTrackID) " + "WHERE EXISTS(SELECT 1 FROM song " + "WHERE HistSong.idAlbum = song.idAlbum AND " + "HistSong.iTrack = song.iTrack AND " + "HistSong.strMusicBrainzTrackID = song.strMusicBrainzTrackID) AND idSong < 0"; + m_pDS->exec(strSQL); + + strSQL = "UPDATE HistSong " + "SET idSong = (SELECT idsong FROM song " + "WHERE HistSong.idAlbum = song.idAlbum AND " + "HistSong.iTrack = song.iTrack AND HistSong.strTitle = song.strTitle) " + "WHERE EXISTS(SELECT 1 FROM song " + "WHERE HistSong.idAlbum = song.idAlbum AND " + "HistSong.iTrack = song.iTrack AND HistSong.strTitle = song.strTitle) AND idSong < 0"; + m_pDS->exec(strSQL); + CommitTransaction(); + if (progressDialog) + { + progressDialog->Progress(); + if (progressDialog->IsCanceled()) + { + m_pDS->exec("DROP TABLE HistSong"); + return false; + } + } + + // Create an index to speed up the updates + m_pDS->exec("CREATE INDEX idxHistSong ON HistSong(idSong)"); + + // Log how many songs matched + int unmatched = static_cast<int>(strtol(GetSingleValue("SELECT COUNT(1) FROM HistSong WHERE idSong < 0", m_pDS).c_str(), nullptr, 10)); + CLog::Log(LOGINFO, "{0}: Importing song history {1} of {2} songs matched", __FUNCTION__, total - unmatched, total); + + if (progressDialog) + { + progressDialog->SetLine(2, CVariant{38352}); //"Updating song playback history" + progressDialog->Progress(); + if (progressDialog->IsCanceled()) + { + m_pDS->exec("DROP TABLE HistSong"); // Drops index too + return false; + } + } + + /* Update song table using the song ids we have matched. + Use correlated subqueries as SQLite does not support updatable joins. + MySQL requires HistSong table not to be defined temporary for this. + */ + BeginTransaction(); + // Times played and last played date(when count is greater) + strSQL = "UPDATE song SET iTimesPlayed = " + "(SELECT iTimesPlayed FROM HistSong WHERE HistSong.idSong = song.idSong), " + "lastplayed = " + "(SELECT lastplayed FROM HistSong WHERE HistSong.idSong = song.idSong) " + "WHERE EXISTS(SELECT 1 FROM HistSong WHERE " + "HistSong.idSong = song.idSong AND HistSong.iTimesPlayed > song.iTimesPlayed)"; + m_pDS->exec(strSQL); + + // User rating + strSQL = "UPDATE song SET userrating = " + "(SELECT userrating FROM HistSong WHERE HistSong.idSong = song.idSong) " + "WHERE EXISTS(SELECT 1 FROM HistSong WHERE " + "HistSong.idSong = song.idSong AND HistSong.userrating > 0)"; + m_pDS->exec(strSQL); + + // Rating and votes + strSQL = "UPDATE song SET rating = " + "(SELECT rating FROM HistSong WHERE HistSong.idSong = song.idSong), " + "votes = " + "(SELECT votes FROM HistSong WHERE HistSong.idSong = song.idSong) " + "WHERE EXISTS(SELECT 1 FROM HistSong WHERE " + "HistSong.idSong = song.idSong AND HistSong.rating > 0)"; + m_pDS->exec(strSQL); + + if (progressDialog) + { + progressDialog->Progress(); + if (progressDialog->IsCanceled()) + { + RollbackTransaction(); + m_pDS->exec("DROP TABLE HistSong"); + return false; + } + } + CommitTransaction(); + + // Tidy up temp table (index also removed) + m_pDS->exec("DROP TABLE HistSong"); + // Compact db to recover space as had to add/drop actual table + if (progressDialog) + { + progressDialog->SetLine(2, CVariant{ 331 }); + progressDialog->Progress(); + } + Compress(false); + + // Write event log entry + // "Importing song history {1} of {2} songs matched", total - unmatched, total) + std::string strLine = StringUtils::Format(g_localizeStrings.Get(38353).c_str(), total - unmatched, total); + CServiceBroker::GetEventLog().Add( + EventPtr(new CNotificationEvent(20197, strLine, EventLevel::Information))); + + return true; + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed", __FUNCTION__); + RollbackTransaction(); + if (bHistSongExists) + m_pDS->exec("DROP TABLE HistSong"); + } + return false; } void CMusicDatabase::SetPropertiesFromArtist(CFileItem& item, const CArtist& artist) diff --git a/xbmc/music/MusicDatabase.h b/xbmc/music/MusicDatabase.h index eae395735d..ed65526a94 100644 --- a/xbmc/music/MusicDatabase.h +++ b/xbmc/music/MusicDatabase.h @@ -499,7 +499,8 @@ public: ///////////////////////////////////////////////// void ExportToXML(const CLibExportSettings& settings, CGUIDialogProgress* progressDialog = nullptr); bool ExportSongHistory(TiXmlNode* pNode, CGUIDialogProgress* progressDialog = nullptr); - void ImportFromXML(const std::string &xmlFile); + void ImportFromXML(const std::string& xmlFile, CGUIDialogProgress* progressDialog = nullptr); + bool ImportSongHistory(const std::string& xmlFile, const int total, CGUIDialogProgress* progressDialog = nullptr); ///////////////////////////////////////////////// // Properties diff --git a/xbmc/music/MusicLibraryQueue.cpp b/xbmc/music/MusicLibraryQueue.cpp index 740fa3095b..acfaffb114 100644 --- a/xbmc/music/MusicLibraryQueue.cpp +++ b/xbmc/music/MusicLibraryQueue.cpp @@ -17,6 +17,7 @@ #include "GUIUserMessages.h" #include "music/jobs/MusicLibraryCleaningJob.h" #include "music/jobs/MusicLibraryExportJob.h" +#include "music/jobs/MusicLibraryImportJob.h" #include "music/jobs/MusicLibraryScanningJob.h" #include "music/jobs/MusicLibraryJob.h" #include "threads/SingleLock.h" @@ -77,6 +78,45 @@ void CMusicLibraryQueue::ExportLibrary(const CLibExportSettings& settings, bool } } +void CMusicLibraryQueue::ImportLibrary(const std::string& xmlFile, bool showDialog /* = false */) +{ + CGUIDialogProgress* progress = nullptr; + if (showDialog) + { + progress = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogProgress>(WINDOW_DIALOG_PROGRESS); + if (progress) + { + progress->SetHeading(CVariant{ 20197 }); //"Import music library" + progress->SetText(CVariant{ 649 }); //"Importing" + progress->SetLine(1, CVariant{ 330 }); //"This could take some time" + progress->SetLine(2, CVariant{ "" }); + progress->SetPercentage(0); + progress->Open(); + progress->ShowProgressBar(true); + } + } + + CMusicLibraryImportJob* importJob = new CMusicLibraryImportJob(xmlFile, progress); + if (showDialog) + { + AddJob(importJob); + + // Wait for import to complete or be canceled, but render every 10ms so that the + // pointer movements work on dialog even when import is reporting progress infrequently + if (progress) + progress->Wait(); + } + else + { + m_modal = true; + importJob->DoWork(); + + delete importJob; + m_modal = false; + Refresh(); + } +} + void CMusicLibraryQueue::ScanLibrary(const std::string& strDirectory, int flags /* = 0 */, bool showProgress /* = true */) { AddJob(new CMusicLibraryScanningJob(strDirectory, flags, showProgress)); diff --git a/xbmc/music/MusicLibraryQueue.h b/xbmc/music/MusicLibraryQueue.h index 2ba993e13a..4ccf215524 100644 --- a/xbmc/music/MusicLibraryQueue.h +++ b/xbmc/music/MusicLibraryQueue.h @@ -44,6 +44,13 @@ public: void ExportLibrary(const CLibExportSettings& settings, bool showDialog = false); /*! + \brief Enqueue a music library import job. + \param[in] xmlFile xml file to import + \param[in] showDialog Show a progress dialog while (asynchronously) exporting, otherwise export in synchronous + */ + void ImportLibrary(const std::string& xmlFile, bool showDialog = false); + + /*! \brief Enqueue a music library update job, scanning tags embedded in music files and optionally scraping additional data. \param[in] strDirectory Directory to scan or "" (empty string) for a global scan. \param[in] flags Flags for controlling the scanning process. See xbmc/music/infoscanner/MusicInfoScanner.h for possible values. diff --git a/xbmc/music/jobs/CMakeLists.txt b/xbmc/music/jobs/CMakeLists.txt index 0392781fee..8ee0f5dda6 100644 --- a/xbmc/music/jobs/CMakeLists.txt +++ b/xbmc/music/jobs/CMakeLists.txt @@ -2,12 +2,14 @@ set(SOURCES MusicLibraryJob.cpp MusicLibraryProgressJob.cpp MusicLibraryCleaningJob.cpp MusicLibraryExportJob.cpp + MusicLibraryImportJob.cpp MusicLibraryScanningJob.cpp) set(HEADERS MusicLibraryJob.h MusicLibraryProgressJob.h MusicLibraryCleaningJob.h MusicLibraryExportJob.h + MusicLibraryImportJob.h MusicLibraryScanningJob.h) core_add_library(music_jobs) diff --git a/xbmc/music/jobs/MusicLibraryImportJob.cpp b/xbmc/music/jobs/MusicLibraryImportJob.cpp new file mode 100644 index 0000000000..714e535b6e --- /dev/null +++ b/xbmc/music/jobs/MusicLibraryImportJob.cpp @@ -0,0 +1,41 @@ +/* +* Copyright (C) 2017-2018 Team Kodi +* This file is part of Kodi - https://kodi.tv +* +* SPDX-License-Identifier: GPL-2.0-or-later +* See LICENSES/README.md for more information. +*/ + +#include "MusicLibraryImportJob.h" +#include "dialogs/GUIDialogProgress.h" +#include "music/MusicDatabase.h" + +CMusicLibraryImportJob::CMusicLibraryImportJob(const std::string& xmlFile, CGUIDialogProgress* progressDialog) + : CMusicLibraryProgressJob(nullptr) + , m_xmlFile(xmlFile) +{ + if (progressDialog) + SetProgressIndicators(nullptr, progressDialog); + SetAutoClose(true); +} + +CMusicLibraryImportJob::~CMusicLibraryImportJob() = default; + +bool CMusicLibraryImportJob::operator==(const CJob* job) const +{ + if (strcmp(job->GetType(), GetType()) != 0) + return false; + + const CMusicLibraryImportJob* importJob = dynamic_cast<const CMusicLibraryImportJob*>(job); + if (importJob == nullptr) + return false; + + return !(m_xmlFile != importJob->m_xmlFile); +} + +bool CMusicLibraryImportJob::Work(CMusicDatabase &db) +{ + db.ImportFromXML(m_xmlFile, GetProgressDialog()); + + return true; +} diff --git a/xbmc/music/jobs/MusicLibraryImportJob.h b/xbmc/music/jobs/MusicLibraryImportJob.h new file mode 100644 index 0000000000..bcca44f245 --- /dev/null +++ b/xbmc/music/jobs/MusicLibraryImportJob.h @@ -0,0 +1,42 @@ +/* +* Copyright (C) 2017-2018 Team Kodi +* This file is part of Kodi - https://kodi.tv +* +* SPDX-License-Identifier: GPL-2.0-or-later +* See LICENSES/README.md for more information. +*/ + +#pragma once + +#include "MusicLibraryProgressJob.h" + +class CGUIDialogProgress; + +/*! +\brief Music library job implementation for importing data to the music library. +*/ +class CMusicLibraryImportJob : public CMusicLibraryProgressJob +{ +public: + /*! + \brief Creates a new music library import job for the given xml file. + + \param[in] xmlFile xml file to import + \param[in] progressDialog Progress dialog to be used to display the import progress + */ + CMusicLibraryImportJob(const std::string &xmlFile, CGUIDialogProgress* progressDialog); + + ~CMusicLibraryImportJob() override; + + // specialization of CJob + const char *GetType() const override { return "MusicLibraryImportJob"; } + bool operator==(const CJob* job) const override; + +protected: + // implementation of CMusicLibraryJob + bool Work(CMusicDatabase &db) override; + +private: + std::string m_xmlFile; +}; + diff --git a/xbmc/settings/MediaSettings.cpp b/xbmc/settings/MediaSettings.cpp index 8cccd71c4d..d88829787c 100644 --- a/xbmc/settings/MediaSettings.cpp +++ b/xbmc/settings/MediaSettings.cpp @@ -19,7 +19,6 @@ #include "guilib/LocalizeStrings.h" #include "interfaces/AnnouncementManager.h" #include "interfaces/builtins/Builtins.h" -#include "music/MusicDatabase.h" #include "music/MusicLibraryQueue.h" #include "messaging/helpers/DialogHelper.h" #include "ServiceBroker.h" @@ -315,10 +314,8 @@ void CMediaSettings::OnSettingAction(std::shared_ptr<const CSetting> setting) if (CGUIDialogFileBrowser::ShowAndGetFile(shares, "musicdb.xml", g_localizeStrings.Get(651) , path)) { - CMusicDatabase musicdatabase; - musicdatabase.Open(); - musicdatabase.ImportFromXML(path); - musicdatabase.Close(); + // Import data to music library showing progress dialog + CMusicLibraryQueue::GetInstance().ImportLibrary(path, true); } } else if (settingId == CSettings::SETTING_VIDEOLIBRARY_CLEANUP) |