bool CMusicThumbLoader::FillLibraryArt(CFileItem &item) { CMusicInfoTag &tag = *item.GetMusicInfoTag(); if (tag.GetDatabaseId() > -1 && !tag.GetType().empty()) { m_musicDatabase->Open(); map<string, string> artwork; if (m_musicDatabase->GetArtForItem(tag.GetDatabaseId(), tag.GetType(), artwork)) item.SetArt(artwork); else if (tag.GetType() == "song") { // no art for the song, try the album ArtCache::const_iterator i = m_albumArt.find(tag.GetAlbumId()); if (i == m_albumArt.end()) { m_musicDatabase->GetArtForItem(tag.GetAlbumId(), "album", artwork); i = m_albumArt.insert(make_pair(tag.GetAlbumId(), artwork)).first; } if (i != m_albumArt.end()) { item.AppendArt(i->second, "album"); for (map<string, string>::const_iterator j = i->second.begin(); j != i->second.end(); ++j) item.SetArtFallback(j->first, "album." + j->first); } } if (tag.GetType() == "song" || tag.GetType() == "album") { // fanart from the artist string fanart = m_musicDatabase->GetArtistArtForItem(tag.GetDatabaseId(), tag.GetType(), "fanart"); if (!fanart.empty()) { item.SetArt("artist.fanart", fanart); item.SetArtFallback("fanart", "artist.fanart"); } } m_musicDatabase->Close(); } return !item.GetArt().empty(); }
CStdString CThumbnailCache::GetFanart(const CFileItem &item) { // get the locally cached thumb if (item.IsVideoDb() || (item.HasVideoInfoTag() && !item.GetVideoInfoTag()->IsEmpty())) { if (!item.HasVideoInfoTag()) return ""; if (!item.GetVideoInfoTag()->m_strArtist.IsEmpty()) return GetThumb(item.GetVideoInfoTag()->m_strArtist,g_settings.GetMusicFanartFolder()); if (!item.m_bIsFolder && !item.GetVideoInfoTag()->m_strShowTitle.IsEmpty()) { CStdString showPath; if (!item.GetVideoInfoTag()->m_strShowPath.IsEmpty()) showPath = item.GetVideoInfoTag()->m_strShowPath; else { CVideoDatabase database; database.Open(); int iShowId = item.GetVideoInfoTag()->m_iIdShow; if (iShowId <= 0) iShowId = database.GetTvShowId(item.GetVideoInfoTag()->m_strPath); CStdString showPath; database.GetFilePathById(iShowId,showPath,VIDEODB_CONTENT_TVSHOWS); } return GetThumb(showPath,g_settings.GetVideoFanartFolder()); } CStdString path = item.GetVideoInfoTag()->GetPath(); if (path.empty()) return ""; return GetThumb(path,g_settings.GetVideoFanartFolder()); } if (item.HasMusicInfoTag()) return GetThumb(item.GetMusicInfoTag()->GetArtist(),g_settings.GetMusicFanartFolder()); return GetThumb(item.GetPath(),g_settings.GetVideoFanartFolder()); }
int CMusicInfoScanner::RetrieveMusicInfo(CFileItemList& items, const CStdString& strDirectory) { CSongMap songsMap; // get all information for all files in current directory from database, and remove them if (m_musicDatabase.RemoveSongsFromPath(strDirectory, songsMap)) m_needsCleanup = true; VECSONGS songsToAdd; // for every file found, but skip folder for (int i = 0; i < items.Size(); ++i) { CFileItem* pItem = items[i]; CStdString strExtension; CUtil::GetExtension(pItem->m_strPath, strExtension); if (m_bStop) return 0; // dont try reading id3tags for folders, playlists or shoutcast streams if (!pItem->m_bIsFolder && !pItem->IsPlayList() && !pItem->IsShoutCast() && !pItem->IsPicture()) { m_currentItem++; // CLog::Log(LOGDEBUG, "%s - Reading tag for: %s", __FUNCTION__, pItem->m_strPath.c_str()); // grab info from the song CSong *dbSong = songsMap.Find(pItem->m_strPath); CMusicInfoTag& tag = *pItem->GetMusicInfoTag(); if (!tag.Loaded() ) { // read the tag from a file auto_ptr<IMusicInfoTagLoader> pLoader (CMusicInfoTagLoaderFactory::CreateLoader(pItem->m_strPath)); if (NULL != pLoader.get()) pLoader->Load(pItem->m_strPath, tag); } // if we have the itemcount, notify our // observer with the progress we made if (m_pObserver && m_itemCount>0) m_pObserver->OnSetProgress(m_currentItem, m_itemCount); if (tag.Loaded()) { CSong song(tag); song.iStartOffset = pItem->m_lStartOffset; song.iEndOffset = pItem->m_lEndOffset; if (dbSong) { // keep the db-only fields intact on rescan... song.iTimesPlayed = dbSong->iTimesPlayed; song.lastPlayed = dbSong->lastPlayed; if (song.rating == '0') song.rating = dbSong->rating; } pItem->SetMusicThumb(); song.strThumb = pItem->GetThumbnailImage(); songsToAdd.push_back(song); // CLog::Log(LOGDEBUG, "%s - Tag loaded for: %s", __FUNCTION__, spItem->m_strPath.c_str()); } else CLog::Log(LOGDEBUG, "%s - No tag found for: %s", __FUNCTION__, pItem->m_strPath.c_str()); } } CheckForVariousArtists(songsToAdd); if (!items.HasThumbnail()) UpdateFolderThumb(songsToAdd, items.m_strPath); // finally, add these to the database for (unsigned int i = 0; i < songsToAdd.size(); ++i) { if (m_bStop) return i; CSong &song = songsToAdd[i]; m_musicDatabase.AddSong(song, false); if (!m_bStop && g_guiSettings.GetBool("musiclibrary.autoartistinfo")) { long iArtist = m_musicDatabase.GetArtistByName(song.strArtist); CStdString strPath; strPath.Format("musicdb://2/%u/",iArtist); if (find(m_artistsScanned.begin(),m_artistsScanned.end(),iArtist) == m_artistsScanned.end()) if (DownloadArtistInfo(strPath,song.strArtist)) m_artistsScanned.push_back(iArtist); if (m_pObserver) m_pObserver->OnStateChanged(READING_MUSIC_INFO); } if (!m_bStop && g_guiSettings.GetBool("musiclibrary.autoalbuminfo")) { long iAlbum = m_musicDatabase.GetAlbumByName(song.strAlbum,song.strArtist); CStdString strPath; strPath.Format("musicdb://3/%u/",iAlbum); CMusicAlbumInfo albumInfo; bool bCanceled; if (find(m_albumsScanned.begin(),m_albumsScanned.end(),iAlbum) == m_albumsScanned.end()) if (DownloadAlbumInfo(strPath,song.strArtist,song.strAlbum,bCanceled,albumInfo)) m_albumsScanned.push_back(iAlbum); if (m_pObserver) m_pObserver->OnStateChanged(READING_MUSIC_INFO); } } return songsToAdd.size(); }
JSONRPC_STATUS CAudioLibrary::GetSongs(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { CMusicDatabase musicdatabase; if (!musicdatabase.Open()) return InternalError; CMusicDbUrl musicUrl; if (!musicUrl.FromString("musicdb://songs/")) return InternalError; if (parameterObject["singlesonly"].asBoolean()) musicUrl.AddOption("singles", true); else if (!parameterObject["includesingles"].asBoolean()) musicUrl.AddOption("singles", false); bool allroles = false; if (parameterObject["allroles"].isBoolean()) allroles = parameterObject["allroles"].asBoolean(); const CVariant &filter = parameterObject["filter"]; if (allroles) musicUrl.AddOption("roleid", -1000); //All roles, override implicit roleid=1 filter required for backward compatibility else if (filter.isMember("roleid")) musicUrl.AddOption("roleid", static_cast<int>(filter["roleid"].asInteger())); else if (filter.isMember("role")) musicUrl.AddOption("role", filter["role"].asString()); // Only one of genreid/genre, artistid/artist, albumid/album or rules type filter is allowed by filter syntax if (filter.isMember("artistid")) musicUrl.AddOption("artistid", static_cast<int>(filter["artistid"].asInteger())); else if (filter.isMember("artist")) musicUrl.AddOption("artist", filter["artist"].asString()); else if (filter.isMember("genreid")) musicUrl.AddOption("genreid", static_cast<int>(filter["genreid"].asInteger())); else if (filter.isMember("genre")) musicUrl.AddOption("genre", filter["genre"].asString()); else if (filter.isMember("albumid")) musicUrl.AddOption("albumid", static_cast<int>(filter["albumid"].asInteger())); else if (filter.isMember("album")) musicUrl.AddOption("album", filter["album"].asString()); else if (filter.isObject()) { std::string xsp; if (!GetXspFiltering("songs", filter, xsp)) return InvalidParams; musicUrl.AddOption("xsp", xsp); } SortDescription sorting; ParseLimits(parameterObject, sorting.limitStart, sorting.limitEnd); if (!ParseSorting(parameterObject, sorting.sortBy, sorting.sortOrder, sorting.sortAttributes)) return InvalidParams; int total; std::set<std::string> fields; if (parameterObject.isMember("properties") && parameterObject["properties"].isArray()) { for (CVariant::const_iterator_array field = parameterObject["properties"].begin_array(); field != parameterObject["properties"].end_array(); field++) fields.insert(field->asString()); } if (!musicdatabase.GetSongsByWhereJSON(fields, musicUrl.ToString(), result, total, sorting)) return InternalError; if (!result.isNull()) { bool bFetchArt = fields.find("art") != fields.end(); bool bFetchFanart = fields.find("fanart") != fields.end(); bool bFetchThumb = fields.find("thumbnail") != fields.end(); if (bFetchArt || bFetchFanart || bFetchThumb) { CThumbLoader* thumbLoader = new CMusicThumbLoader(); thumbLoader->OnLoaderStart(); std::set<std::string> artfields; if (bFetchArt) artfields.insert("art"); if (bFetchFanart) artfields.insert("fanart"); if (bFetchThumb) artfields.insert("thumbnail"); for (unsigned int index = 0; index < result["songs"].size(); index++) { CFileItem item; // Only needs song and album id (if we have it) set to get art // Getting art is quicker if "albumid" has been fetched item.GetMusicInfoTag()->SetDatabaseId(result["songs"][index]["songid"].asInteger(), MediaTypeSong); if (result["songs"][index].isMember("albumid")) item.GetMusicInfoTag()->SetAlbumId(result["songs"][index]["albumid"].asInteger()); else item.GetMusicInfoTag()->SetAlbumId(-1); // Could use FillDetails, but it does unnecessary serialization of empty MusiInfoTag // CFileItemPtr itemptr(new CFileItem(item)); // FillDetails(item.GetMusicInfoTag(), itemptr, artfields, result["songs"][index], thumbLoader); thumbLoader->FillLibraryArt(item); if (bFetchThumb) { if (item.HasArt("thumb")) result["songs"][index]["thumbnail"] = CTextureUtils::GetWrappedImageURL(item.GetArt("thumb")); else result["songs"][index]["thumbnail"] = ""; } if (bFetchFanart) { if (item.HasArt("fanart")) result["songs"][index]["fanart"] = CTextureUtils::GetWrappedImageURL(item.GetArt("fanart")); else result["songs"][index]["fanart"] = ""; } if (bFetchArt) { CGUIListItem::ArtMap artMap = item.GetArt(); CVariant artObj(CVariant::VariantTypeObject); for (CGUIListItem::ArtMap::const_iterator artIt = artMap.begin(); artIt != artMap.end(); ++artIt) { if (!artIt->second.empty()) artObj[artIt->first] = CTextureUtils::GetWrappedImageURL(artIt->second); } result["songs"][index]["art"] = artObj; } } delete thumbLoader; } } int start, end; HandleLimits(parameterObject, result, total, start, end); return OK; }
CSong::CSong(CFileItem& item) { CMusicInfoTag& tag = *item.GetMusicInfoTag(); SYSTEMTIME stTime; tag.GetReleaseDate(stTime); strTitle = tag.GetTitle(); genre = tag.GetGenre(); std::vector<std::string> artist = tag.GetArtist(); std::vector<std::string> musicBrainArtistHints = tag.GetMusicBrainzArtistHints(); strArtistDesc = tag.GetArtistString(); if (!tag.GetMusicBrainzArtistID().empty()) { // have musicbrainz artist info, so use it for (size_t i = 0; i < tag.GetMusicBrainzArtistID().size(); i++) { std::string artistId = tag.GetMusicBrainzArtistID()[i]; std::string artistName; /* We try and get the corresponding artist name from the hints list. If the hints list is missing or the wrong length, it will try the artist list. We match on the same index, and if that fails just use the first name we have. */ if (i < musicBrainArtistHints.size()) artistName = musicBrainArtistHints[i]; else if (!artist.empty()) artistName = (i < artist.size()) ? artist[i] : artist[0]; if (artistName.empty()) artistName = artistId; std::string strJoinPhrase = (i == tag.GetMusicBrainzArtistID().size()-1) ? "" : g_advancedSettings.m_musicItemSeparator; CArtistCredit artistCredit(artistName, artistId, strJoinPhrase); artistCredits.push_back(artistCredit); } } else { // no musicbrainz info, so fill in directly for (std::vector<std::string>::const_iterator it = tag.GetArtist().begin(); it != tag.GetArtist().end(); ++it) { std::string strJoinPhrase = (it == --tag.GetArtist().end() ? "" : g_advancedSettings.m_musicItemSeparator); CArtistCredit artistCredit(*it, "", strJoinPhrase); artistCredits.push_back(artistCredit); } } strAlbum = tag.GetAlbum(); m_albumArtist = tag.GetAlbumArtist(); strMusicBrainzTrackID = tag.GetMusicBrainzTrackID(); strComment = tag.GetComment(); strCueSheet = tag.GetCueSheet(); strMood = tag.GetMood(); rating = tag.GetRating(); userrating = tag.GetUserrating(); votes = tag.GetVotes(); iYear = stTime.wYear; iTrack = tag.GetTrackAndDiscNumber(); iDuration = tag.GetDuration(); bCompilation = tag.GetCompilation(); embeddedArt = tag.GetCoverArtInfo(); strFileName = tag.GetURL().empty() ? item.GetPath() : tag.GetURL(); dateAdded = tag.GetDateAdded(); strThumb = item.GetUserMusicThumb(true); iStartOffset = item.m_lStartOffset; iEndOffset = item.m_lEndOffset; idSong = -1; iTimesPlayed = 0; idAlbum = -1; }
CAlbum::CAlbum(const CFileItem& item) { Reset(); const CMusicInfoTag& tag = *item.GetMusicInfoTag(); SYSTEMTIME stTime; tag.GetReleaseDate(stTime); strAlbum = tag.GetAlbum(); strMusicBrainzAlbumID = tag.GetMusicBrainzAlbumID(); genre = tag.GetGenre(); std::vector<std::string> musicBrainAlbumArtistHints = tag.GetMusicBrainzAlbumArtistHints(); strArtistDesc = tag.GetAlbumArtistString(); if (!tag.GetMusicBrainzAlbumArtistID().empty()) { // have musicbrainz artist info, so use it for (size_t i = 0; i < tag.GetMusicBrainzAlbumArtistID().size(); i++) { std::string artistId = tag.GetMusicBrainzAlbumArtistID()[i]; std::string artistName; /* We try and get the mbrainzid <-> name matching from the hints and match on the same index. If not found, we try and use the mbrainz <-> name matching from the artists fields If still not found, try and use the same index of the albumartist field. If still not found, use the mbrainzid and hope we later on can update that entry */ if (i < musicBrainAlbumArtistHints.size()) artistName = musicBrainAlbumArtistHints[i]; else if (!tag.GetMusicBrainzArtistID().empty() && !tag.GetArtist().empty()) { for (size_t j = 0; j < tag.GetMusicBrainzArtistID().size(); j++) { if (artistId == tag.GetMusicBrainzArtistID()[j]) { if (j < tag.GetMusicBrainzArtistHints().size()) artistName = tag.GetMusicBrainzArtistHints()[j]; else artistName = (j < tag.GetArtist().size()) ? tag.GetArtist()[j] : tag.GetArtist()[0]; } } } if (artistName.empty() && tag.GetMusicBrainzAlbumArtistID().size() == tag.GetAlbumArtist().size()) artistName = tag.GetAlbumArtist()[i]; if (artistName.empty()) artistName = artistId; std::string strJoinPhrase = (i == tag.GetMusicBrainzAlbumArtistID().size()-1) ? "" : g_advancedSettings.m_musicItemSeparator; CArtistCredit artistCredit(artistName, tag.GetMusicBrainzAlbumArtistID()[i], strJoinPhrase); artistCredits.push_back(artistCredit); } } else { // no musicbrainz info, so fill in directly for (std::vector<std::string>::const_iterator it = tag.GetAlbumArtist().begin(); it != tag.GetAlbumArtist().end(); ++it) { std::string strJoinPhrase = (it == --tag.GetAlbumArtist().end() ? "" : g_advancedSettings.m_musicItemSeparator); CArtistCredit artistCredit(*it, "", strJoinPhrase); artistCredits.push_back(artistCredit); } } iYear = stTime.wYear; bCompilation = tag.GetCompilation(); iTimesPlayed = 0; dateAdded.Reset(); lastPlayed.Reset(); releaseType = tag.GetAlbumReleaseType(); }
CSong::CSong(CFileItem& item) { CMusicInfoTag& tag = *item.GetMusicInfoTag(); SYSTEMTIME stTime; tag.GetReleaseDate(stTime); strTitle = tag.GetTitle(); genre = tag.GetGenre(); std::vector<std::string> artist = tag.GetArtist(); std::vector<std::string> musicBrainzArtistHints = tag.GetMusicBrainzArtistHints(); strArtistDesc = tag.GetArtistString(); if (!tag.GetMusicBrainzArtistID().empty()) { // Have musicbrainz artist info, so use it // Vector of possible separators in the order least likely to be part of artist name const std::vector<std::string> separators{ " feat. ", " ft. ", " Feat. "," Ft. ", ";", ":", "|", "#", "/", " with ", ",", "&" }; // Establish tag consistency - do the number of musicbrainz ids and number of names in hints or artist match if (tag.GetMusicBrainzArtistID().size() != musicBrainzArtistHints.size() && tag.GetMusicBrainzArtistID().size() != artist.size()) { // Tags mis-match - report it and then try to fix CLog::Log(LOGDEBUG, "Mis-match in song file tags: %i mbid %i names %s %s", (int)tag.GetMusicBrainzArtistID().size(), (int)artist.size(), strTitle.c_str(), strArtistDesc.c_str()); /* Most likey we have no hints and a single artist name like "Artist1 feat. Artist2" or "Composer; Conductor, Orchestra, Soloist" or "Artist1/Artist2" where the expected single item separator (default = space-slash-space) as not been used. Ampersand (&), comma and slash (no spaces) are poor delimiters as could be in name e.g. "AC/DC", "Earth, Wind & Fire", but here treat them as such in attempt to find artist names. When there are hints but count not match mbid they could be poorly formatted using unexpected separators so attempt to split them. Or we could have more hints or artist names than musicbrainz id so ingore them but raise warning. */ // Do hints exist yet mis-match if (musicBrainzArtistHints.size() > 0 && musicBrainzArtistHints.size() != tag.GetMusicBrainzArtistID().size()) { if (artist.size() == tag.GetMusicBrainzArtistID().size()) // Artist name count matches, use that as hints musicBrainzArtistHints = artist; else if (musicBrainzArtistHints.size() < tag.GetMusicBrainzArtistID().size()) { // Try splitting the hints until have matching number musicBrainzArtistHints = StringUtils::SplitMulti(musicBrainzArtistHints, separators, tag.GetMusicBrainzArtistID().size()); } else // Extra hints, discard them. musicBrainzArtistHints.resize(tag.GetMusicBrainzArtistID().size()); } // Do hints not exist or still mis-match, try artists if (musicBrainzArtistHints.size() != tag.GetMusicBrainzArtistID().size()) musicBrainzArtistHints = artist; // Still mis-match, try splitting the hints (now artists) until have matching number if (musicBrainzArtistHints.size() < tag.GetMusicBrainzArtistID().size()) { musicBrainzArtistHints = StringUtils::SplitMulti(musicBrainzArtistHints, separators, tag.GetMusicBrainzArtistID().size()); } } else { // Either hints or artist names (or both) matches number of musicbrainz id // If hints mis-match, use artists if (musicBrainzArtistHints.size() != tag.GetMusicBrainzArtistID().size()) musicBrainzArtistHints = tag.GetArtist(); } for (size_t i = 0; i < tag.GetMusicBrainzArtistID().size(); i++) { std::string artistId = tag.GetMusicBrainzArtistID()[i]; std::string artistName; /* We try and get the corresponding artist name from the hints list. Having already attempted to make the number of hints match, if they still don't then use musicbrainz id as the name and hope later on we can update that entry. */ if (i < musicBrainzArtistHints.size()) artistName = musicBrainzArtistHints[i]; else artistName = artistId; artistCredits.emplace_back(StringUtils::Trim(artistName), artistId); } } else { // No musicbrainz artist ids, so fill in directly // Separate artist names further, if possible, and trim blank space. if (musicBrainzArtistHints.size() > tag.GetArtist().size()) // Make use of hints (ARTISTS tag), when present, to separate artist names artist = musicBrainzArtistHints; else // Split artist names further using multiple possible delimiters, over single separator applied in Tag loader artist = StringUtils::SplitMulti(artist, g_advancedSettings.m_musicArtistSeparators); for (auto artistname: artist) { artistCredits.emplace_back(StringUtils::Trim(artistname)); } } strAlbum = tag.GetAlbum(); m_albumArtist = tag.GetAlbumArtist(); // Separate album artist names further, if possible, and trim blank space. if (tag.GetMusicBrainzAlbumArtistHints().size() > m_albumArtist.size()) // Make use of hints (ALBUMARTISTS tag), when present, to separate artist names m_albumArtist = tag.GetMusicBrainzAlbumArtistHints(); else // Split album artist names further using multiple possible delimiters, over single separator applied in Tag loader m_albumArtist = StringUtils::SplitMulti(m_albumArtist, g_advancedSettings.m_musicArtistSeparators); for (auto artistname : m_albumArtist) StringUtils::Trim(artistname); strMusicBrainzTrackID = tag.GetMusicBrainzTrackID(); m_musicRoles = tag.GetContributors(); strComment = tag.GetComment(); strCueSheet = tag.GetCueSheet(); strMood = tag.GetMood(); rating = tag.GetRating(); userrating = tag.GetUserrating(); votes = tag.GetVotes(); iYear = stTime.wYear; iTrack = tag.GetTrackAndDiscNumber(); iDuration = tag.GetDuration(); strRecordLabel = tag.GetRecordLabel(); strAlbumType = tag.GetMusicBrainzReleaseType(); bCompilation = tag.GetCompilation(); embeddedArt = tag.GetCoverArtInfo(); strFileName = tag.GetURL().empty() ? item.GetPath() : tag.GetURL(); dateAdded = tag.GetDateAdded(); strThumb = item.GetUserMusicThumb(true); iStartOffset = item.m_lStartOffset; iEndOffset = item.m_lEndOffset; idSong = -1; iTimesPlayed = 0; idAlbum = -1; }
void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg) { switch (pMsg->dwMessage) { case TMSG_SHUTDOWN: { switch (CSettings::Get().GetInt("powermanagement.shutdownstate")) { case POWERSTATE_SHUTDOWN: Powerdown(); break; case POWERSTATE_SUSPEND: Suspend(); break; case POWERSTATE_HIBERNATE: Hibernate(); break; case POWERSTATE_QUIT: Quit(); break; case POWERSTATE_MINIMIZE: Minimize(); break; case TMSG_RENDERER_FLUSH: g_renderManager.Flush(); break; } } break; case TMSG_POWERDOWN: { g_application.Stop(EXITCODE_POWERDOWN); g_powerManager.Powerdown(); } break; case TMSG_QUIT: { g_application.Stop(EXITCODE_QUIT); } break; case TMSG_HIBERNATE: { g_powerManager.Hibernate(); } break; case TMSG_SUSPEND: { g_powerManager.Suspend(); } break; case TMSG_RESTART: case TMSG_RESET: { g_application.Stop(EXITCODE_REBOOT); g_powerManager.Reboot(); } break; case TMSG_RESTARTAPP: { #if defined(TARGET_WINDOWS) || defined(TARGET_LINUX) g_application.Stop(EXITCODE_RESTARTAPP); #endif } break; case TMSG_INHIBITIDLESHUTDOWN: { g_application.InhibitIdleShutdown(pMsg->param1 != 0); } break; case TMSG_ACTIVATESCREENSAVER: { g_application.ActivateScreenSaver(); } break; case TMSG_MEDIA_PLAY: { // first check if we were called from the PlayFile() function if (pMsg->lpVoid && pMsg->param2 == 0) { CFileItem *item = (CFileItem *)pMsg->lpVoid; g_application.PlayFile(*item, pMsg->param1 != 0); delete item; return; } // restore to previous window if needed if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO || g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) g_windowManager.PreviousWindow(); g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); //g_application.StopPlaying(); // play file if(pMsg->lpVoid) { CFileItemList *list = (CFileItemList *)pMsg->lpVoid; if (list->Size() > 0) { int playlist = PLAYLIST_MUSIC; for (int i = 0; i < list->Size(); i++) { if ((*list)[i]->IsVideo()) { playlist = PLAYLIST_VIDEO; break; } } g_playlistPlayer.ClearPlaylist(playlist); g_playlistPlayer.SetCurrentPlaylist(playlist); //For single item lists try PlayMedia. This covers some more cases where a playlist is not appropriate //It will fall through to PlayFile if (list->Size() == 1 && !(*list)[0]->IsPlayList()) g_application.PlayMedia(*((*list)[0]), playlist); else { // Handle "shuffled" option if present if (list->HasProperty("shuffled") && list->GetProperty("shuffled").isBoolean()) g_playlistPlayer.SetShuffle(playlist, list->GetProperty("shuffled").asBoolean(), false); // Handle "repeat" option if present if (list->HasProperty("repeat") && list->GetProperty("repeat").isInteger()) g_playlistPlayer.SetRepeat(playlist, (PLAYLIST::REPEAT_STATE)list->GetProperty("repeat").asInteger(), false); g_playlistPlayer.Add(playlist, (*list)); g_playlistPlayer.Play(pMsg->param1); } } delete list; } else if (pMsg->param1 == PLAYLIST_MUSIC || pMsg->param1 == PLAYLIST_VIDEO) { if (g_playlistPlayer.GetCurrentPlaylist() != pMsg->param1) g_playlistPlayer.SetCurrentPlaylist(pMsg->param1); PlayListPlayerPlay(pMsg->param2); } } break; case TMSG_MEDIA_RESTART: g_application.Restart(true); break; case TMSG_PICTURE_SHOW: { CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW); if (!pSlideShow) return ; // stop playing file if (g_application.m_pPlayer->IsPlayingVideo()) g_application.StopPlaying(); if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO) g_windowManager.PreviousWindow(); g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); g_graphicsContext.Lock(); if (g_windowManager.GetActiveWindow() != WINDOW_SLIDESHOW) g_windowManager.ActivateWindow(WINDOW_SLIDESHOW); if (URIUtils::IsZIP(pMsg->strParam) || URIUtils::IsRAR(pMsg->strParam)) // actually a cbz/cbr { CFileItemList items; CURL pathToUrl; if (URIUtils::IsZIP(pMsg->strParam)) pathToUrl = URIUtils::CreateArchivePath("zip", CURL(pMsg->strParam), ""); else pathToUrl = URIUtils::CreateArchivePath("rar", CURL(pMsg->strParam), ""); CUtil::GetRecursiveListing(pathToUrl.Get(), items, g_advancedSettings.m_pictureExtensions, XFILE::DIR_FLAG_NO_FILE_DIRS); if (items.Size() > 0) { pSlideShow->Reset(); for (int i=0;i<items.Size();++i) { pSlideShow->Add(items[i].get()); } pSlideShow->Select(items[0]->GetPath()); } } else { CFileItem item(pMsg->strParam, false); pSlideShow->Reset(); pSlideShow->Add(&item); pSlideShow->Select(pMsg->strParam); } g_graphicsContext.Unlock(); } break; case TMSG_PICTURE_SLIDESHOW: { CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW); if (!pSlideShow) return ; if (g_application.m_pPlayer->IsPlayingVideo()) g_application.StopPlaying(); g_graphicsContext.Lock(); pSlideShow->Reset(); CFileItemList items; std::string strPath = pMsg->strParam; std::string extensions = g_advancedSettings.m_pictureExtensions; if (pMsg->param1) extensions += "|.tbn"; CUtil::GetRecursiveListing(strPath, items, extensions); if (items.Size() > 0) { for (int i=0;i<items.Size();++i) pSlideShow->Add(items[i].get()); pSlideShow->StartSlideShow(); //Start the slideshow! } if (g_windowManager.GetActiveWindow() != WINDOW_SLIDESHOW) { if(items.Size() == 0) { CSettings::Get().SetString("screensaver.mode", "screensaver.xbmc.builtin.dim"); g_application.ActivateScreenSaver(); } else g_windowManager.ActivateWindow(WINDOW_SLIDESHOW); } g_graphicsContext.Unlock(); } break; case TMSG_SETLANGUAGE: g_application.SetLanguage(pMsg->strParam); break; case TMSG_MEDIA_STOP: { // restore to previous window if needed bool stopSlideshow = true; bool stopVideo = true; bool stopMusic = true; if (pMsg->param1 >= PLAYLIST_MUSIC && pMsg->param1 <= PLAYLIST_PICTURE) { stopSlideshow = (pMsg->param1 == PLAYLIST_PICTURE); stopVideo = (pMsg->param1 == PLAYLIST_VIDEO); stopMusic = (pMsg->param1 == PLAYLIST_MUSIC); } if ((stopSlideshow && g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW) || (stopVideo && g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO) || (stopMusic && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)) g_windowManager.PreviousWindow(); g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); // stop playing file if (g_application.m_pPlayer->IsPlaying()) g_application.StopPlaying(); } break; case TMSG_MEDIA_PAUSE: if (g_application.m_pPlayer->HasPlayer()) { g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); g_application.m_pPlayer->Pause(); } break; case TMSG_MEDIA_UNPAUSE: if (g_application.m_pPlayer->IsPausedPlayback()) { g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); g_application.m_pPlayer->Pause(); } break; case TMSG_MEDIA_PAUSE_IF_PLAYING: if (g_application.m_pPlayer->IsPlaying() && !g_application.m_pPlayer->IsPaused()) { g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); g_application.m_pPlayer->Pause(); } break; case TMSG_SWITCHTOFULLSCREEN: if(g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO) g_application.SwitchToFullScreen(true); break; case TMSG_SETVIDEORESOLUTION: { RESOLUTION res = (RESOLUTION)pMsg->param1; bool forceUpdate = pMsg->param2 == 1 ? true : false; g_graphicsContext.SetVideoResolution(res, forceUpdate); } break; case TMSG_VIDEORESIZE: { XBMC_Event newEvent; memset(&newEvent, 0, sizeof(newEvent)); newEvent.type = XBMC_VIDEORESIZE; newEvent.resize.w = pMsg->param1; newEvent.resize.h = pMsg->param2; g_application.OnEvent(newEvent); g_windowManager.MarkDirty(); } break; case TMSG_TOGGLEFULLSCREEN: g_graphicsContext.Lock(); g_graphicsContext.ToggleFullScreenRoot(); g_graphicsContext.Unlock(); break; case TMSG_MINIMIZE: g_application.Minimize(); break; case TMSG_EXECUTE_OS: /* Suspend AE temporarily so exclusive or hog-mode sinks */ /* don't block external player's access to audio device */ if (!CAEFactory::Suspend()) { CLog::Log(LOGNOTICE, "%s: Failed to suspend AudioEngine before launching external program",__FUNCTION__); } #if defined( TARGET_POSIX) && !defined(TARGET_DARWIN) CUtil::RunCommandLine(pMsg->strParam.c_str(), (pMsg->param1 == 1)); #elif defined(TARGET_WINDOWS) CWIN32Util::XBMCShellExecute(pMsg->strParam.c_str(), (pMsg->param1 == 1)); #endif /* Resume AE processing of XBMC native audio */ if (!CAEFactory::Resume()) { CLog::Log(LOGFATAL, "%s: Failed to restart AudioEngine after return from external player",__FUNCTION__); } break; case TMSG_EXECUTE_SCRIPT: CScriptInvocationManager::Get().ExecuteAsync(pMsg->strParam); break; case TMSG_EXECUTE_BUILT_IN: CBuiltins::Execute(pMsg->strParam.c_str()); break; case TMSG_PLAYLISTPLAYER_PLAY: if (pMsg->param1 != -1) g_playlistPlayer.Play(pMsg->param1); else g_playlistPlayer.Play(); break; case TMSG_PLAYLISTPLAYER_PLAY_SONG_ID: if (pMsg->param1 != -1) { bool *result = (bool*)pMsg->lpVoid; *result = g_playlistPlayer.PlaySongId(pMsg->param1); } else g_playlistPlayer.Play(); break; case TMSG_PLAYLISTPLAYER_NEXT: g_playlistPlayer.PlayNext(); break; case TMSG_PLAYLISTPLAYER_PREV: g_playlistPlayer.PlayPrevious(); break; case TMSG_PLAYLISTPLAYER_ADD: if(pMsg->lpVoid) { CFileItemList *list = (CFileItemList *)pMsg->lpVoid; g_playlistPlayer.Add(pMsg->param1, (*list)); delete list; } break; case TMSG_PLAYLISTPLAYER_INSERT: if (pMsg->lpVoid) { CFileItemList *list = (CFileItemList *)pMsg->lpVoid; g_playlistPlayer.Insert(pMsg->param1, (*list), pMsg->param2); delete list; } break; case TMSG_PLAYLISTPLAYER_REMOVE: if (pMsg->param1 != -1) g_playlistPlayer.Remove(pMsg->param1,pMsg->param2); break; case TMSG_PLAYLISTPLAYER_CLEAR: g_playlistPlayer.ClearPlaylist(pMsg->param1); break; case TMSG_PLAYLISTPLAYER_SHUFFLE: g_playlistPlayer.SetShuffle(pMsg->param1, pMsg->param2 > 0); break; case TMSG_PLAYLISTPLAYER_REPEAT: g_playlistPlayer.SetRepeat(pMsg->param1, (PLAYLIST::REPEAT_STATE)pMsg->param2); break; case TMSG_PLAYLISTPLAYER_GET_ITEMS: if (pMsg->lpVoid) { PLAYLIST::CPlayList playlist = g_playlistPlayer.GetPlaylist(pMsg->param1); CFileItemList *list = (CFileItemList *)pMsg->lpVoid; for (int i = 0; i < playlist.size(); i++) list->Add(CFileItemPtr(new CFileItem(*playlist[i]))); } break; case TMSG_PLAYLISTPLAYER_SWAP: if (pMsg->lpVoid) { vector<int> *indexes = (vector<int> *)pMsg->lpVoid; if (indexes->size() == 2) g_playlistPlayer.Swap(pMsg->param1, indexes->at(0), indexes->at(1)); delete indexes; } break; // Window messages below here... case TMSG_DIALOG_DOMODAL: //doModel of window { CGUIDialog* pDialog = (CGUIDialog*)g_windowManager.GetWindow(pMsg->param1); if (!pDialog) return ; pDialog->DoModal(); } break; case TMSG_NETWORKMESSAGE: { g_application.getNetwork().NetworkMessage((CNetwork::EMESSAGE)pMsg->param1, pMsg->param2); } break; case TMSG_GUI_DO_MODAL: { CGUIDialog *pDialog = (CGUIDialog *)pMsg->lpVoid; if (pDialog) pDialog->DoModal(pMsg->param1, pMsg->strParam); } break; case TMSG_GUI_SHOW: { CGUIDialog *pDialog = (CGUIDialog *)pMsg->lpVoid; if (pDialog) pDialog->Show(); } break; case TMSG_GUI_WINDOW_CLOSE: { CGUIWindow *window = (CGUIWindow *)pMsg->lpVoid; if (window) window->Close(pMsg->param2 & 0x1 ? true : false, pMsg->param1, pMsg->param2 & 0x2 ? true : false); } break; case TMSG_GUI_ACTIVATE_WINDOW: { g_windowManager.ActivateWindow(pMsg->param1, pMsg->params, pMsg->param2 & 0x1 ? true : false, pMsg->param2 & 0x2 ? true : false); } break; case TMSG_GUI_ADDON_DIALOG: { if (pMsg->lpVoid) { // TODO: This is ugly - really these python dialogs should just be normal XBMC dialogs ((ADDON::CGUIAddonWindowDialog *) pMsg->lpVoid)->Show_Internal(pMsg->param2 > 0); } } break; #ifdef HAS_PYTHON case TMSG_GUI_PYTHON_DIALOG: { // This hack is not much better but at least I don't need to make ApplicationMessenger // know about Addon (Python) specific classes. CAction caction(pMsg->param1); ((CGUIWindow*)pMsg->lpVoid)->OnAction(caction); } break; #endif case TMSG_GUI_ACTION: { if (pMsg->lpVoid) { CAction *action = (CAction *)pMsg->lpVoid; if (pMsg->param1 == WINDOW_INVALID) g_application.OnAction(*action); else { CGUIWindow *pWindow = g_windowManager.GetWindow(pMsg->param1); if (pWindow) pWindow->OnAction(*action); else CLog::Log(LOGWARNING, "Failed to get window with ID %i to send an action to", pMsg->param1); } delete action; } } break; case TMSG_GUI_MESSAGE: { if (pMsg->lpVoid) { CGUIMessage *message = (CGUIMessage *)pMsg->lpVoid; g_windowManager.SendMessage(*message, pMsg->param1); delete message; } } break; case TMSG_GUI_INFOLABEL: { if (pMsg->lpVoid) { vector<string> *infoLabels = (vector<string> *)pMsg->lpVoid; for (unsigned int i = 0; i < pMsg->params.size(); i++) infoLabels->push_back(g_infoManager.GetLabel(g_infoManager.TranslateString(pMsg->params[i]))); } } break; case TMSG_GUI_INFOBOOL: { if (pMsg->lpVoid) { vector<bool> *infoLabels = (vector<bool> *)pMsg->lpVoid; for (unsigned int i = 0; i < pMsg->params.size(); i++) infoLabels->push_back(g_infoManager.EvaluateBool(pMsg->params[i])); } } break; case TMSG_CALLBACK: { ThreadMessageCallback *callback = (ThreadMessageCallback*)pMsg->lpVoid; callback->callback(callback->userptr); } break; case TMSG_VOLUME_SHOW: { CAction action(pMsg->param1); g_application.ShowVolumeBar(&action); } break; case TMSG_DISPLAY_SETUP: { *((bool*)pMsg->lpVoid) = g_application.InitWindow(); g_application.SetRenderGUI(true); } break; case TMSG_DISPLAY_DESTROY: { *((bool*)pMsg->lpVoid) = g_application.DestroyWindow(); g_application.SetRenderGUI(false); } break; case TMSG_UPDATE_CURRENT_ITEM: { CFileItem* item = (CFileItem*)pMsg->lpVoid; if (!item) return; if (pMsg->param1 == 1 && item->HasMusicInfoTag()) // only grab music tag g_infoManager.SetCurrentSongTag(*item->GetMusicInfoTag()); else if (pMsg->param1 == 2 && item->HasVideoInfoTag()) // only grab video tag g_infoManager.SetCurrentVideoTag(*item->GetVideoInfoTag()); else g_infoManager.SetCurrentItem(*item); delete item; break; } case TMSG_LOADPROFILE: { CGUIWindowLoginScreen::LoadProfile(pMsg->param1); break; } case TMSG_CECTOGGLESTATE: { *((bool*)pMsg->lpVoid) = g_peripherals.ToggleDeviceState(STATE_SWITCH_TOGGLE); break; } case TMSG_CECACTIVATESOURCE: { g_peripherals.ToggleDeviceState(STATE_ACTIVATE_SOURCE); break; } case TMSG_CECSTANDBY: { g_peripherals.ToggleDeviceState(STATE_STANDBY); break; } case TMSG_START_ANDROID_ACTIVITY: { #if defined(TARGET_ANDROID) if (pMsg->params.size()) { CXBMCApp::StartActivity(pMsg->params[0], pMsg->params.size() > 1 ? pMsg->params[1] : "", pMsg->params.size() > 2 ? pMsg->params[2] : "", pMsg->params.size() > 3 ? pMsg->params[3] : ""); } #endif break; } case TMSG_SETPVRMANAGERSTATE: { if (pMsg->param1 != 0) g_application.StartPVRManager(); else g_application.StopPVRManager(); } } }
void CSaveFileState::DoWork(CFileItem& item, CBookmark& bookmark, bool updatePlayCount) { std::string progressTrackingFile = item.GetPath(); if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://")) progressTrackingFile = item.GetVideoInfoTag()->m_strFileNameAndPath; // this variable contains removable:// suffixed by disc label+uniqueid or is empty if label not uniquely identified else if (item.HasProperty("original_listitem_url")) { // only use original_listitem_url for Python, UPnP and Bluray sources std::string original = item.GetProperty("original_listitem_url").asString(); if (URIUtils::IsPlugin(original) || URIUtils::IsUPnP(original) || URIUtils::IsBluray(item.GetPath())) progressTrackingFile = original; } if (!progressTrackingFile.empty()) { #ifdef HAS_UPNP // checks if UPnP server of this file is available and supports updating if (URIUtils::IsUPnP(progressTrackingFile) && UPNP::CUPnP::SaveFileState(item, bookmark, updatePlayCount)) { return; } #endif if (item.IsVideo()) { std::string redactPath = CURL::GetRedacted(progressTrackingFile); CLog::Log(LOGDEBUG, "%s - Saving file state for video item %s", __FUNCTION__, redactPath.c_str()); CVideoDatabase videodatabase; if (!videodatabase.Open()) { CLog::Log(LOGWARNING, "%s - Unable to open video database. Can not save file state!", __FUNCTION__); } else { if (URIUtils::IsPlugin(progressTrackingFile) && !(item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_iDbId >= 0)) { // FileItem from plugin can lack information, make sure all needed fields are set CVideoInfoTag *tag = item.GetVideoInfoTag(); CStreamDetails streams = tag->m_streamDetails; if (videodatabase.LoadVideoInfo(progressTrackingFile, *tag)) { item.SetPath(progressTrackingFile); item.ClearProperty("original_listitem_url"); tag->m_streamDetails = streams; } } bool updateListing = false; // No resume & watched status for livetv if (!item.IsLiveTV()) { if (updatePlayCount) { // no watched for not yet finished pvr recordings if (!item.IsInProgressPVRRecording()) { CLog::Log(LOGDEBUG, "%s - Marking video item %s as watched", __FUNCTION__, redactPath.c_str()); // consider this item as played videodatabase.IncrementPlayCount(item); item.GetVideoInfoTag()->IncrementPlayCount(); item.SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, true); updateListing = true; if (item.HasVideoInfoTag()) { CVariant data; data["id"] = item.GetVideoInfoTag()->m_iDbId; data["type"] = item.GetVideoInfoTag()->m_type; ANNOUNCEMENT::CAnnouncementManager::GetInstance().Announce(ANNOUNCEMENT::VideoLibrary, "xbmc", "OnUpdate", data); } } } else videodatabase.UpdateLastPlayed(item); if (!item.HasVideoInfoTag() || item.GetVideoInfoTag()->GetResumePoint().timeInSeconds != bookmark.timeInSeconds) { if (bookmark.timeInSeconds <= 0.0f) videodatabase.ClearBookMarksOfFile(progressTrackingFile, CBookmark::RESUME); else videodatabase.AddBookMarkToFile(progressTrackingFile, bookmark, CBookmark::RESUME); if (item.HasVideoInfoTag()) item.GetVideoInfoTag()->SetResumePoint(bookmark); // UPnP announce resume point changes to clients // however not if playcount is modified as that already announces if (item.HasVideoInfoTag() && !updatePlayCount) { CVariant data; data["id"] = item.GetVideoInfoTag()->m_iDbId; data["type"] = item.GetVideoInfoTag()->m_type; ANNOUNCEMENT::CAnnouncementManager::GetInstance().Announce(ANNOUNCEMENT::VideoLibrary, "xbmc", "OnUpdate", data); } updateListing = true; } } if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->HasStreamDetails()) { CFileItem dbItem(item); // Check whether the item's db streamdetails need updating if (!videodatabase.GetStreamDetails(dbItem) || dbItem.GetVideoInfoTag()->m_streamDetails != item.GetVideoInfoTag()->m_streamDetails) { videodatabase.SetStreamDetailsForFile(item.GetVideoInfoTag()->m_streamDetails, progressTrackingFile); updateListing = true; } } // Could be part of an ISO stack. In this case the bookmark is saved onto the part. // In order to properly update the list, we need to refresh the stack's resume point CApplicationStackHelper& stackHelper = g_application.GetAppStackHelper(); if (stackHelper.HasRegisteredStack(item) && stackHelper.GetRegisteredStackTotalTimeMs(item) == 0) videodatabase.GetResumePoint(*(stackHelper.GetRegisteredStack(item)->GetVideoInfoTag())); videodatabase.Close(); if (updateListing) { CUtil::DeleteVideoDatabaseDirectoryCache(); CFileItemPtr msgItem(new CFileItem(item)); if (item.HasProperty("original_listitem_url")) msgItem->SetPath(item.GetProperty("original_listitem_url").asString()); CGUIMessage message(GUI_MSG_NOTIFY_ALL, CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow(), 0, GUI_MSG_UPDATE_ITEM, 0, msgItem); CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(message); } } } if (item.IsAudio()) { std::string redactPath = CURL::GetRedacted(progressTrackingFile); CLog::Log(LOGDEBUG, "%s - Saving file state for audio item %s", __FUNCTION__, redactPath.c_str()); CMusicDatabase musicdatabase; if (updatePlayCount) { if (!musicdatabase.Open()) { CLog::Log(LOGWARNING, "%s - Unable to open music database. Can not save file state!", __FUNCTION__); } else { // consider this item as played CLog::Log(LOGDEBUG, "%s - Marking audio item %s as listened", __FUNCTION__, redactPath.c_str()); musicdatabase.IncrementPlayCount(item); musicdatabase.Close(); // UPnP announce resume point changes to clients // however not if playcount is modified as that already announces if (item.IsMusicDb()) { CVariant data; data["id"] = item.GetMusicInfoTag()->GetDatabaseId(); data["type"] = item.GetMusicInfoTag()->GetType(); ANNOUNCEMENT::CAnnouncementManager::GetInstance().Announce(ANNOUNCEMENT::AudioLibrary, "xbmc", "OnUpdate", data); } } } if (item.IsAudioBook()) { musicdatabase.Open(); musicdatabase.SetResumeBookmarkForAudioBook(item, item.m_lStartOffset + CUtil::ConvertSecsToMilliSecs(bookmark.timeInSeconds)); musicdatabase.Close(); } } } }
CStdString CThumbnailCache::GetAlbumThumb(const CFileItem &item) { return GetAlbumThumb(item.GetMusicInfoTag()); }
bool CPVRManager::UpdateItem(CFileItem& item) { /* Don't update if a recording is played */ if (item.IsPVRRecording()) return false; if (!item.IsPVRChannel()) { CLog::Log(LOGERROR, "CPVRManager - %s - no channel tag provided", __FUNCTION__); return false; } CSingleLock lock(m_critSection); if (!m_currentFile || *m_currentFile->GetPVRChannelInfoTag() == *item.GetPVRChannelInfoTag()) return false; g_application.SetCurrentFileItem(*m_currentFile); CFileItemPtr itemptr(new CFileItem(*m_currentFile)); g_infoManager.SetCurrentItem(itemptr); CPVRChannelPtr channelTag(item.GetPVRChannelInfoTag()); CEpgInfoTagPtr epgTagNow(channelTag->GetEPGNow()); if (channelTag->IsRadio()) { CMusicInfoTag* musictag = item.GetMusicInfoTag(); if (musictag) { musictag->SetTitle(epgTagNow ? epgTagNow->Title() : CSettings::GetInstance().GetBool(CSettings::SETTING_EPG_HIDENOINFOAVAILABLE) ? "" : g_localizeStrings.Get(19055)); // no information available if (epgTagNow) musictag->SetGenre(epgTagNow->Genre()); musictag->SetDuration(epgTagNow ? epgTagNow->GetDuration() : 3600); musictag->SetURL(channelTag->Path()); musictag->SetArtist(channelTag->ChannelName()); musictag->SetAlbumArtist(channelTag->ChannelName()); musictag->SetLoaded(true); musictag->SetComment(""); musictag->SetLyrics(""); } } else { CVideoInfoTag *videotag = item.GetVideoInfoTag(); if (videotag) { videotag->m_strTitle = epgTagNow ? epgTagNow->Title() : CSettings::GetInstance().GetBool(CSettings::SETTING_EPG_HIDENOINFOAVAILABLE) ? "" : g_localizeStrings.Get(19055); // no information available if (epgTagNow) videotag->m_genre = epgTagNow->Genre(); videotag->m_strPath = channelTag->Path(); videotag->m_strFileNameAndPath = channelTag->Path(); videotag->m_strPlot = epgTagNow ? epgTagNow->Plot() : ""; videotag->m_strPlotOutline = epgTagNow ? epgTagNow->PlotOutline() : ""; videotag->m_iEpisode = epgTagNow ? epgTagNow->EpisodeNumber() : 0; } } return false; }
bool CMusicThumbLoader::FillLibraryArt(CFileItem &item) { /* Called for any item with MusicInfoTag and no art. Items on Genres, Sources and Roles nodes have ID (although items on Years node do not) so check for song/album/artist specifically. Non-library songs (file view) can also have MusicInfoTag but no ID or type */ bool artfound(false); std::vector<ArtForThumbLoader> art; CMusicInfoTag &tag = *item.GetMusicInfoTag(); if (tag.GetDatabaseId() > -1 && (tag.GetType() == MediaTypeSong || tag.GetType() == MediaTypeAlbum || tag.GetType() == MediaTypeArtist)) { // Item in music library, fetch the art m_musicDatabase->Open(); if (tag.GetType() == MediaTypeSong) artfound = m_musicDatabase->GetArtForItem(tag.GetDatabaseId(), tag.GetAlbumId(), -1, false, art); else if (tag.GetType() == MediaTypeAlbum) artfound = m_musicDatabase->GetArtForItem(-1, tag.GetDatabaseId(), -1, false, art); else //Artist artfound = m_musicDatabase->GetArtForItem(-1, -1, tag.GetDatabaseId(), true, art); m_musicDatabase->Close(); } else if (!tag.GetArtist().empty() && (tag.GetType() == MediaTypeNone || tag.GetType() == MediaTypeSong)) { /* Could be non-library song - has musictag but no ID or type (may have thumb already). Try to fetch both song artist(s) and album artist(s) art by artist name, e.g. "artist.thumb", "artist.fanart", "artist.clearlogo", "artist.banner", "artist1.thumb", "artist1.fanart", "artist1.clearlogo", "artist1.banner", "albumartist.thumb", "albumartist.fanart" etc. Set fanart as fallback. */ CSong song; // Try to split song artist names (various tags) into artist credits song.SetArtistCredits(tag.GetArtist(), tag.GetMusicBrainzArtistHints(), tag.GetMusicBrainzArtistID()); if (!song.artistCredits.empty()) { tag.SetType(MediaTypeSong); // Makes "Information" context menu visible m_musicDatabase->Open(); int iOrder = 0; // Song artist art for (const auto& artistCredit : song.artistCredits) { int idArtist = m_musicDatabase->GetArtistByName(artistCredit.GetArtist()); if (idArtist > 0) { std::vector<ArtForThumbLoader> artistart; if (m_musicDatabase->GetArtForItem(-1, -1, idArtist, true, artistart)) { for (auto& artitem : artistart) { if (iOrder > 0) artitem.prefix = StringUtils::Format("artist%i", iOrder); else artitem.prefix = "artist"; } art.insert(art.end(), artistart.begin(), artistart.end()); } } ++iOrder; } // Album artist art if (!tag.GetAlbumArtist().empty() && tag.GetArtistString().compare(tag.GetAlbumArtistString()) != 0) { // Split song artist names correctly into artist credits from various tag // arrays, inc. fallback to song artist names CAlbum album; album.SetArtistCredits(tag.GetAlbumArtist(), tag.GetMusicBrainzAlbumArtistHints(), tag.GetMusicBrainzAlbumArtistID(), tag.GetArtist(), tag.GetMusicBrainzArtistHints(), tag.GetMusicBrainzArtistID()); iOrder = 0; for (const auto& artistCredit : album.artistCredits) { int idArtist = m_musicDatabase->GetArtistByName(artistCredit.GetArtist()); if (idArtist > 0) { std::vector<ArtForThumbLoader> artistart; if (m_musicDatabase->GetArtForItem(-1, -1, idArtist, true, artistart)) { for (auto& artitem : artistart) { if (iOrder > 0) artitem.prefix = StringUtils::Format("albumartist%i", iOrder); else artitem.prefix = "albumartist"; } art.insert(art.end(), artistart.begin(), artistart.end()); } } ++iOrder; } } else { // Replicate the artist art as album artist art std::vector<ArtForThumbLoader> artistart; for (const auto& artitem : art) { ArtForThumbLoader newart; newart.artType = artitem.artType; newart.mediaType = artitem.mediaType; newart.prefix = "album" + artitem.prefix; newart.url = artitem.url; artistart.emplace_back(newart); } art.insert(art.end(), artistart.begin(), artistart.end()); } artfound = !art.empty(); m_musicDatabase->Close(); } } if (artfound) { std::string fanartfallback; bool bDiscSetThumbSet = false; std::map<std::string, std::string> artmap; for (auto artitem : art) { /* Add art to artmap, naming according to media type. For example: artists have "thumb", "fanart", "poster" etc., albums have "thumb", "artist.thumb", "artist.fanart",... "artist1.thumb", "artist1.fanart" etc., songs have "thumb", "album.thumb", "artist.thumb", "albumartist.thumb", "albumartist1.thumb" etc. */ std::string artname; if (tag.GetType() == artitem.mediaType) artname = artitem.artType; else if (artitem.prefix.empty()) artname = artitem.mediaType + "." + artitem.artType; else { if (tag.GetType() == MediaTypeAlbum) StringUtils::Replace(artitem.prefix, "albumartist", "artist"); artname = artitem.prefix + "." + artitem.artType; } artmap.insert(std::make_pair(artname, artitem.url)); // Add fallback art for "thumb" and "fanart" art types only // Set album thumb as the fallback used when song thumb is missing // or use extra album thumb when part of disc set if (tag.GetType() == MediaTypeSong && artitem.mediaType == MediaTypeAlbum) { if (artitem.artType == "thumb" && !bDiscSetThumbSet) item.SetArtFallback(artitem.artType, artname); else if (StringUtils::StartsWith(artitem.artType, "thumb")) { int number = atoi(artitem.artType.substr(5).c_str()); if (number > 0 && tag.GetDiscNumber() == number) { item.SetArtFallback("thumb", artname); bDiscSetThumbSet = true; } } } // For albums and songs set fallback fanart from the artist. // For songs prefer primary song artist over primary albumartist fanart as fallback fanart if (artitem.prefix == "artist" && artitem.artType == "fanart") fanartfallback = artname; if (artitem.prefix == "albumartist" && artitem.artType == "fanart" && fanartfallback.empty()) fanartfallback = artname; } if (!fanartfallback.empty()) item.SetArtFallback("fanart", fanartfallback); item.AppendArt(artmap); } return artfound; }
void CGUIWindowMusicBase::OnInfo(CFileItem *pItem, bool bShowInfo) { if (pItem->m_bIsFolder && pItem->IsParentFolder()) return; if (pItem->IsVideoDb()) { OnContextButton(m_viewControl.GetSelectedItem(), CONTEXT_BUTTON_INFO); // nasty but it is the same item i promise :) return; } CStdString strPath = pItem->m_strPath; // Try to find an album to lookup from the current item CAlbum album; CArtist artist; bool foundAlbum = false; album.idAlbum = -1; if (pItem->IsMusicDb()) { CQueryParams params; CDirectoryNode::GetDatabaseInfo(pItem->m_strPath, params); if (params.GetAlbumId() == -1) { artist.idArtist = params.GetArtistId(); artist.strArtist = pItem->GetMusicInfoTag()->GetArtist(); } else { // show dialog box indicating we're searching the album name if (m_dlgProgress && bShowInfo) { m_dlgProgress->SetHeading(185); m_dlgProgress->SetLine(0, 501); m_dlgProgress->SetLine(1, ""); m_dlgProgress->SetLine(2, ""); m_dlgProgress->StartModal(); m_dlgProgress->Progress(); if (m_dlgProgress->IsCanceled()) return; } album.idAlbum = params.GetAlbumId(); album.strAlbum = pItem->GetMusicInfoTag()->GetAlbum(); album.strArtist = pItem->GetMusicInfoTag()->GetArtist(); // we're going to need it's path as well (we assume that there's only one) - this is for // assigning thumbs to folders, and obtaining the local folder.jpg m_musicdatabase.GetAlbumPath(album.idAlbum, strPath); } } else { // lookup is done on a folder - find the albums in the folder CFileItemList items; GetDirectory(strPath, items); // check the first song we find in the folder, and grab it's album info for (int i = 0; i < items.Size() && !foundAlbum; i++) { CFileItem* pItem = items[i]; pItem->LoadMusicTag(); if (pItem->HasMusicInfoTag() && pItem->GetMusicInfoTag()->Loaded() && !pItem->GetMusicInfoTag()->GetAlbum().IsEmpty()) { // great, have a song - use it. CSong song(*pItem->GetMusicInfoTag()); // this function won't be needed if/when the tag has idSong information if (!m_musicdatabase.GetAlbumFromSong(song, album)) { // album isn't in the database - construct it from the tag info we have CMusicInfoTag *tag = pItem->GetMusicInfoTag(); album.strAlbum = tag->GetAlbum(); album.strArtist = tag->GetAlbumArtist().IsEmpty() ? tag->GetArtist() : tag->GetAlbumArtist(); album.idAlbum = -1; // the -1 indicates it's not in the database } foundAlbum = true; } } if (!foundAlbum) { CLog::Log(LOGINFO, "%s called on a folder containing no songs with tag info - nothing can be done", __FUNCTION__); if (m_dlgProgress && bShowInfo) m_dlgProgress->Close(); } } if (m_dlgProgress && bShowInfo) m_dlgProgress->Close(); if (album.idAlbum == -1 && foundAlbum == false) ShowArtistInfo(artist, pItem->m_strPath, false, bShowInfo); else ShowAlbumInfo(album, strPath, false, bShowInfo); }
void CGUIWindowMusicBase::UpdateThumb(const CAlbum &album, const CStdString &path) { // check user permissions bool saveDb = album.idAlbum != -1; bool saveDirThumb = true; if (!g_settings.m_vecProfiles[g_settings.m_iLastLoadedProfileIndex].canWriteDatabases() && !g_passwordManager.bMasterUser) { saveDb = false; saveDirThumb = false; } CStdString albumThumb(CUtil::GetCachedAlbumThumb(album.strAlbum, album.strArtist)); // Update the thumb in the music database (songs + albums) CStdString albumPath(path); if (saveDb && CFile::Exists(albumThumb)) m_musicdatabase.SaveAlbumThumb(album.idAlbum, albumThumb); // Update currently playing song if it's from the same album. This is necessary as when the album // first gets it's cover, the info manager's item doesn't have the updated information (so will be // sending a blank thumb to the skin.) if (g_application.IsPlayingAudio()) { CStdString strSongFolder; const CMusicInfoTag* tag=g_infoManager.GetCurrentSongTag(); if (tag) { // really, this may not be enough as it is to reliably update this item. eg think of various artists albums // that aren't tagged as such (and aren't yet scanned). But we probably can't do anything better than this // in that case if (album.strAlbum == tag->GetAlbum() && (album.strArtist == tag->GetAlbumArtist() || album.strArtist == tag->GetArtist())) { g_infoManager.SetCurrentAlbumThumb(albumThumb); } } } // Save this thumb as the directory thumb if it's the only album in the folder (files view nicety) // We do this by grabbing all the songs in the folder, and checking to see whether they come // from the same album. if (saveDirThumb && CFile::Exists(albumThumb) && !albumPath.IsEmpty() && !CUtil::IsCDDA(albumPath)) { CFileItemList items; GetDirectory(albumPath, items); OnRetrieveMusicInfo(items); VECSONGS songs; for (int i = 0; i < items.Size(); i++) { CFileItem *item = items[i]; if (item->HasMusicInfoTag() && item->GetMusicInfoTag()->Loaded()) { CSong song(*item->GetMusicInfoTag()); songs.push_back(song); } } CMusicInfoScanner::CheckForVariousArtists(songs); CStdString album, artist; if (CMusicInfoScanner::HasSingleAlbum(songs, album, artist)) { // can cache as the folder thumb CStdString folderThumb(CUtil::GetCachedMusicThumb(albumPath)); ::CopyFile(albumThumb, folderThumb, false); } } // update the file listing int iSelectedItem = m_viewControl.GetSelectedItem(); if (iSelectedItem >= 0 && m_vecItems->Get(iSelectedItem)) { CFileItem* pSelectedItem=m_vecItems->Get(iSelectedItem); if (pSelectedItem->m_bIsFolder) { // refresh only the icon of // the current folder pSelectedItem->FreeMemory(); if (!pSelectedItem->HasThumbnail()) pSelectedItem->SetThumbnailImage(albumThumb); pSelectedItem->FillInDefaultIcon(); } else { // Refresh all items m_vecItems->RemoveDiscCache(); Update(m_vecItems->m_strPath); } // Do we have to autoswitch to the thumb control? m_guiState.reset(CGUIViewState::GetViewState(GetID(), *m_vecItems)); UpdateButtons(); } }
bool PAPlayer::QueueNextFileEx(const CFileItem &file, bool fadeIn/* = true */, bool job /* = false */) { // check if we advance a track of a CUE sheet // if this is the case we don't need to open a new stream std::string newURL = file.GetMusicInfoTag() ? file.GetMusicInfoTag()->GetURL() : file.GetPath(); std::string oldURL = m_FileItem->GetMusicInfoTag() ? m_FileItem->GetMusicInfoTag()->GetURL() : m_FileItem->GetPath(); if (newURL.compare(oldURL) == 0 && file.m_lStartOffset && file.m_lStartOffset == m_FileItem->m_lEndOffset && m_currentStream && m_currentStream->m_prepareTriggered) { m_continueStream = true; m_upcomingCrossfadeMS = 0; *m_FileItem = file; return true; } else { m_continueStream = false; } StreamInfo *si = new StreamInfo(); if (!si->m_decoder.Create(file, (file.m_lStartOffset * 1000) / 75)) { CLog::Log(LOGWARNING, "PAPlayer::QueueNextFileEx - Failed to create the decoder"); delete si; // advance playlist if (job) m_callback.OnPlayBackStarted(); m_callback.OnQueueNextItem(); return false; } /* decode until there is data-available */ si->m_decoder.Start(); while(si->m_decoder.GetDataSize() == 0) { int status = si->m_decoder.GetStatus(); if (status == STATUS_ENDED || status == STATUS_NO_FILE || si->m_decoder.ReadSamples(PACKET_SIZE) == RET_ERROR) { CLog::Log(LOGINFO, "PAPlayer::QueueNextFileEx - Error reading samples"); si->m_decoder.Destroy(); delete si; // advance playlist if (job) m_callback.OnPlayBackStarted(); m_callback.OnQueueNextItem(); return false; } /* yield our time so that the main PAP thread doesnt stall */ CThread::Sleep(1); } // set m_upcomingCrossfadeMS depending on type of file and user settings UpdateCrossfadeTime(file); /* init the streaminfo struct */ si->m_decoder.GetDataFormat(&si->m_channelInfo, &si->m_sampleRate, &si->m_encodedSampleRate, &si->m_dataFormat); si->m_startOffset = file.m_lStartOffset * 1000 / 75; si->m_endOffset = file.m_lEndOffset * 1000 / 75; si->m_bytesPerSample = CAEUtil::DataFormatToBits(si->m_dataFormat) >> 3; si->m_bytesPerFrame = si->m_bytesPerSample * si->m_channelInfo.Count(); si->m_started = false; si->m_finishing = false; si->m_framesSent = 0; si->m_seekNextAtFrame = 0; si->m_seekFrame = -1; si->m_stream = NULL; si->m_volume = (fadeIn && m_upcomingCrossfadeMS) ? 0.0f : 1.0f; si->m_fadeOutTriggered = false; si->m_isSlaved = false; int64_t streamTotalTime = si->m_decoder.TotalTime(); if (si->m_endOffset) streamTotalTime = si->m_endOffset - si->m_startOffset; si->m_prepareNextAtFrame = 0; // cd drives don't really like it to be crossfaded or prepared if(!file.IsCDDA()) { if (streamTotalTime >= TIME_TO_CACHE_NEXT_FILE + m_defaultCrossfadeMS) si->m_prepareNextAtFrame = (int)((streamTotalTime - TIME_TO_CACHE_NEXT_FILE - m_defaultCrossfadeMS) * si->m_sampleRate / 1000.0f); } if (m_currentStream && (AE_IS_RAW(m_currentStream->m_dataFormat) || AE_IS_RAW(si->m_dataFormat))) { m_currentStream->m_prepareTriggered = false; m_currentStream->m_waitOnDrain = true; m_currentStream->m_prepareNextAtFrame = 0; si->m_decoder.Destroy(); delete si; return false; } si->m_prepareTriggered = false; si->m_playNextAtFrame = 0; si->m_playNextTriggered = false; si->m_waitOnDrain = false; if (!PrepareStream(si)) { CLog::Log(LOGINFO, "PAPlayer::QueueNextFileEx - Error preparing stream"); si->m_decoder.Destroy(); delete si; // advance playlist if (job) m_callback.OnPlayBackStarted(); m_callback.OnQueueNextItem(); return false; } /* add the stream to the list */ CExclusiveLock lock(m_streamsLock); m_streams.push_back(si); //update the current stream to start playing the next track at the correct frame. UpdateStreamInfoPlayNextAtFrame(m_currentStream, m_upcomingCrossfadeMS); *m_FileItem = file; return true; }
bool CPVRManager::UpdateItem(CFileItem& item) { /* Don't update if a recording is played */ if (item.IsPVRRecording()) return false; if (!item.IsPVRChannel()) { CLog::Log(LOGERROR, "CPVRManager - %s - no channel tag provided", __FUNCTION__); return false; } CSingleLock lock(m_critSection); if (!m_currentFile || *m_currentFile->GetPVRChannelInfoTag() == *item.GetPVRChannelInfoTag()) return false; g_application.CurrentFileItem() = *m_currentFile; g_infoManager.SetCurrentItem(*m_currentFile); CPVRChannel* channelTag = item.GetPVRChannelInfoTag(); CEpgInfoTag epgTagNow; bool bHasTagNow = channelTag->GetEPGNow(epgTagNow); if (channelTag->IsRadio()) { CMusicInfoTag* musictag = item.GetMusicInfoTag(); if (musictag) { musictag->SetTitle(bHasTagNow ? epgTagNow.Title() : g_guiSettings.GetBool("epg.hidenoinfoavailable") ? StringUtils::EmptyString : g_localizeStrings.Get(19055)); // no information available if (bHasTagNow) musictag->SetGenre(epgTagNow.Genre()); musictag->SetDuration(bHasTagNow ? epgTagNow.GetDuration() : 3600); musictag->SetURL(channelTag->Path()); musictag->SetArtist(channelTag->ChannelName()); musictag->SetAlbumArtist(channelTag->ChannelName()); musictag->SetLoaded(true); musictag->SetComment(StringUtils::EmptyString); musictag->SetLyrics(StringUtils::EmptyString); } } else { CVideoInfoTag *videotag = item.GetVideoInfoTag(); if (videotag) { videotag->m_strTitle = bHasTagNow ? epgTagNow.Title() : g_guiSettings.GetBool("epg.hidenoinfoavailable") ? StringUtils::EmptyString : g_localizeStrings.Get(19055); // no information available if (bHasTagNow) videotag->m_genre = epgTagNow.Genre(); videotag->m_strPath = channelTag->Path(); videotag->m_strFileNameAndPath = channelTag->Path(); videotag->m_strPlot = bHasTagNow ? epgTagNow.Plot() : StringUtils::EmptyString; videotag->m_strPlotOutline = bHasTagNow ? epgTagNow.PlotOutline() : StringUtils::EmptyString; videotag->m_iEpisode = bHasTagNow ? epgTagNow.EpisodeNum() : 0; } } return false; }
void CGUIWindowMusicNav::GetContextButtons(int itemNumber, CContextButtons &buttons) { CGUIWindowMusicBase::GetContextButtons(itemNumber, buttons); CGUIDialogMusicScan *musicScan = (CGUIDialogMusicScan *)m_gWindowManager.GetWindow(WINDOW_DIALOG_MUSIC_SCAN); CFileItem *item = (itemNumber >= 0 && itemNumber < m_vecItems->Size()) ? m_vecItems->Get(itemNumber) : NULL; if (item && (item->GetExtraInfo().Find("lastfm") < 0)) { // are we in the playlists location? bool inPlaylists = m_vecItems->m_strPath.Equals(CUtil::MusicPlaylistsLocation()) || m_vecItems->m_strPath.Equals("special://musicplaylists/"); CMusicDatabaseDirectory dir; SScraperInfo info; m_musicdatabase.GetScraperForPath(item->m_strPath,info); // enable music info button on an album or on a song. if (item->IsAudio() && !item->IsPlayList() && !item->IsSmartPlayList() && !item->IsLastFM() && !item->IsShoutCast()) { buttons.Add(CONTEXT_BUTTON_SONG_INFO, 658); } else if (item->IsVideoDb()) { if (!item->m_bIsFolder) // music video buttons.Add(CONTEXT_BUTTON_INFO, 20393); if (item->m_strPath.Left(14).Equals("videodb://3/4/") && item->m_strPath.size() > 14 && item->m_bIsFolder) { long idArtist = m_musicdatabase.GetArtistByName(m_vecItems->Get(itemNumber)->GetLabel()); if (idArtist > - 1) buttons.Add(CONTEXT_BUTTON_INFO,21891); } } else if (!inPlaylists && (dir.HasAlbumInfo(item->m_strPath)|| dir.IsArtistDir(item->m_strPath) ) && !dir.IsAllItem(item->m_strPath) && !item->IsParentFolder() && !item->IsLastFM() && !item->IsShoutCast() && !item->m_strPath.Left(14).Equals("musicsearch://")) { if (dir.IsArtistDir(item->m_strPath)) buttons.Add(CONTEXT_BUTTON_INFO, 21891); else buttons.Add(CONTEXT_BUTTON_INFO, 13351); } // enable query all albums button only in album view if (dir.HasAlbumInfo(item->m_strPath) && !dir.IsAllItem(item->m_strPath) && item->m_bIsFolder && !item->IsVideoDb() && !item->IsParentFolder() && !item->IsLastFM() && !item->IsShoutCast() && !item->m_strPath.Left(14).Equals("musicsearch://")) { buttons.Add(CONTEXT_BUTTON_INFO_ALL, 20059); } // enable query all artist button only in album view if (dir.IsArtistDir(item->m_strPath) && !dir.IsAllItem(item->m_strPath) && item->m_bIsFolder && !item->IsVideoDb() && !info.strContent.IsEmpty()) { buttons.Add(CONTEXT_BUTTON_INFO_ALL, 21884); } // turn off set artist image if not at artist listing. if (dir.IsArtistDir(item->m_strPath) && !dir.IsAllItem(item->m_strPath) || (item->m_strPath.Left(14).Equals("videodb://3/4/") && item->m_strPath.size() > 14 && item->m_bIsFolder)) { buttons.Add(CONTEXT_BUTTON_SET_ARTIST_THUMB, 13359); } if (m_vecItems->m_strPath.Equals("plugin://music/")) buttons.Add(CONTEXT_BUTTON_SET_PLUGIN_THUMB, 1044); //Set default or clear default NODE_TYPE nodetype = dir.GetDirectoryType(item->m_strPath); if (!item->IsParentFolder() && !inPlaylists && (nodetype == NODE_TYPE_ROOT || nodetype == NODE_TYPE_OVERVIEW || nodetype == NODE_TYPE_TOP100)) { if (!item->m_strPath.Equals(g_settings.m_defaultMusicLibSource)) buttons.Add(CONTEXT_BUTTON_SET_DEFAULT, 13335); // set default if (strcmp(g_settings.m_defaultMusicLibSource, "")) buttons.Add(CONTEXT_BUTTON_CLEAR_DEFAULT, 13403); // clear default } NODE_TYPE childtype = dir.GetDirectoryChildType(item->m_strPath); if (childtype == NODE_TYPE_ALBUM || childtype == NODE_TYPE_ARTIST || nodetype == NODE_TYPE_GENRE || nodetype == NODE_TYPE_ALBUM) { // we allow the user to set content for // 1. general artist and album nodes // 2. specific per genre // 3. specific per artist // 4. specific per album buttons.Add(CONTEXT_BUTTON_SET_CONTENT,20195); } if (item->HasMusicInfoTag() && item->GetMusicInfoTag()->GetArtist().size() > 0) { CVideoDatabase database; database.Open(); if (database.GetMusicVideoArtistByName(item->GetMusicInfoTag()->GetArtist()) > -1) buttons.Add(CONTEXT_BUTTON_GO_TO_ARTIST, 20400); } if (item->HasMusicInfoTag() && item->GetMusicInfoTag()->GetArtist().size() > 0 && item->GetMusicInfoTag()->GetAlbum().size() > 0 && item->GetMusicInfoTag()->GetTitle().size() > 0) { CVideoDatabase database; database.Open(); if (database.GetMusicVideoByArtistAndAlbumAndTitle(item->GetMusicInfoTag()->GetArtist(),item->GetMusicInfoTag()->GetAlbum(),item->GetMusicInfoTag()->GetTitle()) > -1) buttons.Add(CONTEXT_BUTTON_PLAY_OTHER, 20401); } if (item->HasVideoInfoTag() && !item->m_bIsFolder) { if (item->GetVideoInfoTag()->m_bWatched) buttons.Add(CONTEXT_BUTTON_MARK_UNWATCHED, 16104); //Mark as UnWatched else buttons.Add(CONTEXT_BUTTON_MARK_WATCHED, 16103); //Mark as Watched if (g_settings.m_vecProfiles[g_settings.m_iLastLoadedProfileIndex].canWriteDatabases() || g_passwordManager.bMasterUser) { buttons.Add(CONTEXT_BUTTON_RENAME, 16105); buttons.Add(CONTEXT_BUTTON_DELETE, 646); } } } // noncontextual buttons if (musicScan && musicScan->IsScanning()) buttons.Add(CONTEXT_BUTTON_STOP_SCANNING, 13353); // Stop Scanning else if (musicScan) buttons.Add(CONTEXT_BUTTON_UPDATE_LIBRARY, 653); CGUIWindowMusicBase::GetNonContextButtons(buttons); }
CAlbum::CAlbum(const CFileItem& item) { Reset(); const CMusicInfoTag& tag = *item.GetMusicInfoTag(); SYSTEMTIME stTime; tag.GetReleaseDate(stTime); strAlbum = tag.GetAlbum(); strMusicBrainzAlbumID = tag.GetMusicBrainzAlbumID(); genre = tag.GetGenre(); std::vector<std::string> musicBrainzAlbumArtistHints = tag.GetMusicBrainzAlbumArtistHints(); strArtistDesc = tag.GetAlbumArtistString(); if (!tag.GetMusicBrainzAlbumArtistID().empty()) { // Have musicbrainz artist info, so use it // Vector of possible separators in the order least likely to be part of artist name const std::vector<std::string> separators{ " feat. ", ";", ":", "|", "#", "/", ",", "&" }; // Establish tag consistency // Do the number of musicbrainz ids and number of names in hints and artist mis-match? if (musicBrainzAlbumArtistHints.size() != tag.GetMusicBrainzAlbumArtistID().size() && tag.GetAlbumArtist().size() != tag.GetMusicBrainzAlbumArtistID().size()) { // Tags mis-match - report it and then try to fix CLog::Log(LOGDEBUG, "Mis-match in song file albumartist tags: %i mbid %i name album: %s %s", (int)tag.GetMusicBrainzAlbumArtistID().size(), (int)tag.GetAlbumArtist().size(), strAlbum.c_str(), strArtistDesc.c_str()); /* Most likely we have no hints and a single artist name like "Artist1 feat. Artist2" or "Composer; Conductor, Orchestra, Soloist" or "Artist1/Artist2" where the expected single item separator (default = space-slash-space) as not been used. Comma and slash (no spaces) are poor delimiters as could be in name e.g. AC/DC, but here treat them as such in attempt to find artist names. When there are hints they could be poorly formatted using unexpected separators, so attempt to split them. Or we could have more hints or artist names than musicbrainz so ignore them but raise warning. */ // Do hints exist yet mis-match if (!musicBrainzAlbumArtistHints.empty() && musicBrainzAlbumArtistHints.size() != tag.GetMusicBrainzAlbumArtistID().size()) { if (tag.GetAlbumArtist().size() == tag.GetMusicBrainzAlbumArtistID().size()) // Album artist name count matches, use that as hints musicBrainzAlbumArtistHints = tag.GetAlbumArtist(); else if (musicBrainzAlbumArtistHints.size() < tag.GetMusicBrainzAlbumArtistID().size()) { // Try splitting the hints until have matching number musicBrainzAlbumArtistHints = StringUtils::SplitMulti(musicBrainzAlbumArtistHints, separators, tag.GetMusicBrainzAlbumArtistID().size()); } else // Extra hints, discard them. musicBrainzAlbumArtistHints.resize(tag.GetMusicBrainzAlbumArtistID().size()); } // Do hints not exist or still mis-match, try album artists if (musicBrainzAlbumArtistHints.size() != tag.GetMusicBrainzAlbumArtistID().size()) musicBrainzAlbumArtistHints = tag.GetAlbumArtist(); // Still mis-match, try splitting the hints (now artists) until have matching number if (musicBrainzAlbumArtistHints.size() < tag.GetMusicBrainzAlbumArtistID().size()) musicBrainzAlbumArtistHints = StringUtils::SplitMulti(musicBrainzAlbumArtistHints, separators, tag.GetMusicBrainzAlbumArtistID().size()); // Try matching on artists or artist hints field, if it is reliable if (musicBrainzAlbumArtistHints.size() != tag.GetMusicBrainzAlbumArtistID().size()) { if (!tag.GetMusicBrainzArtistID().empty() && (tag.GetMusicBrainzArtistID().size() == tag.GetArtist().size() || tag.GetMusicBrainzArtistID().size() == tag.GetMusicBrainzArtistHints().size())) { for (size_t i = 0; i < tag.GetMusicBrainzAlbumArtistID().size(); i++) { for (size_t j = 0; j < tag.GetMusicBrainzArtistID().size(); j++) { if (tag.GetMusicBrainzAlbumArtistID()[i] == tag.GetMusicBrainzArtistID()[j]) { if (musicBrainzAlbumArtistHints.size() < i + 1) musicBrainzAlbumArtistHints.resize(i + 1); if (tag.GetMusicBrainzArtistID().size() == tag.GetMusicBrainzArtistHints().size()) musicBrainzAlbumArtistHints[j] = tag.GetMusicBrainzArtistHints()[j]; else musicBrainzAlbumArtistHints[j] = tag.GetArtist()[j]; } } } } } } else { // Either hints or album artists (or both) name matches number of musicbrainz id // If hints mis-match, use album artists if (musicBrainzAlbumArtistHints.size() != tag.GetMusicBrainzAlbumArtistID().size()) musicBrainzAlbumArtistHints = tag.GetAlbumArtist(); } for (size_t i = 0; i < tag.GetMusicBrainzAlbumArtistID().size(); i++) { std::string artistId = tag.GetMusicBrainzAlbumArtistID()[i]; std::string artistName; /* We try and get the mbrainzid <-> name matching from the hints and match on the same index. Some album artist hints could be blank (if populated from artist or artist hints). If not found, use the mbrainzid and hope we later on can update that entry If we have more names than musicbrainz id they are ignored, but raise a warning. */ if (i < musicBrainzAlbumArtistHints.size()) artistName = musicBrainzAlbumArtistHints[i]; if (artistName.empty()) artistName = artistId; artistCredits.emplace_back(StringUtils::Trim(artistName), tag.GetMusicBrainzAlbumArtistID()[i]); } } else { // No musicbrainz album artist ids so fill artist names directly. // This method only called when there is a musicbrainz album id, so means mbid tags are incomplete. // Try to separate album artist names further, and trim blank space. std::vector<std::string> albumArtists = tag.GetAlbumArtist(); if (musicBrainzAlbumArtistHints.size() > albumArtists.size()) // Make use of hints (ALBUMARTISTS tag), when present, to separate artist names albumArtists = musicBrainzAlbumArtistHints; else // Split album artist names further using multiple possible delimiters, over single separator applied in Tag loader albumArtists = StringUtils::SplitMulti(albumArtists, g_advancedSettings.m_musicArtistSeparators); for (auto artistname : albumArtists) { artistCredits.emplace_back(StringUtils::Trim(artistname)); } } iYear = stTime.wYear; strLabel = tag.GetRecordLabel(); strType = tag.GetMusicBrainzReleaseType(); bCompilation = tag.GetCompilation(); iTimesPlayed = 0; dateAdded.Reset(); lastPlayed.Reset(); releaseType = tag.GetAlbumReleaseType(); }
bool CShoutcastDirectory::ParseStations(TiXmlElement *root, CFileItemList &items, CURL &url) { TiXmlElement *element = NULL; CStdString path; items.m_idepth = 2; /* station list */ element = root->FirstChildElement("tunein"); if(element == NULL) { CLog::Log(LOGWARNING, "%s - No tunein base found", __FUNCTION__); return false; } path = element->Attribute("base"); path.TrimLeft("/"); url.SetFileName(path); element = root->FirstChildElement("station"); if(element == NULL) { CLog::Log(LOGWARNING, "%s - No stations found", __FUNCTION__); return false; } int stations = 0; while(element != NULL && stations < 1000) { CStdString name = element->Attribute("name"); CStdString id = element->Attribute("id"); CStdString bitrate = element->Attribute("br"); CStdString genre = element->Attribute("genre"); CStdString listeners = element->Attribute("lc"); CStdString content = element->Attribute("mt"); CStdString label = name; url.SetOptions("?id=" + id); url.GetURL(path); //printf("%s: %s\n", name.c_str(), path.c_str()); CFileItem* pItem = new CFileItem; pItem->m_bIsFolder = false; /* we highjack the music tag for this stuff, they will be used by */ /* viewstates to sort and display proper information */ pItem->GetMusicInfoTag()->SetArtist(listeners); pItem->GetMusicInfoTag()->SetAlbum(bitrate); pItem->GetMusicInfoTag()->SetGenre(genre); /* this is what will be sorted upon */ pItem->GetVideoInfoTag()->m_fRating = (float)atoi(listeners.c_str()); pItem->m_dwSize = atoi(bitrate.c_str()); pItem->SetLabel(label); /* content type is known before hand, should save later lookup */ /* wonder if we could combine the contentype of the playlist and of the real stream */ pItem->SetContentType("audio/x-scpls"); pItem->m_strPath = path; items.Add(pItem); stations++; element = element->NextSiblingElement("station"); } return true; }
bool CPVRManager::UpdateItem(CFileItem& item) { /* Don't update if a recording is played */ if (item.IsPVRRecording()) return false; if (!item.IsPVRChannel()) { CLog::Log(LOGERROR, "CPVRManager - %s - no channel tag provided", __FUNCTION__); return false; } CSingleLock lock(m_critSection); if (!m_currentFile || *m_currentFile->GetPVRChannelInfoTag() == *item.GetPVRChannelInfoTag()) return false; g_application.CurrentFileItem() = *m_currentFile; g_infoManager.SetCurrentItem(*m_currentFile); CPVRChannel* channelTag = item.GetPVRChannelInfoTag(); CEpgInfoTag epgTagNow; bool bHasTagNow = channelTag->GetEPGNow(epgTagNow); if (channelTag->IsRadio()) { CMusicInfoTag* musictag = item.GetMusicInfoTag(); if (musictag) { musictag->SetTitle(bHasTagNow ? epgTagNow.Title() : g_localizeStrings.Get(19055)); if (bHasTagNow) musictag->SetGenre(epgTagNow.Genre()); musictag->SetDuration(bHasTagNow ? epgTagNow.GetDuration() : 3600); musictag->SetURL(channelTag->Path()); musictag->SetArtist(channelTag->ChannelName()); musictag->SetAlbumArtist(channelTag->ChannelName()); musictag->SetLoaded(true); musictag->SetComment(StringUtils::EmptyString); musictag->SetLyrics(StringUtils::EmptyString); } } else { CVideoInfoTag *videotag = item.GetVideoInfoTag(); if (videotag) { videotag->m_strTitle = bHasTagNow ? epgTagNow.Title() : g_localizeStrings.Get(19055); if (bHasTagNow) videotag->m_genre = epgTagNow.Genre(); videotag->m_strPath = channelTag->Path(); videotag->m_strFileNameAndPath = channelTag->Path(); videotag->m_strPlot = bHasTagNow ? epgTagNow.Plot() : StringUtils::EmptyString; videotag->m_strPlotOutline = bHasTagNow ? epgTagNow.PlotOutline() : StringUtils::EmptyString; videotag->m_iEpisode = bHasTagNow ? epgTagNow.EpisodeNum() : 0; } } CPVRChannel* tagPrev = item.GetPVRChannelInfoTag(); if (tagPrev && tagPrev->ChannelNumber() != m_LastChannel) { m_LastChannel = tagPrev->ChannelNumber(); m_LastChannelChanged = XbmcThreads::SystemClockMillis(); } if (XbmcThreads::SystemClockMillis() - m_LastChannelChanged >= (unsigned int) g_guiSettings.GetInt("pvrplayback.channelentrytimeout") && m_LastChannel != m_PreviousChannel[m_PreviousChannelIndex]) m_PreviousChannel[m_PreviousChannelIndex ^= 1] = m_LastChannel; else m_LastChannelChanged = XbmcThreads::SystemClockMillis(); return false; }
void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg) { switch (pMsg->dwMessage) { case TMSG_SHUTDOWN: { switch (g_guiSettings.GetInt("powermanagement.shutdownstate")) { case POWERSTATE_SHUTDOWN: Powerdown(); break; case POWERSTATE_SUSPEND: Suspend(); break; case POWERSTATE_HIBERNATE: Hibernate(); break; case POWERSTATE_QUIT: Quit(); break; case POWERSTATE_MINIMIZE: Minimize(); break; case TMSG_RENDERER_FLUSH: g_renderManager.Flush(); break; } } break; case TMSG_POWERDOWN: { g_application.Stop(EXITCODE_POWERDOWN); g_powerManager.Powerdown(); } break; case TMSG_QUIT: { g_application.Stop(EXITCODE_QUIT); } break; case TMSG_HIBERNATE: { g_PVRManager.SetWakeupCommand(); g_powerManager.Hibernate(); } break; case TMSG_SUSPEND: { g_PVRManager.SetWakeupCommand(); g_powerManager.Suspend(); } break; case TMSG_RESTART: case TMSG_RESET: { g_application.Stop(EXITCODE_REBOOT); g_powerManager.Reboot(); } break; case TMSG_RESTARTAPP: { #if defined(TARGET_WINDOWS) || defined(TARGET_LINUX) g_application.Stop(EXITCODE_RESTARTAPP); #endif } break; case TMSG_INHIBITIDLESHUTDOWN: { g_application.InhibitIdleShutdown((bool)pMsg->dwParam1); } break; case TMSG_MEDIA_PLAY: { // first check if we were called from the PlayFile() function if (pMsg->lpVoid && pMsg->dwParam2 == 0) { CFileItem *item = (CFileItem *)pMsg->lpVoid; g_application.PlayFile(*item, pMsg->dwParam1 != 0); delete item; return; } // restore to previous window if needed if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO || g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) g_windowManager.PreviousWindow(); g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); //g_application.StopPlaying(); // play file if(pMsg->lpVoid) { CFileItemList *list = (CFileItemList *)pMsg->lpVoid; if (list->Size() > 0) { int playlist = PLAYLIST_MUSIC; for (int i = 0; i < list->Size(); i++) { if ((*list)[i]->IsVideo()) { playlist = PLAYLIST_VIDEO; break; } } g_playlistPlayer.ClearPlaylist(playlist); g_playlistPlayer.SetCurrentPlaylist(playlist); //For single item lists try PlayMedia. This covers some more cases where a playlist is not appropriate //It will fall through to PlayFile if (list->Size() == 1 && !(*list)[0]->IsPlayList()) g_application.PlayMedia(*((*list)[0]), playlist); else { // Handle "shuffled" option if present if (list->HasProperty("shuffled") && list->GetProperty("shuffled").isBoolean()) g_playlistPlayer.SetShuffle(playlist, list->GetProperty("shuffled").asBoolean(), false); // Handle "repeat" option if present if (list->HasProperty("repeat") && list->GetProperty("repeat").isInteger()) g_playlistPlayer.SetRepeat(playlist, (PLAYLIST::REPEAT_STATE)list->GetProperty("repeat").asInteger(), false); g_playlistPlayer.Add(playlist, (*list)); g_playlistPlayer.Play(pMsg->dwParam1); } } delete list; } else if (pMsg->dwParam1 == PLAYLIST_MUSIC || pMsg->dwParam1 == PLAYLIST_VIDEO) { if (g_playlistPlayer.GetCurrentPlaylist() != (int)pMsg->dwParam1) g_playlistPlayer.SetCurrentPlaylist(pMsg->dwParam1); PlayListPlayerPlay(pMsg->dwParam2); } } break; case TMSG_MEDIA_RESTART: g_application.Restart(true); break; case TMSG_PICTURE_SHOW: { CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW); if (!pSlideShow) return ; // stop playing file if (g_application.IsPlayingVideo()) g_application.StopPlaying(); if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO) g_windowManager.PreviousWindow(); g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); g_graphicsContext.Lock(); if (g_windowManager.GetActiveWindow() != WINDOW_SLIDESHOW) g_windowManager.ActivateWindow(WINDOW_SLIDESHOW); if (URIUtils::IsZIP(pMsg->strParam) || URIUtils::IsRAR(pMsg->strParam)) // actually a cbz/cbr { CFileItemList items; CStdString strPath; if (URIUtils::IsZIP(pMsg->strParam)) URIUtils::CreateArchivePath(strPath, "zip", pMsg->strParam.c_str(), ""); else URIUtils::CreateArchivePath(strPath, "rar", pMsg->strParam.c_str(), ""); CUtil::GetRecursiveListing(strPath, items, g_settings.m_pictureExtensions); if (items.Size() > 0) { pSlideShow->Reset(); for (int i=0;i<items.Size();++i) { pSlideShow->Add(items[i].get()); } pSlideShow->Select(items[0]->GetPath()); } } else { CFileItem item(pMsg->strParam, false); pSlideShow->Reset(); pSlideShow->Add(&item); pSlideShow->Select(pMsg->strParam); } g_graphicsContext.Unlock(); } break; case TMSG_SLIDESHOW_SCREENSAVER: case TMSG_PICTURE_SLIDESHOW: { CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW); if (!pSlideShow) return ; if (g_application.IsPlayingVideo()) g_application.StopPlaying(); g_graphicsContext.Lock(); pSlideShow->Reset(); CFileItemList items; CStdString strPath = pMsg->strParam; CStdString extensions = g_settings.m_pictureExtensions; if (pMsg->dwParam1) extensions += "|.tbn"; CUtil::GetRecursiveListing(strPath, items, extensions); if (items.Size() > 0) { for (int i=0;i<items.Size();++i) pSlideShow->Add(items[i].get()); pSlideShow->StartSlideShow(pMsg->dwMessage == TMSG_SLIDESHOW_SCREENSAVER); //Start the slideshow! } if (pMsg->dwMessage == TMSG_SLIDESHOW_SCREENSAVER) pSlideShow->Shuffle(); if (g_windowManager.GetActiveWindow() != WINDOW_SLIDESHOW) { if(items.Size() == 0) { g_guiSettings.SetString("screensaver.mode", "screensaver.xbmc.builtin.dim"); g_application.ActivateScreenSaver(); } else g_windowManager.ActivateWindow(WINDOW_SLIDESHOW); } g_graphicsContext.Unlock(); } break; case TMSG_SETLANGUAGE: g_guiSettings.SetLanguage(pMsg->strParam); break; case TMSG_MEDIA_STOP: { // restore to previous window if needed if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO || g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) g_windowManager.PreviousWindow(); g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); // stop playing file if (g_application.IsPlaying()) g_application.StopPlaying(); } break; case TMSG_MEDIA_PAUSE: if (g_application.m_pPlayer) { g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); g_application.m_pPlayer->Pause(); } break; case TMSG_MEDIA_UNPAUSE: if (g_application.IsPaused()) { g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); g_application.m_pPlayer->Pause(); } break; case TMSG_SWITCHTOFULLSCREEN: if( g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO ) g_application.SwitchToFullScreen(); break; case TMSG_TOGGLEFULLSCREEN: g_graphicsContext.Lock(); g_graphicsContext.ToggleFullScreenRoot(); g_graphicsContext.Unlock(); break; case TMSG_MINIMIZE: g_application.Minimize(); break; case TMSG_EXECUTE_OS: #if defined( _LINUX) && !defined(TARGET_DARWIN) CUtil::RunCommandLine(pMsg->strParam.c_str(), (pMsg->dwParam1 == 1)); #elif defined(_WIN32) CWIN32Util::XBMCShellExecute(pMsg->strParam.c_str(), (pMsg->dwParam1 == 1)); #endif break; case TMSG_HTTPAPI: { #ifdef HAS_HTTPAPI if (!m_pXbmcHttp) { m_pXbmcHttp = new CXbmcHttp(); } switch (m_pXbmcHttp->xbmcCommand(pMsg->strParam)) { case 1: Restart(); break; case 2: Shutdown(); break; case 3: Quit(); break; case 4: Reset(); break; case 5: RestartApp(); break; } #endif } break; case TMSG_EXECUTE_SCRIPT: #ifdef HAS_PYTHON g_pythonParser.evalFile(pMsg->strParam.c_str(),ADDON::AddonPtr()); #endif break; case TMSG_EXECUTE_BUILT_IN: CBuiltins::Execute(pMsg->strParam.c_str()); break; case TMSG_PLAYLISTPLAYER_PLAY: if (pMsg->dwParam1 != (DWORD) -1) g_playlistPlayer.Play(pMsg->dwParam1); else g_playlistPlayer.Play(); break; case TMSG_PLAYLISTPLAYER_PLAY_SONG_ID: if (pMsg->dwParam1 != (DWORD) -1) { bool *result = (bool*)pMsg->lpVoid; *result = g_playlistPlayer.PlaySongId(pMsg->dwParam1); } else g_playlistPlayer.Play(); break; case TMSG_PLAYLISTPLAYER_NEXT: g_playlistPlayer.PlayNext(); break; case TMSG_PLAYLISTPLAYER_PREV: g_playlistPlayer.PlayPrevious(); break; case TMSG_PLAYLISTPLAYER_ADD: if(pMsg->lpVoid) { CFileItemList *list = (CFileItemList *)pMsg->lpVoid; g_playlistPlayer.Add(pMsg->dwParam1, (*list)); delete list; } break; case TMSG_PLAYLISTPLAYER_INSERT: if (pMsg->lpVoid) { CFileItemList *list = (CFileItemList *)pMsg->lpVoid; g_playlistPlayer.Insert(pMsg->dwParam1, (*list), pMsg->dwParam2); delete list; } break; case TMSG_PLAYLISTPLAYER_REMOVE: if (pMsg->dwParam1 != (DWORD) -1) g_playlistPlayer.Remove(pMsg->dwParam1,pMsg->dwParam2); break; case TMSG_PLAYLISTPLAYER_CLEAR: g_playlistPlayer.ClearPlaylist(pMsg->dwParam1); break; case TMSG_PLAYLISTPLAYER_SHUFFLE: g_playlistPlayer.SetShuffle(pMsg->dwParam1, pMsg->dwParam2 > 0); break; case TMSG_PLAYLISTPLAYER_REPEAT: g_playlistPlayer.SetRepeat(pMsg->dwParam1, (PLAYLIST::REPEAT_STATE)pMsg->dwParam2); break; case TMSG_PLAYLISTPLAYER_GET_ITEMS: if (pMsg->lpVoid) { PLAYLIST::CPlayList playlist = g_playlistPlayer.GetPlaylist(pMsg->dwParam1); CFileItemList *list = (CFileItemList *)pMsg->lpVoid; for (int i = 0; i < playlist.size(); i++) list->Add(CFileItemPtr(new CFileItem(*playlist[i]))); } break; case TMSG_PLAYLISTPLAYER_SWAP: if (pMsg->lpVoid) { vector<int> *indexes = (vector<int> *)pMsg->lpVoid; if (indexes->size() == 2) g_playlistPlayer.Swap(pMsg->dwParam1, indexes->at(0), indexes->at(1)); delete indexes; } break; // Window messages below here... case TMSG_DIALOG_DOMODAL: //doModel of window { CGUIDialog* pDialog = (CGUIDialog*)g_windowManager.GetWindow(pMsg->dwParam1); if (!pDialog) return ; pDialog->DoModal(); } break; case TMSG_NETWORKMESSAGE: { g_application.getNetwork().NetworkMessage((CNetwork::EMESSAGE)pMsg->dwParam1, (int)pMsg->dwParam2); } break; case TMSG_GUI_DO_MODAL: { CGUIDialog *pDialog = (CGUIDialog *)pMsg->lpVoid; if (pDialog) pDialog->DoModal((int)pMsg->dwParam1, pMsg->strParam); } break; case TMSG_GUI_SHOW: { CGUIDialog *pDialog = (CGUIDialog *)pMsg->lpVoid; if (pDialog) pDialog->Show(); } break; case TMSG_GUI_WINDOW_CLOSE: { CGUIWindow *window = (CGUIWindow *)pMsg->lpVoid; if (window) window->Close(pMsg->dwParam2 & 0x1 ? true : false, pMsg->dwParam1, pMsg->dwParam2 & 0x2 ? true : false); } break; case TMSG_GUI_ACTIVATE_WINDOW: { g_windowManager.ActivateWindow(pMsg->dwParam1, pMsg->params, pMsg->dwParam2 > 0); } break; case TMSG_GUI_ADDON_DIALOG: { if (pMsg->lpVoid) { // TODO: This is ugly - really these python dialogs should just be normal XBMC dialogs ((ADDON::CGUIAddonWindowDialog *) pMsg->lpVoid)->Show_Internal(pMsg->dwParam2 > 0); } } break; case TMSG_GUI_PYTHON_DIALOG: { if (pMsg->lpVoid) { // TODO: This is ugly - really these python dialogs should just be normal XBMC dialogs if (pMsg->dwParam1) ((CGUIPythonWindowXMLDialog *)pMsg->lpVoid)->Show_Internal(pMsg->dwParam2 > 0); else ((CGUIPythonWindowDialog *)pMsg->lpVoid)->Show_Internal(pMsg->dwParam2 > 0); } } break; case TMSG_GUI_ACTION: { if (pMsg->lpVoid) { CAction *action = (CAction *)pMsg->lpVoid; if (pMsg->dwParam1 == WINDOW_INVALID) g_application.OnAction(*action); else { CGUIWindow *pWindow = g_windowManager.GetWindow(pMsg->dwParam1); if (pWindow) pWindow->OnAction(*action); else CLog::Log(LOGWARNING, "Failed to get window with ID %i to send an action to", pMsg->dwParam1); } delete action; } } break; case TMSG_GUI_MESSAGE: { if (pMsg->lpVoid) { CGUIMessage *message = (CGUIMessage *)pMsg->lpVoid; g_windowManager.SendMessage(*message, pMsg->dwParam1); delete message; } } break; case TMSG_GUI_INFOLABEL: { if (pMsg->lpVoid) { vector<CStdString> *infoLabels = (vector<CStdString> *)pMsg->lpVoid; for (unsigned int i = 0; i < pMsg->params.size(); i++) infoLabels->push_back(g_infoManager.GetLabel(g_infoManager.TranslateString(pMsg->params[i]))); } } break; case TMSG_GUI_INFOBOOL: { if (pMsg->lpVoid) { vector<bool> *infoLabels = (vector<bool> *)pMsg->lpVoid; for (unsigned int i = 0; i < pMsg->params.size(); i++) infoLabels->push_back(g_infoManager.EvaluateBool(pMsg->params[i])); } } break; case TMSG_CALLBACK: { ThreadMessageCallback *callback = (ThreadMessageCallback*)pMsg->lpVoid; callback->callback(callback->userptr); } break; case TMSG_VOLUME_SHOW: { CAction action((int)pMsg->dwParam1); g_application.ShowVolumeBar(&action); } break; case TMSG_SPLASH_MESSAGE: { if (g_application.GetSplash()) g_application.GetSplash()->Show(pMsg->strParam); } break; case TMSG_DISPLAY_SETUP: { *((bool*)pMsg->lpVoid) = g_application.InitWindow(); g_application.ReloadSkin(); } break; case TMSG_DISPLAY_DESTROY: { *((bool*)pMsg->lpVoid) = g_application.DestroyWindow(); } break; case TMSG_UPDATE_CURRENT_ITEM: { CFileItem* item = (CFileItem*)pMsg->lpVoid; if (!item) return; if (pMsg->dwParam1 == 1 && item->HasMusicInfoTag()) // only grab music tag g_infoManager.SetCurrentSongTag(*item->GetMusicInfoTag()); else if (pMsg->dwParam1 == 2 && item->HasVideoInfoTag()) // only grab video tag g_infoManager.SetCurrentVideoTag(*item->GetVideoInfoTag()); else g_infoManager.SetCurrentItem(*item); delete item; break; } } }