Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

[GSoC] artist-based smartplaylists #1249

Merged
merged 2 commits into from

3 participants

@Montellese
Owner

This adds very basic support for artist-based smartplaylists. There are only very few possible rules i.e. artist, genre, moods, styles, born, bandformed, disbanded, died, biography, instruments and a compilation artist switch (not sure if this one makes sense I never really understood how that works). These rules could be extended if necessary.

@Montellese
Owner

I extracted the changes to SmartPlaylist.cpp which were actually fixes for existing bugs (which nobody noticed so far it seems) and already pushed them to master.

@jmarshallnz or @night199uk could one of you shed some light on the implications of enabling/disabling "include artists who appear only on compilations"? Does it change the way the scraper works (i.e. it ignores those artists if enabled) or does it only change the way the SQL queries in CMusicDatabase::GetArtistsNav work (with the albumArtistsOnly parameter)? If the former holds true the "compilation artists" rule I added does not make any sense otherwise IMO it does.

@jmarshallnz
Owner
@Montellese
Owner

It's not an advanced setting it's a GUI setting in Settings -> Music -> Library. I always keep it disabled to get a clean list of artists but if I understood @night199uk right he plans to improve scraping/organization of all those "Foo feat. Bar" so it might make sense to just keep it on the SQL level i.e. grab the information for all the artists but in Music -> Artists only show the album artists. Then maybe add a new node Music -> Compilation artists where only those artists are shown.

Thinking about it I'll remove that rule/filter because I have neither the understanding for it nor the items/database to actually test it.

@night199uk
Collaborator
@Montellese
Owner

@night199uk: I've removed that part for now because I can't test it anyway. I was also confused by boolFeatured and bCompilation so I can still add it back once your musicdatabase changes/refactor have been merged as well.

@Montellese Montellese was assigned
@Montellese
Owner

@cptspiff Thanks for the review and for spotting that oopsie. I fixed the issues you pointed out.

