|
|
|
@ -34,6 +34,7 @@ CPlayer* CPlayerWinamp::c_Player = NULL;
|
|
|
|
|
CPlayerWinamp::CPlayerWinamp(WINAMPTYPE type) : CPlayer(),
|
|
|
|
|
m_Window(),
|
|
|
|
|
m_UseUnicodeAPI(false),
|
|
|
|
|
m_PlayingStream(false),
|
|
|
|
|
m_WinampType(type),
|
|
|
|
|
m_WinampHandle(),
|
|
|
|
|
m_WinampAddress()
|
|
|
|
@ -140,153 +141,180 @@ void CPlayerWinamp::UpdateData()
|
|
|
|
|
|
|
|
|
|
WCHAR wBuffer[MAX_PATH];
|
|
|
|
|
char cBuffer[MAX_PATH];
|
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
|
|
if (m_UseUnicodeAPI)
|
|
|
|
|
{
|
|
|
|
|
ret = ReadProcessMemory(m_WinampHandle, m_WinampAddress, &wBuffer, sizeof(wBuffer), NULL);
|
|
|
|
|
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);
|
|
|
|
|
ret = ReadProcessMemory(m_WinampHandle, address, &cBuffer, sizeof(cBuffer), NULL);
|
|
|
|
|
mbstowcs(wBuffer, cBuffer, MAX_PATH);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
|
{
|
|
|
|
|
LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: Failed to read Winamp memory (file).");
|
|
|
|
|
return;
|
|
|
|
|
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_Rating = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETRATING);
|
|
|
|
|
m_Duration = SendMessage(m_Window, WM_WA_IPC, 1, IPC_GETOUTPUTTIME);
|
|
|
|
|
m_PlayingStream = (m_FilePath.find(L"://") != std::wstring::npos);
|
|
|
|
|
|
|
|
|
|
TagLib::FileRef fr(wBuffer);
|
|
|
|
|
if (!fr.isNull() && fr.tag())
|
|
|
|
|
if (!m_PlayingStream)
|
|
|
|
|
{
|
|
|
|
|
m_Rating = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETRATING);
|
|
|
|
|
m_Duration = SendMessage(m_Window, WM_WA_IPC, 1, IPC_GETOUTPUTTIME);
|
|
|
|
|
|
|
|
|
|
TagLib::FileRef fr(wBuffer);
|
|
|
|
|
TagLib::Tag* tag = fr.tag();
|
|
|
|
|
m_Artist = tag->artist().toWString();
|
|
|
|
|
m_Album = tag->album().toWString();
|
|
|
|
|
m_Title = tag->title().toWString();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// TagLib couldn't parse the file, try title instead
|
|
|
|
|
if (m_UseUnicodeAPI)
|
|
|
|
|
if (tag)
|
|
|
|
|
{
|
|
|
|
|
LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_PLAYING_TITLE);
|
|
|
|
|
ret = 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, m_WinampAddress, &cBuffer, sizeof(cBuffer), NULL);
|
|
|
|
|
ret = mbstowcs(wBuffer, cBuffer, MAX_PATH);
|
|
|
|
|
}
|
|
|
|
|
m_Artist = tag->artist().toWString();
|
|
|
|
|
m_Album = tag->album().toWString();
|
|
|
|
|
m_Title = tag->title().toWString();
|
|
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
|
{
|
|
|
|
|
LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: Failed to read Winamp memory (title).");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::wstring title = wBuffer;
|
|
|
|
|
std::wstring::size_type pos = title.find(L". ");
|
|
|
|
|
if (pos != std::wstring::npos && pos < 5)
|
|
|
|
|
{
|
|
|
|
|
pos += 2; // Skip ". "
|
|
|
|
|
title.erase(0, pos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pos = title.find(L" - ");
|
|
|
|
|
if (pos != std::wstring::npos)
|
|
|
|
|
{
|
|
|
|
|
m_Title.assign(title, 0, pos);
|
|
|
|
|
pos += 3; // Skip " - "
|
|
|
|
|
m_Artist.assign(title, pos, title.length() - pos);
|
|
|
|
|
m_Album.clear();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_Title = title;
|
|
|
|
|
m_Artist.clear();
|
|
|
|
|
m_Album.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_HasLyricsMeasure)
|
|
|
|
|
{
|
|
|
|
|
FindLyrics();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Find cover if needed
|
|
|
|
|
if (m_HasCoverMeasure)
|
|
|
|
|
{
|
|
|
|
|
m_CoverPath = GetCacheFile();
|
|
|
|
|
if (!CCover::GetCached(m_CoverPath) &&
|
|
|
|
|
!CCover::GetEmbedded(fr, m_CoverPath))
|
|
|
|
|
{
|
|
|
|
|
std::wstring trackFolder = CCover::GetFileFolder(m_FilePath);
|
|
|
|
|
|
|
|
|
|
if (!m_Album.empty())
|
|
|
|
|
if (m_HasLyricsMeasure)
|
|
|
|
|
{
|
|
|
|
|
// 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)
|
|
|
|
|
FindLyrics();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (m_HasLyricsMeasure)
|
|
|
|
|
{
|
|
|
|
|
m_Lyrics.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Find cover if needed
|
|
|
|
|
if (m_HasCoverMeasure)
|
|
|
|
|
{
|
|
|
|
|
m_CoverPath = GetCacheFile();
|
|
|
|
|
if (!CCover::GetCached(m_CoverPath) &&
|
|
|
|
|
(tag && !CCover::GetEmbedded(fr, m_CoverPath)))
|
|
|
|
|
{
|
|
|
|
|
std::wstring trackFolder = CCover::GetFileFolder(m_FilePath);
|
|
|
|
|
|
|
|
|
|
if (!m_Album.empty())
|
|
|
|
|
{
|
|
|
|
|
// Replace reserved chars according to Winamp specs
|
|
|
|
|
switch (file[pos])
|
|
|
|
|
// 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)
|
|
|
|
|
{
|
|
|
|
|
case L'?':
|
|
|
|
|
case L'*':
|
|
|
|
|
case L'|':
|
|
|
|
|
file[pos] = L'_';
|
|
|
|
|
break;
|
|
|
|
|
// 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'/':
|
|
|
|
|
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;
|
|
|
|
|
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(file, trackFolder, m_CoverPath))
|
|
|
|
|
if (!CCover::GetLocal(L"cover", trackFolder, m_CoverPath) &&
|
|
|
|
|
!CCover::GetLocal(L"folder", trackFolder, m_CoverPath))
|
|
|
|
|
{
|
|
|
|
|
// %album% art file found
|
|
|
|
|
return;
|
|
|
|
|
// Nothing found
|
|
|
|
|
m_CoverPath.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!CCover::GetLocal(L"cover", trackFolder, m_CoverPath) &&
|
|
|
|
|
!CCover::GetLocal(L"folder", trackFolder, m_CoverPath))
|
|
|
|
|
{
|
|
|
|
|
// Nothing found
|
|
|
|
|
m_CoverPath.clear();
|
|
|
|
|
}
|
|
|
|
|
if (tag)
|
|
|
|
|
{
|
|
|
|
|
// Got metadata, return
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_Rating = 0;
|
|
|
|
|
m_Duration = 0;
|
|
|
|
|
|
|
|
|
|
if (m_HasCoverMeasure)
|
|
|
|
|
{
|
|
|
|
|
m_CoverPath.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (!m_PlayingStream)
|
|
|
|
|
{
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|