diff options
author | Sascha Montellese <sascha.montellese@gmail.com> | 2015-04-01 18:43:41 +0200 |
---|---|---|
committer | Sascha Montellese <sascha.montellese@gmail.com> | 2015-04-01 18:43:41 +0200 |
commit | 9d9c66022eb1358c13c592180943a9f85fba5171 (patch) | |
tree | a3fd576284647a1df41b8e896907aa1ebf17946b | |
parent | f4ad529a6a7b59eff19ca1932d283a79ac4868ff (diff) | |
parent | d928d1969c828c24131e070336fa5f22c95b0d9c (diff) |
Merge pull request #6810 from Montellese/musicdb_singles
musicdb: cleanup detection of Singles
-rw-r--r-- | Kodi.xcodeproj/project.pbxproj | 2 | ||||
-rw-r--r-- | project/VS2010Express/XBMC.vcxproj | 3 | ||||
-rw-r--r-- | project/VS2010Express/XBMC.vcxproj.filters | 8 | ||||
-rw-r--r-- | xbmc/Application.cpp | 1 | ||||
-rw-r--r-- | xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeOverview.cpp | 3 | ||||
-rw-r--r-- | xbmc/interfaces/json-rpc/AudioLibrary.cpp | 8 | ||||
-rw-r--r-- | xbmc/interfaces/json-rpc/schema/methods.json | 6 | ||||
-rw-r--r-- | xbmc/interfaces/json-rpc/schema/types.json | 24 | ||||
-rw-r--r-- | xbmc/interfaces/json-rpc/schema/version.txt | 2 | ||||
-rw-r--r-- | xbmc/music/Album.cpp | 56 | ||||
-rw-r--r-- | xbmc/music/Album.h | 15 | ||||
-rw-r--r-- | xbmc/music/CueInfoLoader.cpp | 1 | ||||
-rw-r--r-- | xbmc/music/EmbeddedArt.h | 60 | ||||
-rw-r--r-- | xbmc/music/MusicDatabase.cpp | 65 | ||||
-rw-r--r-- | xbmc/music/MusicDatabase.h | 9 | ||||
-rw-r--r-- | xbmc/music/Song.h | 3 | ||||
-rw-r--r-- | xbmc/music/infoscanner/MusicInfoScanner.cpp | 4 | ||||
-rw-r--r-- | xbmc/music/tags/MusicInfoTag.cpp | 24 | ||||
-rw-r--r-- | xbmc/music/tags/MusicInfoTag.h | 37 |
19 files changed, 268 insertions, 63 deletions
diff --git a/Kodi.xcodeproj/project.pbxproj b/Kodi.xcodeproj/project.pbxproj index 5b3c9cd1eb..f27030af4f 100644 --- a/Kodi.xcodeproj/project.pbxproj +++ b/Kodi.xcodeproj/project.pbxproj @@ -3545,6 +3545,7 @@ 38F4E56E13CCCB3B00664821 /* ThreadLocal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadLocal.h; sourceTree = "<group>"; }; 395897131AAD94F00033D27C /* KeyboardLayoutManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KeyboardLayoutManager.cpp; sourceTree = "<group>"; }; 395897141AAD94F00033D27C /* KeyboardLayoutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyboardLayoutManager.h; sourceTree = "<group>"; }; + 395938731AC28F5A0053A590 /* EmbeddedArt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EmbeddedArt.h; sourceTree = "<group>"; }; 395C29BA1A94733100EBC7AD /* Key.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Key.cpp; sourceTree = "<group>"; }; 395C29BB1A94733100EBC7AD /* Key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Key.h; sourceTree = "<group>"; }; 395C29BF1A98A0A000EBC7AD /* Webinterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Webinterface.cpp; sourceTree = "<group>"; }; @@ -6166,6 +6167,7 @@ 880DBE4A0DC223FF00E26B71 /* Artist.h */, 5EB3113A1A978B9B00551907 /* CueInfoLoader.cpp */, 5EB3113B1A978B9B00551907 /* CueInfoLoader.h */, + 395938731AC28F5A0053A590 /* EmbeddedArt.h */, E38E17FB0D25F9FA00618676 /* GUIViewStateMusic.cpp */, E38E17FC0D25F9FA00618676 /* GUIViewStateMusic.h */, E38E1D8F0D25F9FD00618676 /* MusicDatabase.cpp */, diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj index 14f1b9dd8e..bfd7809b6f 100644 --- a/project/VS2010Express/XBMC.vcxproj +++ b/project/VS2010Express/XBMC.vcxproj @@ -955,6 +955,7 @@ <ClInclude Include="..\..\xbmc\interfaces\python\pythreadstate.h" /> <ClInclude Include="..\..\xbmc\media\MediaType.h" /> <ClInclude Include="..\..\xbmc\music\CueInfoLoader.h" /> + <ClInclude Include="..\..\xbmc\music\EmbeddedArt.h" /> <ClInclude Include="..\..\xbmc\music\karaoke\karaokevideobackground.h" /> <ClInclude Include="..\..\xbmc\music\tags\ReplayGain.h" /> <ClInclude Include="..\..\xbmc\network\httprequesthandler\HTTPFileHandler.h" /> @@ -2539,4 +2540,4 @@ </VisualStudio> </ProjectExtensions> <Import Project="$(SolutionDir)\$(ProjectFileName).targets.user" Condition="Exists('$(SolutionDir)\$(ProjectFileName).targets.user')" /> -</Project> +</Project>
\ No newline at end of file diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters index 7c7e944dd3..ffe40c72b4 100644 --- a/project/VS2010Express/XBMC.vcxproj.filters +++ b/project/VS2010Express/XBMC.vcxproj.filters @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <Filter Include="win32"> @@ -3086,6 +3086,7 @@ <ClCompile Include="..\..\xbmc\music\CueInfoLoader.cpp"> <Filter>music</Filter> </ClCompile> + <ClCompile Include="..\..\xbmc\filesystem\NFSDirectory.cpp" /> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\xbmc\win32\pch.h"> @@ -5970,6 +5971,9 @@ <ClInclude Include="..\..\xbmc\input\KeyboardLayoutManager.h"> <Filter>input</Filter> </ClInclude> + <ClInclude Include="..\..\xbmc\music\EmbeddedArt.h"> + <Filter>music</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ResourceCompile Include="..\..\xbmc\win32\XBMC_PC.rc"> @@ -6015,4 +6019,4 @@ <Filter>interfaces\swig</Filter> </CustomBuild> </ItemGroup> -</Project> +</Project>
\ No newline at end of file diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index 3490f4ec61..f2b47ddc72 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -187,6 +187,7 @@ #include "utils/XMLUtils.h" #include "addons/AddonInstaller.h" #include "addons/AddonManager.h" +#include "music/tags/MusicInfoTag.h" #include "music/tags/MusicInfoTagLoaderFactory.h" #include "CompileInfo.h" diff --git a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeOverview.cpp b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeOverview.cpp index 020513506e..2b4cd9a0df 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeOverview.cpp +++ b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeOverview.cpp @@ -74,8 +74,7 @@ bool CDirectoryNodeOverview::GetContent(CFileItemList& items) const bool showSingles = false; if (musicDatabase.Open()) { - CDatabase::Filter filter("songview.idAlbum IN (SELECT idAlbum FROM album WHERE strAlbum = '')"); - if (musicDatabase.GetSongsCount(filter) > 0) + if (musicDatabase.GetSinglesCount() > 0) showSingles = true; } diff --git a/xbmc/interfaces/json-rpc/AudioLibrary.cpp b/xbmc/interfaces/json-rpc/AudioLibrary.cpp index 40d3e4f54f..2a8f4c9f8c 100644 --- a/xbmc/interfaces/json-rpc/AudioLibrary.cpp +++ b/xbmc/interfaces/json-rpc/AudioLibrary.cpp @@ -130,6 +130,10 @@ JSONRPC_STATUS CAudioLibrary::GetAlbums(const std::string &method, ITransportLay CMusicDbUrl musicUrl; musicUrl.FromString("musicdb://albums/"); + + if (parameterObject["includesingles"].asBoolean()) + musicUrl.AddOption("show_singles", true); + int artistID = -1, genreID = -1; const CVariant &filter = parameterObject["filter"]; if (filter.isMember("artistid")) @@ -208,6 +212,10 @@ JSONRPC_STATUS CAudioLibrary::GetSongs(const std::string &method, ITransportLaye CMusicDbUrl musicUrl; musicUrl.FromString("musicdb://songs/"); + + if (!parameterObject["includesingles"].asBoolean()) + musicUrl.AddOption("singles", false); + int genreID = -1, albumID = -1, artistID = -1; const CVariant &filter = parameterObject["filter"]; if (filter.isMember("artistid")) diff --git a/xbmc/interfaces/json-rpc/schema/methods.json b/xbmc/interfaces/json-rpc/schema/methods.json index 024316e9a9..1b82ee2203 100644 --- a/xbmc/interfaces/json-rpc/schema/methods.json +++ b/xbmc/interfaces/json-rpc/schema/methods.json @@ -683,7 +683,8 @@ { "type": "object", "properties": { "artist": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, { "$ref": "List.Filter.Albums" } ] - } + }, + { "name": "includesingles", "type": "boolean", "default": false } ], "returns": { "type": "object", @@ -729,7 +730,8 @@ { "type": "object", "properties": { "album": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, { "$ref": "List.Filter.Songs" } ] - } + }, + { "name": "includesingles", "type": "boolean", "default": true } ], "returns": { "type": "object", diff --git a/xbmc/interfaces/json-rpc/schema/types.json b/xbmc/interfaces/json-rpc/schema/types.json index 81b3ed9bb4..3c1708a61b 100644 --- a/xbmc/interfaces/json-rpc/schema/types.json +++ b/xbmc/interfaces/json-rpc/schema/types.json @@ -407,7 +407,8 @@ "theme", "mood", "style", "type", "albumlabel", "rating", "year", "musicbrainzalbumid", "musicbrainzalbumartistid", "fanart", "thumbnail", - "playcount", "genreid", "artistid", "displayartist" ] + "playcount", "genreid", "artistid", "displayartist", + "compilation", "releasetype" ] } }, "Audio.Fields.Song": { @@ -420,9 +421,14 @@ "musicbrainzalbumid", "musicbrainzalbumartistid", "playcount", "fanart", "thumbnail", "file", "albumid", "lastplayed", "disc", "genreid", "artistid", "displayartist", - "albumartistid" ] + "albumartistid", "albumreleasetype" ] } }, + "Audio.Album.ReleaseType": { + "type": "string", + "enum": [ "album", "single" ], + "default": "album" + }, "Audio.Details.Base": { "extends": "Media.Details.Base", "properties": { @@ -471,7 +477,9 @@ "style": { "$ref": "Array.String" }, "type": { "type": "string" }, "albumlabel": { "type": "string" }, - "playcount": { "type": "integer" } + "playcount": { "type": "integer" }, + "compilation": { "type": "boolean" }, + "releasetype": { "$ref": "Audio.Album.ReleaseType" } } }, "Audio.Details.Song": { @@ -491,7 +499,8 @@ "albumid": { "$ref": "Library.Id" }, "lastplayed": { "type": "string" }, "disc": { "type": "integer" }, - "albumartistid": { "$ref": "Array.Integer" } + "albumartistid": { "$ref": "Array.Integer" }, + "albumreleasetype": { "$ref": "Audio.Album.ReleaseType" } } }, "Video.Fields.Movie": { @@ -1230,7 +1239,10 @@ "style": { "$ref": "Array.String" }, "albumlabel": { "type": "string" }, "specialsortseason": { "type": "integer" }, - "specialsortepisode": { "type": "integer" } + "specialsortepisode": { "type": "integer" }, + "compilation": { "type": "boolean" }, + "releasetype": { "$ref": "Audio.Album.ReleaseType" }, + "albumreleasetype": { "$ref": "Audio.Album.ReleaseType" } } }, "List.Fields.All": { @@ -1249,7 +1261,7 @@ "description", "theme", "mood", "style", "albumlabel", "sorttitle", "episodeguide", "uniqueid", "dateadded", "channel", "channeltype", "hidden", "locked", "channelnumber", "starttime", "endtime", "specialsortseason", - "specialsortepisode" ] + "specialsortepisode", "compilation", "releasetype", "albumreleasetype" ] } }, "List.Item.All": { diff --git a/xbmc/interfaces/json-rpc/schema/version.txt b/xbmc/interfaces/json-rpc/schema/version.txt index 9e55b202e1..2496b04b84 100644 --- a/xbmc/interfaces/json-rpc/schema/version.txt +++ b/xbmc/interfaces/json-rpc/schema/version.txt @@ -1 +1 @@ -6.22.2 +6.24.0 diff --git a/xbmc/music/Album.cpp b/xbmc/music/Album.cpp index 447f6e05f5..b2866e1204 100644 --- a/xbmc/music/Album.cpp +++ b/xbmc/music/Album.cpp @@ -19,6 +19,7 @@ */ #include "Album.h" +#include "music/tags/MusicInfoTag.h" #include "settings/AdvancedSettings.h" #include "utils/StringUtils.h" #include "utils/XMLUtils.h" @@ -30,6 +31,18 @@ using namespace std; using namespace MUSIC_INFO; +typedef struct ReleaseTypeInfo { + CAlbum::ReleaseType type; + std::string name; +} ReleaseTypeInfo; + +ReleaseTypeInfo releaseTypes[] = { + { CAlbum::Album, "album" }, + { CAlbum::Single, "single" } +}; + +#define RELEASE_TYPES_SIZE sizeof(releaseTypes) / sizeof(ReleaseTypeInfo) + CAlbum::CAlbum(const CFileItem& item) { Reset(); @@ -81,6 +94,7 @@ CAlbum::CAlbum(const CFileItem& item) iYear = stTime.wYear; bCompilation = tag.GetCompilation(); iTimesPlayed = 0; + releaseType = tag.GetAlbumReleaseType(); } void CAlbum::MergeScrapedAlbum(const CAlbum& source, bool override /* = true */) @@ -147,6 +161,40 @@ std::string CAlbum::GetGenreString() const return StringUtils::Join(genre, g_advancedSettings.m_musicItemSeparator); } +std::string CAlbum::GetReleaseType() const +{ + return ReleaseTypeToString(releaseType); +} + +void CAlbum::SetReleaseType(const std::string& strReleaseType) +{ + releaseType = ReleaseTypeFromString(strReleaseType); +} + +std::string CAlbum::ReleaseTypeToString(CAlbum::ReleaseType releaseType) +{ + for (size_t i = 0; i < RELEASE_TYPES_SIZE; i++) + { + const ReleaseTypeInfo& releaseTypeInfo = releaseTypes[i]; + if (releaseTypeInfo.type == releaseType) + return releaseTypeInfo.name; + } + + return "album"; +} + +CAlbum::ReleaseType CAlbum::ReleaseTypeFromString(const std::string& strReleaseType) +{ + for (size_t i = 0; i < RELEASE_TYPES_SIZE; i++) + { + const ReleaseTypeInfo& releaseTypeInfo = releaseTypes[i]; + if (releaseTypeInfo.name == strReleaseType) + return releaseTypeInfo.type; + } + + return Album; +} + bool CAlbum::operator<(const CAlbum &a) const { if (strMusicBrainzAlbumID.empty() && a.strMusicBrainzAlbumID.empty()) @@ -304,6 +352,12 @@ bool CAlbum::Load(const TiXmlElement *album, bool append, bool prioritise) node = node->NextSiblingElement("track"); } + std::string strReleaseType; + if (XMLUtils::GetString(album, "releasetype", strReleaseType)) + SetReleaseType(strReleaseType); + else + releaseType = Album; + return true; } @@ -379,6 +433,8 @@ bool CAlbum::Save(TiXmlNode *node, const std::string &tag, const std::string& st XMLUtils::SetString(node, "duration", StringUtils::SecondsToTimeString(song->iDuration)); } + XMLUtils::SetString(album, "releasetype", GetReleaseType()); + return true; } diff --git a/xbmc/music/Album.h b/xbmc/music/Album.h index 4b85b13ce2..db7d299368 100644 --- a/xbmc/music/Album.h +++ b/xbmc/music/Album.h @@ -36,7 +36,7 @@ class CAlbum { public: CAlbum(const CFileItem& item); - CAlbum() { idAlbum = 0; iRating = 0; iYear = 0; iTimesPlayed = 0; }; + CAlbum() { idAlbum = 0; iRating = 0; iYear = 0; iTimesPlayed = 0; releaseType = Album; }; bool operator<(const CAlbum &a) const; void MergeScrapedAlbum(const CAlbum& album, bool override = true); @@ -64,11 +64,23 @@ public: iTimesPlayed = 0; songs.clear(); infoSongs.clear(); + releaseType = Album; } std::string GetArtistString() const; std::string GetGenreString() const; + typedef enum ReleaseType { + Album = 0, + Single + } ReleaseType; + + std::string GetReleaseType() const; + void SetReleaseType(const std::string& strReleaseType); + + static std::string ReleaseTypeToString(ReleaseType releaseType); + static ReleaseType ReleaseTypeFromString(const std::string& strReleaseType); + /*! \brief Load album information from an XML file. See CVideoInfoTag::Load for a description of the types of elements we load. \param element the root XML element to parse. @@ -101,6 +113,7 @@ public: int iTimesPlayed; VECSONGS songs; ///< Local songs VECSONGS infoSongs; ///< Scraped songs + ReleaseType releaseType; }; typedef std::vector<CAlbum> VECALBUMS; diff --git a/xbmc/music/CueInfoLoader.cpp b/xbmc/music/CueInfoLoader.cpp index f81fee7575..9c2f16326c 100644 --- a/xbmc/music/CueInfoLoader.cpp +++ b/xbmc/music/CueInfoLoader.cpp @@ -18,6 +18,7 @@ * */ #include "CueInfoLoader.h" +#include "music/tags/MusicInfoTag.h" void CueInfoLoader::Load(const std::string& aStrCuesheet, CFileItemPtr aFileItem) { diff --git a/xbmc/music/EmbeddedArt.h b/xbmc/music/EmbeddedArt.h new file mode 100644 index 0000000000..55bf2bb25a --- /dev/null +++ b/xbmc/music/EmbeddedArt.h @@ -0,0 +1,60 @@ +#pragma once +/* +* Copyright (C) 2015 Team XBMC +* http://xbmc.org +* +* This Program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* 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 XBMC; see the file COPYING. If not, see +* <http://www.gnu.org/licenses/>. +* +*/ + +#include <stdint.h> +#include <string> +#include <vector> + +#include "utils/IArchivable.h" + +namespace MUSIC_INFO +{ + class EmbeddedArtInfo : public IArchivable + { + public: + EmbeddedArtInfo() { } + EmbeddedArtInfo(size_t size, const std::string &mime); + ~EmbeddedArtInfo() { } + + // implementation of IArchivable + virtual void Archive(CArchive& ar); + + void set(size_t size, const std::string &mime); + void clear(); + bool empty() const; + bool matches(const EmbeddedArtInfo &right) const; + + size_t size; + std::string mime; + }; + + class EmbeddedArt : public EmbeddedArtInfo + { + public: + EmbeddedArt() { } + EmbeddedArt(const uint8_t *data, size_t size, const std::string &mime); + ~EmbeddedArt() { } + + void set(const uint8_t *data, size_t size, const std::string &mime); + + std::vector<uint8_t> data; + }; +}
\ No newline at end of file diff --git a/xbmc/music/MusicDatabase.cpp b/xbmc/music/MusicDatabase.cpp index 9cd434e471..6482c321a3 100644 --- a/xbmc/music/MusicDatabase.cpp +++ b/xbmc/music/MusicDatabase.cpp @@ -138,7 +138,8 @@ void CMusicDatabase::CreateTables() " strType text, " " iRating integer, " " lastScraped varchar(20) default NULL, " - " dateAdded varchar (20) default NULL)"); + " dateAdded varchar (20) default NULL, " + " strReleaseType text)"); CLog::Log(LOGINFO, "create album_artist table"); m_pDS->exec("CREATE TABLE album_artist (idArtist integer, idAlbum integer, strJoinPhrase text, boolFeatured integer, iOrder integer, strArtist text)"); CLog::Log(LOGINFO, "create album_genre table"); @@ -276,7 +277,8 @@ void CMusicDatabase::CreateViews() " strPath, " " iKaraNumber, iKaraDelay, strKaraEncoding," " album.bCompilation AS bCompilation," - " album.strArtists AS strAlbumArtists " + " album.strArtists AS strAlbumArtists, " + " album.strReleaseType AS strAlbumReleaseType " "FROM song" " JOIN album ON" " song.idAlbum=album.idAlbum" @@ -302,7 +304,8 @@ void CMusicDatabase::CreateViews() " album.strImage as strImage, " " iRating, " " bCompilation, " - " MIN(song.iTimesPlayed) AS iTimesPlayed " + " MIN(song.iTimesPlayed) AS iTimesPlayed, " + " strReleaseType " "FROM album" " LEFT OUTER JOIN song ON" " album.idAlbum=song.idAlbum " @@ -481,7 +484,7 @@ bool CMusicDatabase::AddAlbum(CAlbum& album) GetArtistString(album.artistCredits), album.GetGenreString(), album.iYear, - album.bCompilation); + album.bCompilation, album.releaseType); // Add the album artists for (VECARTISTCREDITS::iterator artistCredit = album.artistCredits.begin(); artistCredit != album.artistCredits.end(); ++artistCredit) @@ -549,7 +552,7 @@ bool CMusicDatabase::UpdateAlbum(CAlbum& album) album.strReview, album.thumbURL.m_xml.c_str(), album.strLabel, album.strType, - album.iRating, album.iYear, album.bCompilation); + album.iRating, album.iYear, album.bCompilation, album.releaseType); // Add the album artists DeleteAlbumArtistsByAlbum(album.idAlbum); @@ -829,7 +832,8 @@ int CMusicDatabase::UpdateSong(int idSong, } int CMusicDatabase::AddAlbum(const std::string& strAlbum, const std::string& strMusicBrainzAlbumID, - const std::string& strArtist, const std::string& strGenre, int year, bool bCompilation) + const std::string& strArtist, const std::string& strGenre, int year, + bool bCompilation, CAlbum::ReleaseType releaseType) { std::string strSQL; try @@ -851,20 +855,22 @@ int CMusicDatabase::AddAlbum(const std::string& strAlbum, const std::string& str m_pDS->close(); // doesnt exists, add it if (strMusicBrainzAlbumID.empty()) - strSQL=PrepareSQL("insert into album (idAlbum, strAlbum, strMusicBrainzAlbumID, strArtists, strGenres, iYear, bCompilation) values( NULL, '%s', NULL, '%s', '%s', %i, %i)", + strSQL=PrepareSQL("insert into album (idAlbum, strAlbum, strMusicBrainzAlbumID, strArtists, strGenres, iYear, bCompilation, strReleaseType) values( NULL, '%s', NULL, '%s', '%s', %i, %i, '%s')", strAlbum.c_str(), strArtist.c_str(), strGenre.c_str(), year, - bCompilation); + bCompilation, + CAlbum::ReleaseTypeToString(releaseType).c_str()); else - strSQL=PrepareSQL("insert into album (idAlbum, strAlbum, strMusicBrainzAlbumID, strArtists, strGenres, iYear, bCompilation) values( NULL, '%s', '%s', '%s', '%s', %i, %i)", + strSQL=PrepareSQL("insert into album (idAlbum, strAlbum, strMusicBrainzAlbumID, strArtists, strGenres, iYear, bCompilation, strReleaseType) values( NULL, '%s', '%s', '%s', '%s', %i, %i, '%s')", strAlbum.c_str(), strMusicBrainzAlbumID.c_str(), strArtist.c_str(), strGenre.c_str(), year, - bCompilation); + bCompilation, + CAlbum::ReleaseTypeToString(releaseType).c_str()); m_pDS->exec(strSQL.c_str()); return (int)m_pDS->lastinsertid(); @@ -883,18 +889,20 @@ int CMusicDatabase::AddAlbum(const std::string& strAlbum, const std::string& str int idAlbum = m_pDS->fv("idAlbum").get_asInt(); m_pDS->close(); if (strMusicBrainzAlbumID.empty()) - strSQL=PrepareSQL("UPDATE album SET strGenres = '%s', iYear=%i, bCompilation=%i, lastScraped = NULL WHERE idAlbum=%i", + strSQL=PrepareSQL("UPDATE album SET strGenres = '%s', iYear=%i, bCompilation=%i, strReleaseType = '%s', lastScraped = NULL WHERE idAlbum=%i", strGenre.c_str(), year, bCompilation, + CAlbum::ReleaseTypeToString(releaseType).c_str(), idAlbum); else - strSQL=PrepareSQL("UPDATE album SET strAlbum = '%s', strArtists = '%s', strGenres = '%s', iYear=%i, bCompilation=%i, lastScraped = NULL WHERE idAlbum=%i", + strSQL=PrepareSQL("UPDATE album SET strAlbum = '%s', strArtists = '%s', strGenres = '%s', iYear=%i, bCompilation=%i, strReleaseType = '%s', lastScraped = NULL WHERE idAlbum=%i", strAlbum.c_str(), strArtist.c_str(), strGenre.c_str(), year, bCompilation, + CAlbum::ReleaseTypeToString(releaseType).c_str(), idAlbum); m_pDS->exec(strSQL.c_str()); DeleteAlbumArtistsByAlbum(idAlbum); @@ -917,7 +925,8 @@ int CMusicDatabase::UpdateAlbum(int idAlbum, const std::string& strThemes, const std::string& strReview, const std::string& strImage, const std::string& strLabel, const std::string& strType, - int iRating, int iYear, bool bCompilation) + int iRating, int iYear, bool bCompilation, + CAlbum::ReleaseType releaseType) { if (idAlbum < 0) return -1; @@ -928,12 +937,14 @@ int CMusicDatabase::UpdateAlbum(int idAlbum, " strMoods = '%s', strStyles = '%s', strThemes = '%s', " " strReview = '%s', strImage = '%s', strLabel = '%s', " " strType = '%s', iRating = %i," - " iYear = %i, bCompilation = %i, lastScraped = '%s'", + " iYear = %i, bCompilation = %i, strReleaseType = '%s', " + " lastScraped = '%s'", strAlbum.c_str(), strArtist.c_str(), strGenre.c_str(), strMoods.c_str(), strStyles.c_str(), strThemes.c_str(), strReview.c_str(), strImage.c_str(), strLabel.c_str(), strType.c_str(), iRating, iYear, bCompilation, + CAlbum::ReleaseTypeToString(releaseType).c_str(), CDateTime::GetCurrentDateTime().GetAsDBDateTime().c_str()); if (strMusicBrainzAlbumID.empty()) strSQL += PrepareSQL(", strMusicBrainzAlbumID = NULL"); @@ -1706,6 +1717,7 @@ void CMusicDatabase::GetFileItemFromDataset(const dbiplus::sql_record* const rec item->GetMusicInfoTag()->SetURL(strRealPath); item->GetMusicInfoTag()->SetCompilation(record->at(song_bCompilation).get_asInt() == 1); item->GetMusicInfoTag()->SetAlbumArtist(record->at(song_strAlbumArtists).get_asString()); + item->GetMusicInfoTag()->SetAlbumReleaseType(CAlbum::ReleaseTypeFromString(record->at(song_strAlbumReleaseType).get_asString())); item->GetMusicInfoTag()->SetLoaded(true); // Get filename with full path if (!baseUrl.IsValid()) @@ -1749,6 +1761,7 @@ CAlbum CMusicDatabase::GetAlbumFromDataset(const dbiplus::sql_record* const reco album.strType = record->at(offset + album_strType).get_asString(); album.bCompilation = record->at(offset + album_bCompilation).get_asInt() == 1; album.iTimesPlayed = record->at(offset + album_iTimesPlayed).get_asInt(); + album.SetReleaseType(record->at(offset + album_strReleaseType).get_asString()); return album; } @@ -4041,11 +4054,20 @@ void CMusicDatabase::UpdateTables(int version) { m_pDS->exec("CREATE TABLE cue (idPath integer, strFileName text, strCuesheet text)"); } + if (version < 50) + { + // add a new column strReleaseType for albums + m_pDS->exec("ALTER TABLE album ADD strReleaseType text\n"); + + // set strReleaseType based on album name + m_pDS->exec(PrepareSQL("UPDATE album SET strReleaseType = '%s' WHERE strAlbum IS NOT NULL AND strAlbum <> ''", CAlbum::ReleaseTypeToString(CAlbum::Album).c_str())); + m_pDS->exec(PrepareSQL("UPDATE album SET strReleaseType = '%s' WHERE strAlbum IS NULL OR strAlbum = ''", CAlbum::ReleaseTypeToString(CAlbum::Single).c_str())); + } } int CMusicDatabase::GetSchemaVersion() const { - return 49; + return 50; } unsigned int CMusicDatabase::GetSongIDs(const Filter &filter, vector<pair<int,int> > &songIDs) @@ -4390,6 +4412,12 @@ int CMusicDatabase::GetCompilationAlbumsCount() return strtol(GetSingleValue("album", "count(idAlbum)", "bCompilation = 1").c_str(), NULL, 10); } +int CMusicDatabase::GetSinglesCount() +{ + CDatabase::Filter filter(PrepareSQL("songview.idAlbum IN (SELECT idAlbum FROM album WHERE strReleaseType = '%s')", CAlbum::ReleaseTypeToString(CAlbum::Single).c_str())); + return GetSongsCount(filter); +} + bool CMusicDatabase::SetPathHash(const std::string &path, const std::string &hash) { try @@ -5468,6 +5496,7 @@ void CMusicDatabase::SetPropertiesFromAlbum(CFileItem& item, const CAlbum& album item.SetProperty("album_title", album.strAlbum); if (album.iRating > 0) item.SetProperty("album_rating", album.iRating); + item.SetProperty("album_releasetype", CAlbum::ReleaseTypeToString(album.releaseType)); } void CMusicDatabase::SetPropertiesForFileItem(CFileItem& item) @@ -5724,7 +5753,7 @@ bool CMusicDatabase::GetFilter(CDbUrl &musicUrl, Filter &filter, SortDescription { option = options.find("show_singles"); if (option == options.end() || !option->second.asBoolean()) - filter.AppendWhere("albumview.strAlbum <> ''"); + filter.AppendWhere(PrepareSQL("albumview.strReleaseType = '%s'", CAlbum::ReleaseTypeToString(CAlbum::Album).c_str())); } } } @@ -5732,7 +5761,9 @@ bool CMusicDatabase::GetFilter(CDbUrl &musicUrl, Filter &filter, SortDescription { option = options.find("singles"); if (option != options.end()) - filter.AppendWhere(PrepareSQL("songview.idAlbum %sIN (SELECT idAlbum FROM album WHERE strAlbum = '')", option->second.asBoolean() ? "" : "NOT ")); + filter.AppendWhere(PrepareSQL("songview.idAlbum %sIN (SELECT idAlbum FROM album WHERE strReleaseType = '%s')", + option->second.asBoolean() ? "" : "NOT ", + CAlbum::ReleaseTypeToString(CAlbum::Single).c_str())); option = options.find("year"); if (option != options.end()) diff --git a/xbmc/music/MusicDatabase.h b/xbmc/music/MusicDatabase.h index d9c9cabb68..41b091d001 100644 --- a/xbmc/music/MusicDatabase.h +++ b/xbmc/music/MusicDatabase.h @@ -206,7 +206,7 @@ public: */ int AddAlbum(const std::string& strAlbum, const std::string& strMusicBrainzAlbumID, const std::string& strArtist, const std::string& strGenre, - int year, bool bCompilation); + int year, bool bCompilation, CAlbum::ReleaseType releaseType); /*! \brief retrieve an album, optionally with all songs. \param idAlbum the database id of the album. \param album [out] the album to fill. @@ -222,7 +222,8 @@ public: const std::string& strThemes, const std::string& strReview, const std::string& strImage, const std::string& strLabel, const std::string& strType, - int iRating, int iYear, bool bCompilation); + int iRating, int iYear, bool bCompilation, + CAlbum::ReleaseType releaseType); bool ClearAlbumLastScrapedTime(int idAlbum); bool HasAlbumBeenScraped(int idAlbum); int AddAlbumInfoSong(int idAlbum, const CSong& song); @@ -328,6 +329,8 @@ public: bool GetCompilationAlbums(const std::string& strBaseDir, CFileItemList& items); bool GetCompilationSongs(const std::string& strBaseDir, CFileItemList& items); int GetCompilationAlbumsCount(); + + int GetSinglesCount(); /*! \brief Increment the playcount of an item Increments the playcount and updates the last played date @@ -533,6 +536,7 @@ private: song_strKarEncoding, song_bCompilation, song_strAlbumArtists, + song_strAlbumReleaseType, song_enumCount // end of the enum, do not add past here } SongFields; @@ -556,6 +560,7 @@ private: album_iRating, album_bCompilation, album_iTimesPlayed, + album_strReleaseType, album_enumCount // end of the enum, do not add past here } AlbumFields; diff --git a/xbmc/music/Song.h b/xbmc/music/Song.h index c32be05e21..a58a693677 100644 --- a/xbmc/music/Song.h +++ b/xbmc/music/Song.h @@ -25,7 +25,8 @@ #include "utils/ISerializable.h" #include "XBDateTime.h" -#include "music/tags/MusicInfoTag.h" // for EmbeddedArt +#include "music/EmbeddedArt.h" +#include "music/tags/ReplayGain.h" #include "Artist.h" #include <map> #include <string> diff --git a/xbmc/music/infoscanner/MusicInfoScanner.cpp b/xbmc/music/infoscanner/MusicInfoScanner.cpp index 4b2eba531f..18ef221bb1 100644 --- a/xbmc/music/infoscanner/MusicInfoScanner.cpp +++ b/xbmc/music/infoscanner/MusicInfoScanner.cpp @@ -766,6 +766,10 @@ int CMusicInfoScanner::RetrieveMusicInfo(const std::string& strDirectory, CFileI if (m_bStop) break; + // mark albums without a title as singles + if (album->strAlbum.empty()) + album->releaseType = CAlbum::Single; + album->strPath = strDirectory; m_musicDatabase.AddAlbum(*album); diff --git a/xbmc/music/tags/MusicInfoTag.cpp b/xbmc/music/tags/MusicInfoTag.cpp index 41ab6e9769..4ad6ada305 100644 --- a/xbmc/music/tags/MusicInfoTag.cpp +++ b/xbmc/music/tags/MusicInfoTag.cpp @@ -125,6 +125,7 @@ const CMusicInfoTag& CMusicInfoTag::operator =(const CMusicInfoTag& tag) m_type = tag.m_type; m_iAlbumId = tag.m_iAlbumId; m_replayGain = tag.m_replayGain; + m_albumReleaseType = tag.m_albumReleaseType; memcpy(&m_dwReleaseDate, &tag.m_dwReleaseDate, sizeof(m_dwReleaseDate) ); m_coverArt = tag.m_coverArt; @@ -142,6 +143,7 @@ bool CMusicInfoTag::operator !=(const CMusicInfoTag& tag) const if (m_strAlbum != tag.m_strAlbum) return true; if (m_iDuration != tag.m_iDuration) return true; if (m_iTrack != tag.m_iTrack) return true; + if (m_albumReleaseType != tag.m_albumReleaseType) return true; return false; } @@ -275,6 +277,11 @@ const ReplayGain& CMusicInfoTag::GetReplayGain() const return m_replayGain; } +CAlbum::ReleaseType CMusicInfoTag::GetAlbumReleaseType() const +{ + return m_albumReleaseType; +} + void CMusicInfoTag::SetURL(const std::string& strURL) { m_strURL = strURL; @@ -486,6 +493,11 @@ void CMusicInfoTag::SetReplayGain(const ReplayGain& aGain) m_replayGain = aGain; } +void CMusicInfoTag::SetAlbumReleaseType(CAlbum::ReleaseType releaseType) +{ + m_albumReleaseType = releaseType; +} + void CMusicInfoTag::SetArtist(const CArtist& artist) { SetArtist(artist.strArtist); @@ -509,6 +521,7 @@ void CMusicInfoTag::SetAlbum(const CAlbum& album) SYSTEMTIME stTime; stTime.wYear = album.iYear; SetReleaseDate(stTime); + SetAlbumReleaseType(album.releaseType); m_iTimesPlayed = album.iTimesPlayed; m_iDbId = album.idAlbum; m_type = MediaTypeAlbum; @@ -576,6 +589,11 @@ void CMusicInfoTag::Serialize(CVariant& value) const value["lyrics"] = m_strLyrics; value["albumid"] = m_iAlbumId; value["compilationartist"] = m_bCompilation; + value["compilation"] = m_bCompilation; + if (m_type.compare(MediaTypeAlbum) == 0) + value["releasetype"] = CAlbum::ReleaseTypeToString(m_albumReleaseType); + else if (m_type.compare(MediaTypeSong) == 0) + value["albumreleasetype"] = CAlbum::ReleaseTypeToString(m_albumReleaseType); } void CMusicInfoTag::ToSortable(SortItem& sortable, Field field) const @@ -638,6 +656,7 @@ void CMusicInfoTag::Archive(CArchive& ar) ar << m_listeners; ar << m_coverArt; ar << m_cuesheet; + ar << static_cast<int>(m_albumReleaseType); } else { @@ -668,6 +687,10 @@ void CMusicInfoTag::Archive(CArchive& ar) ar >> m_listeners; ar >> m_coverArt; ar >> m_cuesheet; + + int albumReleaseType; + ar >> albumReleaseType; + m_albumReleaseType = static_cast<CAlbum::ReleaseType>(albumReleaseType); } } @@ -699,6 +722,7 @@ void CMusicInfoTag::Clear() m_iAlbumId = -1; m_coverArt.clear(); m_replayGain = ReplayGain(); + m_albumReleaseType = CAlbum::Album; } void CMusicInfoTag::AppendArtist(const std::string &artist) diff --git a/xbmc/music/tags/MusicInfoTag.h b/xbmc/music/tags/MusicInfoTag.h index 7c861b4497..0ba65c0f19 100644 --- a/xbmc/music/tags/MusicInfoTag.h +++ b/xbmc/music/tags/MusicInfoTag.h @@ -20,45 +20,23 @@ */ class CSong; -class CAlbum; class CArtist; -#include <vector> -#include <string> #include <stdint.h> +#include <string> +#include <vector> +#include "ReplayGain.h" +#include "XBDateTime.h" +#include "music/Album.h" +#include "music/EmbeddedArt.h" #include "utils/IArchivable.h" #include "utils/ISerializable.h" #include "utils/ISortable.h" -#include "XBDateTime.h" -#include "ReplayGain.h" namespace MUSIC_INFO { - class EmbeddedArtInfo : public IArchivable - { - public: - EmbeddedArtInfo() {}; - EmbeddedArtInfo(size_t size, const std::string &mime); - void set(size_t size, const std::string &mime); - void clear(); - bool empty() const; - bool matches(const EmbeddedArtInfo &right) const; - virtual void Archive(CArchive& ar); - size_t size; - std::string mime; - }; - - class EmbeddedArt : public EmbeddedArtInfo - { - public: - EmbeddedArt() {}; - EmbeddedArt(const uint8_t *data, size_t size, const std::string &mime); - void set(const uint8_t *data, size_t size, const std::string &mime); - std::vector<uint8_t> data; - }; - class CMusicInfoTag : public IArchivable, public ISerializable, public ISortable { public: @@ -100,6 +78,7 @@ public: int GetPlayCount() const; const EmbeddedArtInfo &GetCoverArtInfo() const; const ReplayGain& GetReplayGain() const; + CAlbum::ReleaseType GetAlbumReleaseType() const; void SetURL(const std::string& strURL); void SetTitle(const std::string& strTitle); @@ -138,6 +117,7 @@ public: void SetCompilation(bool compilation); void SetCoverArtInfo(size_t size, const std::string &mimeType); void SetReplayGain(const ReplayGain& aGain); + void SetAlbumReleaseType(CAlbum::ReleaseType releaseType); /*! \brief Append a unique artist to the artist list Checks if we have this artist already added, and if not adds it to the songs artist list. @@ -195,6 +175,7 @@ protected: int m_iTimesPlayed; int m_iAlbumId; SYSTEMTIME m_dwReleaseDate; + CAlbum::ReleaseType m_albumReleaseType; EmbeddedArtInfo m_coverArt; ///< art information |