@Montellese Montellese merged commit 5817696 into xbmc:master
@Montellese Montellese deleted the Montellese:gsoc_xsp_artists branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
2  xbmc/dialogs/GUIDialogSmartPlaylistEditor.cpp
@@ -57,6 +57,7 @@ typedef struct
static const translateType types[] = { { CGUIDialogSmartPlaylistEditor::TYPE_SONGS, "songs", 134 },
{ CGUIDialogSmartPlaylistEditor::TYPE_ALBUMS, "albums", 132 },
+ { CGUIDialogSmartPlaylistEditor::TYPE_ARTISTS, "artists", 133 },
{ CGUIDialogSmartPlaylistEditor::TYPE_MIXED, "mixed", 20395 },
{ CGUIDialogSmartPlaylistEditor::TYPE_MUSICVIDEOS, "musicvideos", 20389 },
{ CGUIDialogSmartPlaylistEditor::TYPE_MOVIES, "movies", 20342 },
@@ -356,6 +357,7 @@ void CGUIDialogSmartPlaylistEditor::OnWindowLoaded()
{ // music types + mixed
allowedTypes.push_back(TYPE_SONGS);
allowedTypes.push_back(TYPE_ALBUMS);
+ allowedTypes.push_back(TYPE_ARTISTS);
allowedTypes.push_back(TYPE_MIXED);
}
else if (m_mode.Equals("video"))
View
2  xbmc/dialogs/GUIDialogSmartPlaylistEditor.h
@@ -30,7 +30,7 @@ class CGUIDialogSmartPlaylistEditor :
public CGUIDialog
{
public:
- enum PLAYLIST_TYPE { TYPE_SONGS = 1, TYPE_ALBUMS, TYPE_MIXED, TYPE_MUSICVIDEOS, TYPE_MOVIES, TYPE_TVSHOWS, TYPE_EPISODES };
+ enum PLAYLIST_TYPE { TYPE_SONGS = 1, TYPE_ALBUMS, TYPE_ARTISTS, TYPE_MIXED, TYPE_MUSICVIDEOS, TYPE_MOVIES, TYPE_TVSHOWS, TYPE_EPISODES };
CGUIDialogSmartPlaylistEditor(void);
virtual ~CGUIDialogSmartPlaylistEditor(void);
View
4 xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp
@@ -117,7 +117,7 @@ void CGUIDialogSmartPlaylistRule::OnBrowse()
{
if (m_type.Equals("tvshows") || m_type.Equals("episodes") || m_type.Equals("movies"))
videodatabase.GetGenresNav("videodb://2/1/",items,type);
- else if (m_type.Equals("songs") || m_type.Equals("albums") || m_type.Equals("mixed"))
+ else if (m_type.Equals("songs") || m_type.Equals("albums") || m_type.Equals("artists") || m_type.Equals("mixed"))
database.GetGenresNav("musicdb://1/",items);
if (m_type.Equals("musicvideos") || m_type.Equals("mixed"))
{
@@ -134,7 +134,7 @@ void CGUIDialogSmartPlaylistRule::OnBrowse()
}
else if (m_rule.m_field == FieldArtist || m_rule.m_field == FieldAlbumArtist)
{
- if (m_type.Equals("songs") || m_type.Equals("mixed") || m_type.Equals("albums"))
+ if (m_type.Equals("songs") || m_type.Equals("mixed") || m_type.Equals("albums") || m_type.Equals("artists"))
database.GetArtistsNav("musicdb://2/", items, m_rule.m_field == FieldAlbumArtist, -1);
if (m_type.Equals("musicvideos") || m_type.Equals("mixed"))
{
View
21 xbmc/filesystem/SmartPlaylistDirectory.cpp
@@ -120,6 +120,27 @@ namespace XFILE
db.Close();
}
}
+ else if (playlist.GetType().Equals("artists"))
+ {
+ CMusicDatabase db;
+ if (db.Open())
+ {
+ CMusicDbUrl musicUrl;
+ CStdString xsp;
+
+ if (!musicUrl.FromString("musicdb://2/") || !playlist.SaveAsJson(xsp, false))
+ return false;
+
+ // store the smartplaylist as JSON in the URL as well
+ musicUrl.AddOption("xsp", xsp);
+
+ CDatabase::Filter filter;
+ success = db.GetArtistsByWhere(musicUrl.ToString(), filter, items, sorting);
+ items.SetContent("albums");
+ db.Close();
+ }
+ }
+
if (playlist.GetType().Equals("songs") || playlist.GetType().Equals("mixed") || playlist.GetType().IsEmpty())
{
CMusicDatabase db;
View
9 xbmc/interfaces/json-rpc/AudioLibrary.cpp
@@ -63,8 +63,13 @@ JSONRPC_STATUS CAudioLibrary::GetArtists(const CStdString &method, ITransportLay
if (parameterObject["albumartistsonly"].isBoolean())
albumArtistsOnly = parameterObject["albumartistsonly"].asBoolean();
+ SortDescription sorting;
+ ParseLimits(parameterObject, sorting.limitStart, sorting.limitEnd);
+ if (!ParseSorting(parameterObject, sorting.sortBy, sorting.sortOrder, sorting.sortAttributes))
+ return InvalidParams;
+
CFileItemList items;
- if (!musicdatabase.GetArtistsNav(musicUrl.ToString(), items, albumArtistsOnly, genreID, albumID, songID))
+ if (!musicdatabase.GetArtistsNav(musicUrl.ToString(), items, albumArtistsOnly, genreID, albumID, songID, sorting))
return InternalError;
// Add "artist" to "properties" array by default
@@ -73,7 +78,7 @@ JSONRPC_STATUS CAudioLibrary::GetArtists(const CStdString &method, ITransportLay
param["properties"] = CVariant(CVariant::VariantTypeArray);
param["properties"].append("artist");
- HandleFileItemList("artistid", false, "artists", items, param, result);
+ HandleFileItemList("artistid", false, "artists", items, param, result, false);
return OK;
}
View
129 xbmc/music/MusicDatabase.cpp
@@ -955,25 +955,30 @@ CAlbum CMusicDatabase::GetAlbumFromDataset(const dbiplus::sql_record* const reco
CArtist CMusicDatabase::GetArtistFromDataset(dbiplus::Dataset* pDS, bool needThumb)
{
+ return GetArtistFromDataset(pDS->get_sql_record(), needThumb);
+}
+
+CArtist CMusicDatabase::GetArtistFromDataset(const dbiplus::sql_record* const record, bool needThumb /* = true */)
+{
CArtist artist;
- artist.idArtist = pDS->fv(artist_idArtist).get_asInt();
- artist.strArtist = pDS->fv(artist_strArtist).get_asString();
- artist.genre = StringUtils::Split(pDS->fv(artist_strGenres).get_asString(), g_advancedSettings.m_musicItemSeparator);
- artist.strBiography = pDS->fv(artist_strBiography).get_asString();
- artist.styles = StringUtils::Split(pDS->fv(artist_strStyles).get_asString(), g_advancedSettings.m_musicItemSeparator);
- artist.moods = StringUtils::Split(pDS->fv(artist_strMoods).get_asString(), g_advancedSettings.m_musicItemSeparator);
- artist.strBorn = pDS->fv(artist_strBorn).get_asString();
- artist.strFormed = pDS->fv(artist_strFormed).get_asString();
- artist.strDied = pDS->fv(artist_strDied).get_asString();
- artist.strDisbanded = pDS->fv(artist_strDisbanded).get_asString();
- artist.yearsActive = StringUtils::Split(pDS->fv(artist_strYearsActive).get_asString(), g_advancedSettings.m_musicItemSeparator);
- artist.instruments = StringUtils::Split(pDS->fv(artist_strInstruments).get_asString(), g_advancedSettings.m_musicItemSeparator);
+ artist.idArtist = record->at(artist_idArtist).get_asInt();
+ artist.strArtist = record->at(artist_strArtist).get_asString();
+ artist.genre = StringUtils::Split(record->at(artist_strGenres).get_asString(), g_advancedSettings.m_musicItemSeparator);
+ artist.strBiography = record->at(artist_strBiography).get_asString();
+ artist.styles = StringUtils::Split(record->at(artist_strStyles).get_asString(), g_advancedSettings.m_musicItemSeparator);
+ artist.moods = StringUtils::Split(record->at(artist_strMoods).get_asString(), g_advancedSettings.m_musicItemSeparator);
+ artist.strBorn = record->at(artist_strBorn).get_asString();
+ artist.strFormed = record->at(artist_strFormed).get_asString();
+ artist.strDied = record->at(artist_strDied).get_asString();
+ artist.strDisbanded = record->at(artist_strDisbanded).get_asString();
+ artist.yearsActive = StringUtils::Split(record->at(artist_strYearsActive).get_asString(), g_advancedSettings.m_musicItemSeparator);
+ artist.instruments = StringUtils::Split(record->at(artist_strInstruments).get_asString(), g_advancedSettings.m_musicItemSeparator);
if (needThumb)
{
- artist.fanart.m_xml = pDS->fv(artist_strFanart).get_asString();
+ artist.fanart.m_xml = record->at(artist_strFanart).get_asString();
artist.fanart.Unpack();
- artist.thumbURL.ParseString(pDS->fv(artist_strImage).get_asString());
+ artist.thumbURL.ParseString(record->at(artist_strImage).get_asString());
}
return artist;
@@ -2747,7 +2752,7 @@ bool CMusicDatabase::GetAlbumsByYear(const CStdString& strBaseDir, CFileItemList
return GetAlbumsByWhere(musicUrl.ToString(), filter, items);
}
-bool CMusicDatabase::GetArtistsNav(const CStdString& strBaseDir, CFileItemList& items, bool albumArtistsOnly /* = false */, int idGenre /* = -1 */, int idAlbum /* = -1 */, int idSong /* = -1 */)
+bool CMusicDatabase::GetArtistsNav(const CStdString& strBaseDir, CFileItemList& items, bool albumArtistsOnly /* = false */, int idGenre /* = -1 */, int idAlbum /* = -1 */, int idSong /* = -1 */, const SortDescription &sortDescription /* = SortDescription() */)
{
if (NULL == m_pDB.get()) return false;
if (NULL == m_pDS.get()) return false;
@@ -2769,7 +2774,7 @@ bool CMusicDatabase::GetArtistsNav(const CStdString& strBaseDir, CFileItemList&
musicUrl.AddOption("albumartistsonly", albumArtistsOnly);
Filter filter;
- bool result = GetArtistsByWhere(musicUrl.ToString(), filter, items);
+ bool result = GetArtistsByWhere(musicUrl.ToString(), filter, items, sortDescription);
CLog::Log(LOGDEBUG,"Time to retrieve artists from dataset = %i", XbmcThreads::SystemClockMillis() - time);
return result;
@@ -2782,20 +2787,49 @@ bool CMusicDatabase::GetArtistsNav(const CStdString& strBaseDir, CFileItemList&
return false;
}
-bool CMusicDatabase::GetArtistsByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items)
+bool CMusicDatabase::GetArtistsByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription /* = SortDescription() */)
{
if (NULL == m_pDB.get()) return false;
if (NULL == m_pDS.get()) return false;
try
{
- CStdString strSQL = PrepareSQL("select %s from artistview ", !filter.fields.empty() ? filter.fields.c_str() : "*");
+ int total = -1;
- CMusicDbUrl musicUrl;
+ CStdString strSQL = "SELECT %s FROM artistview ";
+
Filter extFilter = filter;
- if (!BuildSQL(strBaseDir, strSQL, extFilter, strSQL, musicUrl))
+ CMusicDbUrl musicUrl;
+ if (!musicUrl.FromString(strBaseDir) || !GetFilter(musicUrl, extFilter))
+ return false;
+
+ // if there are extra WHERE conditions we might need access
+ // to songview or albumview for these conditions
+ if (extFilter.where.size() > 0)
+ {
+ if (extFilter.where.find("songview") != string::npos)
+ extFilter.AppendJoin("JOIN song_artist ON song_artist.idArtist = artistview.idArtist JOIN songview ON songview.idSong = song_artist.idSong");
+ else if (extFilter.where.find("albumview") != string::npos)
+ extFilter.AppendJoin("JOIN album_artist ON album_artist.idArtist = artistview.idArtist JOIN albumview ON albumview.idAlbum = album_artist.idAlbum");
+
+ extFilter.AppendGroup("artistview.idArtist");
+ }
+
+ CStdString strSQLExtra;
+ if (!BuildSQL(strSQLExtra, extFilter, strSQLExtra))
return false;
+ // Apply the limiting directly here if there's no special sorting but limiting
+ if (extFilter.limit.empty() &&
+ sortDescription.sortBy == SortByNone &&
+ (sortDescription.limitStart > 0 || sortDescription.limitEnd > 0))
+ {
+ total = (int)strtol(GetSingleValue(PrepareSQL(strSQL, "COUNT(1)") + strSQLExtra, m_pDS).c_str(), NULL, 10);
+ strSQLExtra += DatabaseUtils::BuildLimitClause(sortDescription.limitEnd, sortDescription.limitStart);
+ }
+
+ strSQL = PrepareSQL(strSQL.c_str(), !extFilter.fields.empty() && extFilter.fields.compare("*") != 0 ? extFilter.fields.c_str() : "artistview.*") + strSQLExtra;
+
// run query
CLog::Log(LOGDEBUG, "%s query: %s", __FUNCTION__, strSQL.c_str());
if (!m_pDS->query(strSQL.c_str())) return false;
@@ -2806,26 +2840,45 @@ bool CMusicDatabase::GetArtistsByWhere(const CStdString& strBaseDir, const Filte
return false;
}
- items.Reserve(iRowsFound);
+ // store the total value of items as a property
+ if (total < iRowsFound)
+ total = iRowsFound;
+ items.SetProperty("total", total);
+
+ DatabaseResults results;
+ results.reserve(iRowsFound);
+ if (!SortUtils::SortFromDataset(sortDescription, MediaTypeArtist, m_pDS, results))
+ return false;
// get data from returned rows
- while (!m_pDS->eof())
+ items.Reserve(results.size());
+ const dbiplus::query_data &data = m_pDS->get_result_set().records;
+ for (DatabaseResults::const_iterator it = results.begin(); it != results.end(); it++)
{
- CArtist artist = GetArtistFromDataset(m_pDS.get(), false);
- CFileItemPtr pItem(new CFileItem(artist));
-
- CMusicDbUrl itemUrl = musicUrl;
- CStdString path; path.Format("%ld/", artist.idArtist);
- itemUrl.AppendPath(path);
- pItem->SetPath(itemUrl.ToString());
+ unsigned int targetRow = (unsigned int)it->at(FieldRow).asInteger();
+ const dbiplus::sql_record* const record = data.at(targetRow);
+
+ try
+ {
+ CArtist artist = GetArtistFromDataset(record, false);
+ CFileItemPtr pItem(new CFileItem(artist));
- pItem->GetMusicInfoTag()->SetDatabaseId(artist.idArtist, "artist");
- pItem->SetIconImage("DefaultArtist.png");
+ CMusicDbUrl itemUrl = musicUrl;
+ CStdString path; path.Format("%ld/", artist.idArtist);
+ itemUrl.AppendPath(path);
+ pItem->SetPath(itemUrl.ToString());
- SetPropertiesFromArtist(*pItem,artist);
- items.Add(pItem);
+ pItem->GetMusicInfoTag()->SetDatabaseId(artist.idArtist, "artist");
+ pItem->SetIconImage("DefaultArtist.png");
- m_pDS->next();
+ SetPropertiesFromArtist(*pItem, artist);
+ items.Add(pItem);
+ }
+ catch (...)
+ {
+ m_pDS->close();
+ CLog::Log(LOGERROR, "%s - out of memory getting listing (got %i)", __FUNCTION__, items.Size());
+ }
}
// cleanup
@@ -5222,8 +5275,12 @@ bool CMusicDatabase::GetFilter(const CDbUrl &musicUrl, Filter &filter)
if (!xsp.LoadFromJson(option->second.asString()))
return false;
- std::set<CStdString> playlists;
- filter.AppendWhere(xsp.GetWhereClause(*this, playlists));
+ // check if the filter playlist matches the item type
+ if (xsp.GetType() != "artists"|| xsp.GetType() == type)
+ {
+ std::set<CStdString> playlists;
+ filter.AppendWhere(xsp.GetWhereClause(*this, playlists));
+ }
}
return true;
View
7 xbmc/music/MusicDatabase.h
@@ -152,14 +152,14 @@ class CMusicDatabase : public CDatabase
bool GetPathHash(const CStdString &path, CStdString &hash);
bool GetGenresNav(const CStdString& strBaseDir, CFileItemList& items);
bool GetYearsNav(const CStdString& strBaseDir, CFileItemList& items);
- bool GetArtistsNav(const CStdString& strBaseDir, CFileItemList& items, bool albumArtistsOnly = false, int idGenre = -1, int idAlbum = -1, int idSong = -1);
+ bool GetArtistsNav(const CStdString& strBaseDir, CFileItemList& items, bool albumArtistsOnly = false, int idGenre = -1, int idAlbum = -1, int idSong = -1, const SortDescription &sortDescription = SortDescription());
bool GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre = -1, int idArtist = -1, const SortDescription &sortDescription = SortDescription());
bool GetAlbumsByYear(const CStdString &strBaseDir, CFileItemList& items, int year);
bool GetSongsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, int idArtist,int idAlbum, const SortDescription &sortDescription = SortDescription());
bool GetSongsByYear(const CStdString& baseDir, CFileItemList& items, int year);
bool GetSongsByWhere(const CStdString &baseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription = SortDescription());
bool GetAlbumsByWhere(const CStdString &baseDir, const Filter &filter, CFileItemList &items, const SortDescription &sortDescription = SortDescription());
- bool GetArtistsByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items);
+ bool GetArtistsByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription = SortDescription());
bool GetRandomSong(CFileItem* item, int& idSong, const Filter &filter);
int GetKaraokeSongsCount();
int GetSongsCount(const Filter &filter = Filter());
@@ -299,7 +299,8 @@ class CMusicDatabase : public CDatabase
void SplitString(const CStdString &multiString, std::vector<std::string> &vecStrings, CStdString &extraStrings);
CSong GetSongFromDataset(bool bWithMusicDbPath=false);
- CArtist GetArtistFromDataset(dbiplus::Dataset* pDS, bool needThumb=true);
+ CArtist GetArtistFromDataset(dbiplus::Dataset* pDS, bool needThumb = true);
+ CArtist GetArtistFromDataset(const dbiplus::sql_record* const record, bool needThumb = true);
CAlbum GetAlbumFromDataset(dbiplus::Dataset* pDS, bool imageURL=false);
CAlbum GetAlbumFromDataset(const dbiplus::sql_record* const record, bool imageURL=false);
void GetFileItemFromDataset(CFileItem* item, const CStdString& strMusicDBbasePath);
View
33 xbmc/playlists/SmartPlayList.cpp
@@ -102,7 +102,13 @@ static const translateField fields[] = {
{ "subtitlelanguage", FieldSubtitleLanguage, SortBySubtitleLanguage, CSmartPlaylistRule::TEXTIN_FIELD, 21448 },
{ "random", FieldRandom, SortByRandom, CSmartPlaylistRule::TEXT_FIELD, 590 },
{ "playlist", FieldPlaylist, SortByPlaylistOrder, CSmartPlaylistRule::PLAYLIST_FIELD, 559 },
- { "tag", FieldTag, SortByNone, CSmartPlaylistRule::BROWSEABLE_FIELD, 20459 }
+ { "tag", FieldTag, SortByNone, CSmartPlaylistRule::BROWSEABLE_FIELD, 20459 },
+ { "instruments", FieldInstruments, SortByNone, CSmartPlaylistRule::TEXT_FIELD, 21892 },
+ { "biography", FieldBiography, SortByNone, CSmartPlaylistRule::TEXT_FIELD, 21887 },
+ { "born", FieldBorn, SortByNone, CSmartPlaylistRule::TEXT_FIELD, 21893 },
+ { "bandformed", FieldBandFormed, SortByNone, CSmartPlaylistRule::TEXT_FIELD, 21894 },
+ { "disbanded", FieldDisbanded, SortByNone, CSmartPlaylistRule::TEXT_FIELD, 21896 },
+ { "died", FieldDied, SortByNone, CSmartPlaylistRule::TEXT_FIELD, 21897 }
};
#define NUM_FIELDS sizeof(fields) / sizeof(translateField)
@@ -214,8 +220,8 @@ bool CSmartPlaylistRule::Load(const CVariant &obj)
if (m_operator == OPERATOR_TRUE || m_operator == OPERATOR_FALSE)
return true;
- if (!obj.isMember("value") || (!obj["value"].isString() && !obj["value"].isArray()))
- return false;
+ if (!obj.isMember("value") || (!obj["value"].isString() && !obj["value"].isArray()))
+ return false;
const CVariant &value = obj["value"];
if (value.isString() && !value.asString().empty())
@@ -373,6 +379,19 @@ vector<Field> CSmartPlaylistRule::GetFields(const CStdString &type)
fields.push_back(FieldMusicLabel);
fields.push_back(FieldRating);
}
+ else if (type == "artists")
+ {
+ fields.push_back(FieldArtist);
+ fields.push_back(FieldGenre);
+ fields.push_back(FieldMoods);
+ fields.push_back(FieldStyles);
+ fields.push_back(FieldInstruments);
+ fields.push_back(FieldBiography);
+ fields.push_back(FieldBorn);
+ fields.push_back(FieldBandFormed);
+ fields.push_back(FieldDisbanded);
+ fields.push_back(FieldDied);
+ }
else if (type == "tvshows")
{
fields.push_back(FieldTitle);
@@ -512,6 +531,10 @@ std::vector<SortBy> CSmartPlaylistRule::GetOrders(const CStdString &type)
//orders.push_back(SortByMusicLabel);
orders.push_back(SortByRating);
}
+ else if (type == "artists")
+ {
+ orders.push_back(SortByArtist);
+ }
else if (type == "tvshows")
{
orders.push_back(SortBySortTitle);
@@ -693,7 +716,7 @@ CStdString CSmartPlaylistRule::GetWhereClause(const CDatabase &db, const CStdStr
if (strType == "movies")
{
if (m_field == FieldInProgress)
- return "movieview.idFile " + negate + " in (select idFile from bookmark where type = 1)";
+ return "movieview.idFile " + negate + " IN (select idFile from bookmark where type = 1)";
else if (m_field == FieldTrailer)
return negate + GetField(m_field, strType) + "!= ''";
}
@@ -1250,7 +1273,7 @@ const vector<CSmartPlaylistRule> &CSmartPlaylist::GetRules() const
CStdString CSmartPlaylist::GetSaveLocation() const
{
- if (m_playlistType == "songs" || m_playlistType == "albums")
+ if (m_playlistType == "songs" || m_playlistType == "albums" || m_playlistType == "artists")
return "music";
else if (m_playlistType == "mixed")
return "mixed";
View
37 xbmc/utils/DatabaseUtils.cpp
@@ -125,6 +125,20 @@ std::string DatabaseUtils::GetField(Field field, MediaType mediaType, DatabaseQu
else if (field == FieldGenre) return "songview.strGenre";
else if (field == FieldDateAdded && queryPart == DatabaseQueryPartOrderBy) return "songview.idSong"; // only used for order clauses
}
+ else if (mediaType == MediaTypeArtist)
+ {
+ if (field == FieldId) return "artistview.idArtist";
+ else if (field == FieldArtist) return "artistview.strArtist";
+ else if (field == FieldGenre) return "artistview.strGenres";
+ else if (field == FieldMoods) return "artistview.strMoods";
+ else if (field == FieldStyles) return "artistview.strStyles";
+ else if (field == FieldInstruments) return "artistview.strInstruments";
+ else if (field == FieldBiography) return "artistview.strBiography";
+ else if (field == FieldBorn) return "artistview.strBorn";
+ else if (field == FieldBandFormed) return "artistview.strFormed";
+ else if (field == FieldDisbanded) return "artistview.strDisbanded";
+ else if (field == FieldDied) return "artistview.strDied";
+ }
else if (mediaType == MediaTypeMusicVideo)
{
CStdString result;
@@ -299,6 +313,20 @@ int DatabaseUtils::GetFieldIndex(Field field, MediaType mediaType)
else if (field == FieldGenre) return CMusicDatabase::song_strGenres;
else if (field == FieldArtist || field == FieldAlbumArtist) return CMusicDatabase::song_strArtists;
}
+ else if (mediaType == MediaTypeArtist)
+ {
+ if (field == FieldId) return CMusicDatabase::artist_idArtist;
+ else if (field == FieldArtist) return CMusicDatabase::artist_strArtist;
+ else if (field == FieldGenre) return CMusicDatabase::artist_strGenres;
+ else if (field == FieldMoods) return CMusicDatabase::artist_strMoods;
+ else if (field == FieldStyles) return CMusicDatabase::artist_strStyles;
+ else if (field == FieldInstruments) return CMusicDatabase::artist_strInstruments;
+ else if (field == FieldBiography) return CMusicDatabase::artist_strBiography;
+ else if (field == FieldBorn) return CMusicDatabase::artist_strBorn;
+ else if (field == FieldBandFormed) return CMusicDatabase::artist_strFormed;
+ else if (field == FieldDisbanded) return CMusicDatabase::artist_strDisbanded;
+ else if (field == FieldDied) return CMusicDatabase::artist_strDied;
+ }
else if (mediaType == MediaTypeMusicVideo)
{
if (field == FieldId) return 0;
@@ -325,8 +353,7 @@ int DatabaseUtils::GetFieldIndex(Field field, MediaType mediaType)
// the first field is the item's ID and the second is the item's file ID
index += 2;
}
- else
- if (mediaType == MediaTypeMovie)
+ else if (mediaType == MediaTypeMovie)
{
if (field == FieldId) return 0;
else if (field == FieldTitle) index = VIDEODB_ID_TITLE;
@@ -440,6 +467,8 @@ bool DatabaseUtils::GetSelectFields(const Fields &fields, MediaType mediaType, F
sortFields.insert(FieldAlbum);
else if (mediaType == MediaTypeSong)
sortFields.insert(FieldTrackNumber);
+ else if (mediaType == MediaTypeArtist)
+ sortFields.insert(FieldArtist);
selectFields.clear();
for (Fields::const_iterator it = sortFields.begin(); it != sortFields.end(); it++)
@@ -603,6 +632,10 @@ bool DatabaseUtils::GetDatabaseResults(MediaType mediaType, const FieldList &fie
break;
}
+ case MediaTypeArtist:
+ result[FieldLabel] = result.at(FieldArtist).asString();
+ break;
+
default:
break;
}
View
8 xbmc/utils/DatabaseUtils.h
@@ -110,7 +110,13 @@ typedef enum {
FieldAudioLanguage,
FieldSubtitleLanguage,
FieldProductionCode,
- FieldTag
+ FieldTag,
+ FieldInstruments,
+ FieldBiography,
+ FieldBorn,
+ FieldBandFormed,
+ FieldDisbanded,
+ FieldDied
} Field;
typedef std::set<Field> Fields;
Something went wrong with that request. Please try again.