/* ** Called during each update of the main measure. ** */ void PlayerSpotify::UpdateData() { if (m_Initialized || CheckWindow()) { // Parse title and artist from window title WCHAR buffer[256]; if (GetWindowText(m_Window, buffer, 256) > 10) { std::wstring title = &buffer[10]; // Skip "Spotify - " std::wstring::size_type pos = title.find(L" \u2013 "); if (pos != std::wstring::npos) { std::wstring artist(title, 0, pos); pos += 3; // Skip " - " std::wstring track(title, pos); if (track != m_Title || artist != m_Artist) { m_State = STATE_PLAYING; m_Title = track; m_Artist = artist; ++m_TrackCount; if (m_Measures & MEASURE_LYRICS) { FindLyrics(); } } return; } } else if (IsWindow(m_Window)) { m_State = STATE_PAUSED; } else { ClearData(); m_Initialized = false; } } }
/* ** Called during each update of the main measure. ** */ void CPlayerWMP::UpdateData() { if (m_Initialized) { // Get the volume long volume; m_ISettings->get_volume(&volume); m_Volume = (UINT)volume; if (m_State != STATE_STOPPED) { double position; m_IControls->get_currentPosition(&position); m_Position = (UINT)position; } if (m_TrackChanged) { m_TrackChanged = false; CComPtr<IWMPMedia> spMedia; m_IPlayer->get_currentMedia(&spMedia); if (spMedia) { BSTR val; spMedia->getItemInfo(CComBSTR(L"Artist"), &val); m_Artist = val; spMedia->getItemInfo(CComBSTR(L"Title"), &val); m_Title = val; spMedia->getItemInfo(CComBSTR(L"Album"), &val); m_Album = val; spMedia->getItemInfo(CComBSTR(L"UserRating"), &val); int rating = _wtoi(val); if (rating > 75) { m_Rating = 5; } else if (rating > 50) { m_Rating = 4; } else if (rating > 25) { m_Rating = 3; } else if (rating > 1) { m_Rating = 2; } else { m_Rating = rating; } spMedia->getItemInfo(CComBSTR(L"WM/TrackNumber"), &val); m_Number = (UINT)_wtoi(val); spMedia->getItemInfo(CComBSTR(L"WM/Year"), &val); m_Year = (UINT)_wtoi(val); double duration; spMedia->get_duration(&duration); m_Duration = (UINT)duration; BSTR url; spMedia->get_sourceURL(&url); std::wstring targetPath = url; if (targetPath != m_FilePath) { ++m_TrackCount; m_FilePath = targetPath; // Find cover if needed // TODO: Fix temp solution if (m_Measures & MEASURE_COVER || m_InstanceCount == 0) { spMedia->getItemInfo(CComBSTR(L"WM/WMCollectionID"), &val); targetPath.resize(targetPath.find_last_of(L'\\') + 1); targetPath += L"AlbumArt_"; targetPath += val; targetPath += L"_Large.jpg"; if (_waccess(targetPath.c_str(), 0) == 0) { m_CoverPath = targetPath; } else { FindCover(); } } if (m_Measures & MEASURE_LYRICS) { FindLyrics(); } } } } } else { DWORD time = GetTickCount(); // Try to find WMP window every 5 seconds if (m_LastCheckTime = 0 || time - m_LastCheckTime > 5000) { m_LastCheckTime = time; if (FindWindow(L"WMPlayerApp", NULL)) { Initialize(); } } } }
/* ** Called by iTunes event handler on track change. ** */ void PlayerITunes::OnTrackChange() { IITTrack* track; HRESULT hr = m_iTunes->get_CurrentTrack(&track); if (SUCCEEDED(hr) && track) { BSTR tmpStr; long tmpVal; // Get metadata track->get_Artist(&tmpStr); tmpStr ? (m_Artist = tmpStr) : m_Artist.clear(); track->get_Name(&tmpStr); tmpStr ? (m_Title = tmpStr) : m_Title.clear(); track->get_Album(&tmpStr); tmpStr ? (m_Album = tmpStr) : m_Album.clear(); track->get_Genre(&tmpStr);; tmpStr ? (m_Genre = tmpStr) : m_Genre.clear(); track->get_Duration(&tmpVal); m_Duration = (UINT)tmpVal; // Rating is 0 - 100, divide to 0 - 5 track->get_Rating(&tmpVal); tmpVal /= 20L; m_Rating = (UINT)tmpVal; track->get_TrackNumber(&tmpVal); m_Number = (UINT)tmpVal; track->get_Year(&tmpVal); m_Year = (UINT)tmpVal; IITPlaylist* playlist; hr = track->get_Playlist(&playlist); if (SUCCEEDED(hr)) { ITPlaylistRepeatMode repeat; hr = playlist->get_SongRepeat(&repeat); if (SUCCEEDED(hr)) { m_Repeat = repeat != ITPlaylistRepeatModeOff; } playlist->Release(); } IITFileOrCDTrack* file; hr = track->QueryInterface(&file); if (SUCCEEDED(hr)) { file->get_Location(&tmpStr); file->Release(); if (tmpStr && wcscmp(tmpStr, m_FilePath.c_str()) != 0) { ++m_TrackCount; m_FilePath = tmpStr; if (m_Measures & MEASURE_COVER) { m_CoverPath.clear(); // Check for embedded art through iTunes interface IITArtworkCollection* artworkCollection; hr = track->get_Artwork(&artworkCollection); if (SUCCEEDED(hr)) { long count; artworkCollection->get_Count(&count); if (count > 0) { IITArtwork* artwork; hr = artworkCollection->get_Item(1, &artwork); if (SUCCEEDED(hr)) { _bstr_t coverPath = m_TempCoverPath.c_str(); hr = artwork->SaveArtworkToFile(coverPath); if (SUCCEEDED(hr)) { m_CoverPath = m_TempCoverPath; } artwork->Release(); } } artworkCollection->Release(); } } if (m_Measures & MEASURE_LYRICS) { FindLyrics(); } } } track->Release(); } else { ClearData(false); } }
/* ** UpdateData ** ** Called during each update of the main measure. ** */ void CPlayerVLC::UpdateData() { xml_.clear(); xml_.addData(QString::fromStdWString(CInternet::DownloadUrl(L"http://127.0.0.1:"+m_Port+L"/requests/status.xml", CP_UTF8))); QStringList currentPosition; while (!xml_.atEnd()) { xml_.readNext(); if (xml_.isStartElement()) { currentPosition.push_back(xml_.name().toString()); } else if (xml_.isEndElement()) { currentPosition.pop_back(); } else if (xml_.isCharacters() && !xml_.isWhitespace()) { QString nodeAddress = currentPosition.join("."); QString nodeValue = xml_.text().toString(); if(nodeAddress == "root.information.meta-information.artist") m_Artist = nodeValue.toStdWString(); if(nodeAddress == "root.information.meta-information.title") m_Title = nodeValue.toStdWString(); if(nodeAddress == "root.information.meta-information.album") m_Album = nodeValue.toStdWString(); if(nodeAddress == "root.length") m_Duration = nodeValue.toInt(); if(nodeAddress == "root.time") m_Position = nodeValue.toInt(); if(nodeAddress == "root.volume") m_Volume = nodeValue.toInt(); if(nodeAddress == "root.state") { if(nodeValue == "paused") m_State = PLAYER_PAUSED; if(nodeValue == "playing") m_State = PLAYER_PLAYING; if(nodeValue == "stop") m_State = PLAYER_STOPPED; } if(nodeAddress == "root.random") m_Shuffle = (nodeValue.toInt()==1); if(nodeAddress == "root.repeat") m_Repeat = (nodeValue.toInt()==1); } } if (xml_.error() && xml_.error() != QXmlStreamReader::PrematureEndOfDocumentError) { qWarning() << "XML ERROR:" << xml_.lineNumber() << ": " << xml_.errorString(); } m_CoverPath.clear(); m_FilePath.clear(); if((m_Measures & MEASURE_COVER) && m_State != PLAYER_STOPPED) { xml_.clear(); xml_.addData(QString::fromStdWString(CInternet::DownloadUrl(L"http://127.0.0.1:"+m_Port+L"/requests/playlist.xml", CP_UTF8))); while (!xml_.atEnd()) { xml_.readNext(); if (xml_.isStartElement()) { QString nodeName = xml_.name().toString(); if(currentPosition.count()!=0 && xml_.attributes().value("name")!="" && nodeName=="node") nodeName = QString("%1:%2").arg(nodeName).arg(xml_.attributes().value("name").toString()); if(currentPosition.count()!=0 && xml_.attributes().value("current")!="" && nodeName=="leaf") nodeName = QString("%1:%2").arg(nodeName).arg(xml_.attributes().value("current").toString()); currentPosition.push_back(nodeName); if(currentPosition.join(".") == "node.node:Playlist.leaf:current") m_FilePath = QUrl::fromEncoded(xml_.attributes().value("uri").toString().toUtf8()).toString().remove("file:///").toStdWString(); } else if (xml_.isEndElement()) currentPosition.pop_back(); else if (xml_.isCharacters() && !xml_.isWhitespace()) { QString nodeAddress = currentPosition.join("."); QString nodeValue = xml_.text().toString(); if(nodeAddress == "node.node:Playlist.leaf:current.art_url") m_CoverPath = QUrl::fromEncoded(nodeValue.toUtf8()).toString().remove("file:///").toStdWString(); } } if (xml_.error() && xml_.error() != QXmlStreamReader::PrematureEndOfDocumentError) { qWarning() << "XML ERROR:" << xml_.lineNumber() << ": " << xml_.errorString(); } } if (m_Measures & MEASURE_LYRICS) { FindLyrics(); } }
/* ** Called during each update of the main measure. ** */ void CPlayerAIMP::UpdateData() { if (!m_Initialized) { if (m_LastTitleSize != 0) { m_LastFileSize = 0; m_LastTitleSize = 0; } if (!CheckWindow()) return; } // If initialized m_State = (StateType)SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_Player); if (m_State == STATE_STOPPED) { // Make sure AIMP is still active if (!IsWindow(m_Window)) { m_Initialized = false; ClearData(); if (m_FileMap) UnmapViewOfFile(m_FileMap); if (m_FileMapHandle) CloseHandle(m_FileMapHandle); } else if (m_State != STATE_STOPPED) { ClearData(false); m_LastFileSize = 0; m_LastTitleSize = 0; } // Don't continue if AIMP has quit or is stopped return; } m_Position = SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_POS); m_Volume = SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_VOLUME); AIMP2FileInfo* info = (AIMP2FileInfo*)m_FileMap; if (info->cbSizeOf > 0 && info->nFileSize != m_LastFileSize || // Avoid reading the same file info->nTitleLen != m_LastTitleSize) { m_LastFileSize = info->nFileSize; m_LastTitleSize = info->nTitleLen; // 44 is sizeof(AIMP2FileInfo) / 2 (due to WCHAR being 16-bit). // Written explicitly due to size differences in 32bit/64bit. LPCTSTR stringData = (LPCTSTR)m_FileMap; stringData += 44; m_Album.assign(stringData, info->nAlbumLen); stringData += info->nAlbumLen; m_Artist.assign(stringData, info->nArtistLen); stringData += info->nArtistLen; stringData += info->nDateLen; std::wstring filepath(stringData, info->nFileNameLen); stringData += info->nFileNameLen; stringData += info->nGenreLen; m_Title.assign(stringData, info->nTitleLen); m_Duration = info->nDuration / 1000; m_Number = (UINT)info->nTrackID; m_Shuffle = (bool)SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_SHUFFLE); m_Repeat = (bool)SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_REPEAT); // Get rating through the AIMP Winamp API m_Rating = SendMessage(m_WinampWindow, WM_WA_IPC, 0, IPC_GETRATING); if (filepath != m_FilePath) { m_FilePath = filepath; ++m_TrackCount; if (m_Measures & MEASURE_COVER) FindCover(); if (m_Measures & MEASURE_LYRICS) FindLyrics(); } } }
/* ** Called during each update of the main measure. ** */ void CPlayerWinamp::UpdateData() { if (m_Initialized || CheckWindow()) { int playing = SendMessage(m_Window, WM_WA_IPC, 0, IPC_ISPLAYING); if (playing == 0) { // Make sure Winamp is still active if (!IsWindow(m_Window)) { m_Initialized = false; ClearData(); if (m_WinampHandle) CloseHandle(m_WinampHandle); } else if (m_State != STATE_STOPPED) { ClearData(false); } // Don't continue if Winamp has quit or is stopped return; } else { m_State = (playing == 1) ? STATE_PLAYING : STATE_PAUSED; m_Position = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETOUTPUTTIME) / 1000; // ms to secs m_Volume = (SendMessage(m_Window, WM_WA_IPC, -666, IPC_SETVOLUME) * 100) / 255; // 0 - 255 to 0 - 100 } WCHAR wBuffer[MAX_PATH]; char cBuffer[MAX_PATH]; if (m_UseUnicodeAPI) { if (!ReadProcessMemory(m_WinampHandle, m_WinampAddress, &wBuffer, sizeof(wBuffer), NULL)) { // Failed to read memory return; } } else { // MediaMonkey doesn't support wide IPC messages int pos = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETLISTPOS); LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, pos, IPC_GETPLAYLISTFILE); if (!ReadProcessMemory(m_WinampHandle, address, &cBuffer, sizeof(cBuffer), NULL)) { // Failed to read memory return; } mbstowcs(wBuffer, cBuffer, MAX_PATH); } if (wcscmp(wBuffer, m_FilePath.c_str()) != 0) { ++m_TrackCount; m_FilePath = wBuffer; m_PlayingStream = (m_FilePath.find(L"://") != std::wstring::npos); if (!m_PlayingStream) { int duration = SendMessage(m_Window, WM_WA_IPC, 1, IPC_GETOUTPUTTIME); m_Duration = (duration != -1) ? duration : 0; m_Rating = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETRATING); m_Shuffle = (bool)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_SHUFFLE); m_Repeat = (bool)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_REPEAT); TagLib::FileRef fr(wBuffer, false); TagLib::Tag* tag = fr.tag(); if (tag) { m_Artist = tag->artist().toWString(); m_Album = tag->album().toWString(); m_Title = tag->title().toWString(); m_Number = tag->track(); m_Year = tag->year(); if (m_Measures & MEASURE_LYRICS) { FindLyrics(); } } else if (m_Measures & MEASURE_LYRICS) { m_Lyrics.clear(); } // Find cover if needed if (m_Measures & MEASURE_COVER) { if (tag && CCover::GetEmbedded(fr, m_TempCoverPath)) { // Got everything, return m_CoverPath = m_TempCoverPath; return; } std::wstring trackFolder = CCover::GetFileFolder(m_FilePath); if (tag && !m_Album.empty()) { // Winamp stores covers usually as %album%.jpg std::wstring file = m_Album; std::wstring::size_type end = file.length(); for (std::wstring::size_type pos = 0; pos < end; ++pos) { // Replace reserved chars according to Winamp specs switch (file[pos]) { case L'?': case L'*': case L'|': file[pos] = L'_'; break; case L'/': case L'\\': case L':': file[pos] = L'-'; break; case L'\"': file[pos] = L'\''; break; case L'<': file[pos] = L'('; break; case L'>': file[pos] = L')'; break; } } if (CCover::GetLocal(file, trackFolder, m_CoverPath)) { // %album% art file found return; } } if (!CCover::GetLocal(L"cover", trackFolder, m_CoverPath) && !CCover::GetLocal(L"folder", trackFolder, m_CoverPath)) { // Nothing found m_CoverPath.clear(); } } if (tag) { return; } } else { m_Rating = 0; m_Duration = 0; m_CoverPath.clear(); } } else if (!m_PlayingStream) { if (m_Duration == 0) { int duration = SendMessage(m_Window, WM_WA_IPC, 1, IPC_GETOUTPUTTIME); m_Duration = (duration != -1) ? duration : 0; } return; } // TagLib couldn't parse the file or Winamp is playing a stream, try to get title if (m_UseUnicodeAPI) { LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_PLAYING_TITLE); ReadProcessMemory(m_WinampHandle, address, &wBuffer, sizeof(wBuffer), NULL); } else { int pos = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETLISTPOS); LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, pos, IPC_GETPLAYLISTTITLE); ReadProcessMemory(m_WinampHandle, address, &cBuffer, sizeof(cBuffer), NULL); mbstowcs(wBuffer, cBuffer, MAX_PATH); } std::wstring title = wBuffer; std::wstring::size_type pos = title.find(L" - "); if (pos != std::wstring::npos) { m_Artist.assign(title, 0, pos); pos += 3; // Skip " - " m_Title.assign(title, pos, title.length() - pos); m_Album.clear(); if (m_PlayingStream) { // Remove crap from title if playing radio pos = m_Title.find(L" ("); if (pos != std::wstring::npos) { m_Title.resize(pos); } } } else { m_Title = title; m_Artist.clear(); m_Album.clear(); } } }