aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSascha Montellese <sascha.montellese@gmail.com>2015-04-01 18:43:41 +0200
committerSascha Montellese <sascha.montellese@gmail.com>2015-04-01 18:43:41 +0200
commit9d9c66022eb1358c13c592180943a9f85fba5171 (patch)
treea3fd576284647a1df41b8e896907aa1ebf17946b
parentf4ad529a6a7b59eff19ca1932d283a79ac4868ff (diff)
parentd928d1969c828c24131e070336fa5f22c95b0d9c (diff)
Merge pull request #6810 from Montellese/musicdb_singles
musicdb: cleanup detection of Singles
-rw-r--r--Kodi.xcodeproj/project.pbxproj2
-rw-r--r--project/VS2010Express/XBMC.vcxproj3
-rw-r--r--project/VS2010Express/XBMC.vcxproj.filters8
-rw-r--r--xbmc/Application.cpp1
-rw-r--r--xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeOverview.cpp3
-rw-r--r--xbmc/interfaces/json-rpc/AudioLibrary.cpp8
-rw-r--r--xbmc/interfaces/json-rpc/schema/methods.json6
-rw-r--r--xbmc/interfaces/json-rpc/schema/types.json24
-rw-r--r--xbmc/interfaces/json-rpc/schema/version.txt2
-rw-r--r--xbmc/music/Album.cpp56
-rw-r--r--xbmc/music/Album.h15
-rw-r--r--xbmc/music/CueInfoLoader.cpp1
-rw-r--r--xbmc/music/EmbeddedArt.h60
-rw-r--r--xbmc/music/MusicDatabase.cpp65
-rw-r--r--xbmc/music/MusicDatabase.h9
-rw-r--r--xbmc/music/Song.h3
-rw-r--r--xbmc/music/infoscanner/MusicInfoScanner.cpp4
-rw-r--r--xbmc/music/tags/MusicInfoTag.cpp24
-rw-r--r--xbmc/music/tags/MusicInfoTag.h37
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