diff --git a/Plugins/PluginNowPlaying/Cover.cpp b/Plugins/PluginNowPlaying/Cover.cpp
index 46cea44c..1d692855 100644
--- a/Plugins/PluginNowPlaying/Cover.cpp
+++ b/Plugins/PluginNowPlaying/Cover.cpp
@@ -19,76 +19,25 @@
#include "StdAfx.h"
#include "Cover.h"
-extern std::wstring g_CachePath;
-
/*
-** GetCover
-**
-** Default implementation for getting cover.
-**
-*/
-void CCover::GetCover(const std::wstring& artist, const std::wstring& title, const std::wstring& file, std::wstring& target)
-{
- if (!GetCachedCover(artist, title, target))
- {
- TagLib::FileRef fr(file.c_str());
- if (fr.isNull() || !fr.tag() || !GetEmbeddedCover(fr, target))
- {
- std::wstring trackFolder = GetFileFolder(file);
-
- if (!GetLocalCover(L"cover", trackFolder, target) &&
- !GetLocalCover(L"folder", trackFolder, target))
- {
- // Nothing found
- target.clear();
- }
- }
- }
-}
-
-/*
-** GetCachedArt
+** GetCached
**
** Checks if cover art is in cache.
**
*/
-bool CCover::GetCachedCover(const std::wstring& artist, const std::wstring& title, std::wstring& target)
+bool CCover::GetCached(std::wstring& path)
{
- target = g_CachePath;
- if (artist.empty() || title.empty())
- {
- target += L"temp.art";
- }
- else
- {
- // Otherwise, save it as "Artist - Title.art"
- std::wstring name = artist;
- name += L" - ";
- name += title;
-
- // Replace reserved chars with _
- std::wstring::size_type pos = 0;
- while ((pos = name.find_first_of(L"\\/:*?\"<>|", pos)) != std::wstring::npos) name[pos] = L'_';
-
- target += name;
- target += L".art";
- if (_waccess(target.c_str(), 0) == 0)
- {
- // Art found in cache
- return true;
- }
- }
-
- return false;
+ path += L".art";
+ return (_waccess(path.c_str(), 0) == 0) ? true : false;
}
/*
-** GetLocalArt
+** GetLocal
**
** Attemps to find local cover art in various formats.
**
*/
-bool CCover::GetLocalCover(std::wstring filename, const std::wstring& folder, std::wstring& target)
+bool CCover::GetLocal(std::wstring filename, const std::wstring& folder, std::wstring& target)
{
std::wstring testPath = folder;
testPath += filename;
@@ -117,12 +66,12 @@ bool CCover::GetLocalCover(std::wstring filename, const std::wstring& folder, st
}
/*
-** GetEmbeddedArt
+** GetEmbedded
**
** Attempts to extract cover art from audio files.
**
*/
-bool CCover::GetEmbeddedCover(const TagLib::FileRef& fr, std::wstring& target)
+bool CCover::GetEmbedded(const TagLib::FileRef& fr, std::wstring& target)
{
bool found = false;
diff --git a/Plugins/PluginNowPlaying/Cover.h b/Plugins/PluginNowPlaying/Cover.h
index 7f5da634..554d8a4c 100644
--- a/Plugins/PluginNowPlaying/Cover.h
+++ b/Plugins/PluginNowPlaying/Cover.h
@@ -19,6 +19,8 @@
#ifndef __COVER_H__
#define __COVER_H__
+// TagLib
+#include "fileref.h"
#include "apefile.h"
#include "apetag.h"
#include "asffile.h"
@@ -40,10 +42,9 @@
class CCover
{
public:
- static void GetCover(const std::wstring& artist, const std::wstring& title, const std::wstring& file, std::wstring& target);
- static bool GetCachedCover(const std::wstring& artist, const std::wstring& title, std::wstring& target);
- static bool GetLocalCover(std::wstring filename, const std::wstring& folder, std::wstring& target);
- static bool GetEmbeddedCover(const TagLib::FileRef& fr, std::wstring& target);
+ static bool GetCached(std::wstring& path);
+ static bool GetLocal(std::wstring filename, const std::wstring& folder, std::wstring& target);
+ static bool GetEmbedded(const TagLib::FileRef& fr, std::wstring& target);
static std::wstring GetFileFolder(const std::wstring& file);
private:
diff --git a/Plugins/PluginNowPlaying/Internet.cpp b/Plugins/PluginNowPlaying/Internet.cpp
new file mode 100644
index 00000000..765f3e9d
--- /dev/null
+++ b/Plugins/PluginNowPlaying/Internet.cpp
@@ -0,0 +1,281 @@
+/*
+ Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net)
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "StdAfx.h"
+#include "Internet.h"
+
+HINTERNET CInternet::c_NetHandle = NULL;
+
+/*
+** Initialize
+**
+** Initialize internet handle and crtical section.
+**
+*/
+void CInternet::Initialize()
+{
+ c_NetHandle = InternetOpen(L"Rainmeter NowPlaying.dll",
+ INTERNET_OPEN_TYPE_PRECONFIG,
+ NULL,
+ NULL,
+ 0);
+
+ if (!c_NetHandle)
+ {
+ LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: Unable to open net handle.");
+ }
+}
+
+/*
+** Finalize
+**
+** Close handles and delete critical section.
+**
+*/
+void CInternet::Finalize()
+{
+ if (c_NetHandle) InternetCloseHandle(c_NetHandle);
+}
+
+/*
+** DownloadUrl
+**
+** Downloads given url and returns it as a string.
+**
+*/
+std::wstring CInternet::DownloadUrl(const std::wstring& url, int codepage)
+{
+ std::wstring result;
+ DWORD flags = INTERNET_FLAG_RESYNCHRONIZE;
+ HINTERNET hUrlDump = InternetOpenUrl(c_NetHandle, url.c_str(), NULL, NULL, flags, 0);
+
+ if (!hUrlDump)
+ {
+ LSLog(LOG_DEBUG, L"Rainmeter", L"NowPlayingPlguin: Unable to open internet file.");
+ return result;
+ }
+
+ // Allocate the buffer.
+ const int CHUNK_SIZE = 8192;
+ BYTE* lpData = new BYTE[CHUNK_SIZE];
+ BYTE* lpOutPut;
+ BYTE* lpHolding = NULL;
+ int nCounter = 1;
+ int nBufferSize;
+ DWORD dwDataSize = 0;
+ DWORD dwSize = 0;
+
+ do
+ {
+ // Read the data.
+ if (!InternetReadFile(hUrlDump, (LPVOID)lpData, CHUNK_SIZE, &dwSize))
+ {
+ LSLog(LOG_DEBUG, L"Rainmeter", L"NowPlayingPlguin: Unable to read internet file.");
+ break;
+ }
+ else
+ {
+ // Check if all of the data has been read. This should
+ // never get called on the first time through the loop.
+ if (dwSize == 0)
+ {
+ break;
+ }
+
+ // Determine the buffer size to hold the new data and the data
+ // already written (if any).
+ nBufferSize = dwDataSize + dwSize;
+
+ // Allocate the output buffer.
+ lpOutPut = new BYTE[nBufferSize + 2];
+
+ // Make sure the buffer is not the initial buffer.
+ if (lpHolding != NULL)
+ {
+ // Copy the data in the holding buffer.
+ memcpy(lpOutPut, lpHolding, dwDataSize);
+
+ // Delete the old buffer
+ delete [] lpHolding;
+
+ lpHolding = lpOutPut;
+ lpOutPut = lpOutPut + dwDataSize;
+ }
+ else
+ {
+ lpHolding = lpOutPut;
+ }
+
+ // Copy the data buffer.
+ memcpy(lpOutPut, lpData, dwSize);
+
+ dwDataSize += dwSize;
+
+ // End with double null
+ lpOutPut[dwSize] = 0;
+ lpOutPut[dwSize + 1] = 0;
+
+ // Increment the number of buffers read.
+ ++nCounter;
+
+ // Clear the buffer
+ memset(lpData, 0, CHUNK_SIZE);
+ }
+ } while (true);
+
+ InternetCloseHandle(hUrlDump);
+
+ delete [] lpData;
+
+ if (lpHolding)
+ {
+ result = ConvertToWide((LPCSTR)lpHolding, codepage);
+ delete [] lpHolding;
+ }
+
+ return result;
+}
+
+/*
+** EncodeUrl
+**
+** Encode reserved characters.
+**
+*/
+std::wstring CInternet::EncodeUrl(const std::wstring& url)
+{
+ // Based on http://www.zedwood.com/article/111/cpp-urlencode-function
+ static const std::wstring url_chars = L" !*'();:@&=+$,/?#[]";
+ std::wstring ret;
+
+ for (size_t i = 0, max = url.length(); i < max; ++i)
+ {
+ if (url_chars.find_first_of(url[i]) != std::string::npos)
+ {
+ // If reserved character
+ ret.append(L"%");
+ WCHAR buffer[3];
+ _snwprintf_s(buffer, 3, L"%.2X", url[i]);
+ ret.append(buffer);
+ }
+ else
+ {
+ ret.push_back(url[i]);
+ }
+ }
+ return ret;
+}
+
+/*
+** DecodeReferences
+**
+** Decodes numeric references.
+**
+*/
+void CInternet::DecodeReferences(std::wstring& str)
+{
+ // From WebParser.cpp
+ std::wstring::size_type start = 0;
+
+ while ((start = str.find(L'&', start)) != std::wstring::npos)
+ {
+ std::wstring::size_type end, pos;
+
+ if ((end = str.find(L';', start)) == std::wstring::npos) break;
+ pos = start + 1;
+
+ if (pos == end) // &; - skip
+ {
+ start = end + 1;
+ continue;
+ }
+ else if ((end - pos) > 10) // name (or number) is too long
+ {
+ ++start;
+ continue;
+ }
+
+ if (str[pos] == L'#') // Numeric character reference
+ {
+ if (++pos == end) // - skip
+ {
+ start = end + 1;
+ continue;
+ }
+
+ int base;
+ if (str[pos] == L'x' || str[pos] == L'X')
+ {
+ if (++pos == end) // or - skip
+ {
+ start = end + 1;
+ continue;
+ }
+ base = 16;
+ }
+ else
+ {
+ base = 10;
+ }
+
+ std::wstring num(str, pos, end - pos);
+ WCHAR* pch = NULL;
+ errno = 0;
+ long ch = wcstol(num.c_str(), &pch, base);
+ if (pch == NULL || *pch != L'\0' || errno == ERANGE || ch <= 0 || ch >= 0xFFFE) // invalid character
+ {
+ start = pos;
+ continue;
+ }
+ str.replace(start, end - start + 1, 1, (WCHAR)ch);
+ ++start;
+ }
+ else // Character entity reference
+ {
+ start = end + 1;
+ continue;
+ }
+ }
+}
+
+/*
+** ConvertToWide
+**
+** Convert from multibyte ti wide string.
+**
+*/
+std::wstring CInternet::ConvertToWide(LPCSTR str, int codepage)
+{
+ std::wstring szWide;
+
+ if (str && *str)
+ {
+ int strLen = (int)strlen(str) + 1;
+ int bufLen = MultiByteToWideChar(codepage, 0, str, strLen, NULL, 0);
+ if (bufLen > 0)
+ {
+ WCHAR* wideSz = new WCHAR[bufLen];
+ wideSz[0] = 0;
+ MultiByteToWideChar(codepage, 0, str, strLen, wideSz, bufLen);
+ szWide = wideSz;
+ delete [] wideSz;
+ }
+ }
+
+ return szWide;
+}
diff --git a/Plugins/PluginNowPlaying/Internet.h b/Plugins/PluginNowPlaying/Internet.h
new file mode 100644
index 00000000..384d81e4
--- /dev/null
+++ b/Plugins/PluginNowPlaying/Internet.h
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net)
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __INTERNET_H__
+#define __INTERNET_H__
+
+class CInternet
+{
+public:
+ static void Initialize();
+ static void Finalize();
+
+ static std::wstring DownloadUrl(const std::wstring& url, int codepage);
+ static std::wstring EncodeUrl(const std::wstring& url);
+ static void DecodeReferences(std::wstring& str);
+ static std::wstring ConvertToWide(LPCSTR str, int codepage);
+
+private:
+ static HINTERNET c_NetHandle;
+};
+
+#endif
\ No newline at end of file
diff --git a/Plugins/PluginNowPlaying/Lyrics.cpp b/Plugins/PluginNowPlaying/Lyrics.cpp
new file mode 100644
index 00000000..a9f654e4
--- /dev/null
+++ b/Plugins/PluginNowPlaying/Lyrics.cpp
@@ -0,0 +1,204 @@
+/*
+ Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net)
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "StdAfx.h"
+#include "Player.h"
+#include "Internet.h"
+#include "Lyrics.h"
+
+/*
+** GetFromInternet
+**
+** Download lyrics from various serivces.
+**
+*/
+bool CLyrics::GetFromInternet(const std::wstring& artist, const std::wstring& title, std::wstring& out)
+{
+ std::wstring encArtist = CInternet::EncodeUrl(artist);
+ std::wstring encTitle = CInternet::EncodeUrl(title);
+
+ bool found = GetFromWikia(encArtist, encTitle, out) ||
+ GetFromLYRDB(encArtist, encTitle, out) ||
+ GetFromLetras(encArtist, encTitle, out);
+
+ return found;
+}
+
+/*
+** GetFromWikia
+**
+** Download lyrics from LyricWiki.
+**
+*/
+bool CLyrics::GetFromWikia(const std::wstring& artist, const std::wstring& title, std::wstring& data)
+{
+ bool ret = false;
+
+ std::wstring url = L"http://lyrics.wikia.com/api.php?func=getSong&fmt=json&artist=";
+ url += artist;
+ url += L"&song=";
+ url += title;
+
+ data = CInternet::DownloadUrl(url, CP_UTF8);
+ if (!data.empty())
+ {
+ // First we get the URL to the actual wiki page
+ std::wstring::size_type pos = data.find(L"http://");
+ if (pos != std::wstring::npos)
+ {
+ data.erase(0, pos);
+ pos = data.find(L"'");
+ url = data.substr(0, pos);
+
+ // Fetch the wiki page
+ data = CInternet::DownloadUrl(url, CP_UTF8);
+ if (!data.empty())
+ {
+ pos = data.find(L"'lyricbox'");
+ pos = data.find(L"", pos);
+ if (pos != std::wstring::npos)
+ {
+ // Get and decode lyrics
+ data.erase(0, pos);
+ pos = data.find(L"");
+ if (pos != std::wstring::npos)
+ {
+ // Skip unavailable lyrics
+ return ret;
+ }
+
+ while ((pos = data.find(L"
"), pos) != std::wstring::npos)
+ {
+ data.replace(pos, 6, L"\n");
+ }
+
+ // Get rid of all HTML tags
+ std::wstring::size_type len = 0;
+ while ((pos = data.find_first_of(L'<'), pos) != std::wstring::npos)
+ {
+ len = data.find_first_of(L'>', pos);
+ len -= pos;
+ data.erase(pos, ++len);
+ }
+
+ ret = true;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+/*
+** GetFromLYRDB
+**
+** Download lyrics from LYRDB.
+**
+*/
+bool CLyrics::GetFromLYRDB(const std::wstring& artist, const std::wstring& title, std::wstring& data)
+{
+ bool ret = false;
+
+ std::wstring query = artist;
+ query += L"|";
+ query += title;
+
+ // LYRDB doesn't like apostrophes
+ std::wstring::size_type pos = 0;
+ while ((pos = query.find(L"%27", pos)) != std::wstring::npos)
+ {
+ query.erase(pos, 3);
+ }
+
+ std::wstring url = L"http://webservices.lyrdb.com/lookup.php?q=";
+ url += query;
+ url += L"&for=match&agent=RainmeterNowPlaying";
+
+ data = CInternet::DownloadUrl(url, CP_ACP);
+ if (!data.empty())
+ {
+ pos = data.find(L"\\");
+ if (pos != std::wstring::npos)
+ {
+ // Grab the first match
+ url = L"http://webservices.lyrdb.com/getlyr.php?q=";
+ url += data.substr(0, pos);
+
+ data = CInternet::DownloadUrl(url, CP_ACP);
+ if (!data.empty())
+ {
+ ret = true;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/*
+** GetFromLetras
+**
+** Download lyrics from Letras.
+**
+*/
+bool CLyrics::GetFromLetras(const std::wstring& artist, const std::wstring& title, std::wstring& data)
+{
+ bool ret = false;
+
+ std::wstring url = L"http://letras.terra.com.br/winamp.php?musica=";
+ url += title;
+ url += L"&artista=";
+ url += artist;
+ data = CInternet::DownloadUrl(url, CP_ACP);
+ if (!data.empty())
+ {
+ std::wstring::size_type pos = data.find(L"\"letra\"");
+ pos = data.find(L"
", pos);
+ if (pos != std::wstring::npos)
+ {
+ pos += 3;
+ data.erase(0, pos);
+
+ pos = data.find(L"
");
+ data.resize(pos);
+
+ CInternet::DecodeReferences(data);
+
+ while ((pos = data.find(L"
"), pos) != std::wstring::npos)
+ {
+ data.erase(pos, 5);
+ }
+
+ ret = true;
+ }
+ }
+
+ return ret;
+}
diff --git a/Plugins/PluginNowPlaying/Lyrics.h b/Plugins/PluginNowPlaying/Lyrics.h
new file mode 100644
index 00000000..d76ca656
--- /dev/null
+++ b/Plugins/PluginNowPlaying/Lyrics.h
@@ -0,0 +1,33 @@
+/*
+ Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net)
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __LYRICS_H__
+#define __LYRICS_H__
+
+class CLyrics
+{
+public:
+ static bool GetFromInternet(const std::wstring& artist, const std::wstring& title, std::wstring& out);
+
+private:
+ static bool GetFromLetras(const std::wstring& artist, const std::wstring& title, std::wstring& data);
+ static bool GetFromLYRDB(const std::wstring& artist, const std::wstring& title, std::wstring& data);
+ static bool GetFromWikia(const std::wstring& artist, const std::wstring& title, std::wstring& data);
+};
+
+#endif
\ No newline at end of file
diff --git a/Plugins/PluginNowPlaying/NowPlaying.cpp b/Plugins/PluginNowPlaying/NowPlaying.cpp
index ccc79a4b..80be0079 100644
--- a/Plugins/PluginNowPlaying/NowPlaying.cpp
+++ b/Plugins/PluginNowPlaying/NowPlaying.cpp
@@ -19,6 +19,7 @@
#include "StdAfx.h"
#include "../../Library/DisableThreadLibraryCalls.h" // contains DllMain entry point
#include "NowPlaying.h"
+#include "Internet.h"
#include "PlayerAIMP.h"
#include "PlayerCAD.h"
#include "PlayerFoobar.h"
@@ -28,17 +29,7 @@
#include "PlayerWLM.h"
#include "PlayerWMP.h"
-CPlayer* g_AIMP = NULL;
-CPlayer* g_CAD = NULL;
-CPlayer* g_Foobar = NULL;
-CPlayer* g_iTunes = NULL;
-CPlayer* g_Spotify = NULL;
-CPlayer* g_Winamp = NULL;
-CPlayer* g_WLM = NULL;
-CPlayer* g_WMP = NULL;
-
static std::map g_Measures;
-static bool g_DisableLeazingZero = false;
std::wstring g_CachePath;
std::wstring g_SettingsFile;
@@ -71,6 +62,8 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
{
LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: Unable to get path to Plugins.ini.");
}
+
+ CInternet::Initialize();
}
// Data is stored in two structs: ChildMeasure and ParentMeasure. ParentMeasure is created for measures
@@ -125,75 +118,39 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
if (_wcsicmp(L"AIMP", str) == 0)
{
- if (!g_AIMP)
- {
- g_AIMP = new CPlayerAIMP();
- }
- parent->player = g_AIMP;
+ parent->player = CPlayerAIMP::Create();
}
else if (_wcsicmp(L"CAD", str) == 0)
{
- if (!g_CAD)
- {
- g_CAD = new CPlayerCAD();
- }
- parent->player = g_CAD;
+ parent->player = CPlayerCAD::Create();
}
else if (_wcsicmp(L"foobar2000", str) == 0)
{
- if (!g_Foobar)
- {
- g_Foobar = new CPlayerFoobar();
- }
- parent->player = g_Foobar;
+ parent->player = CPlayerFoobar::Create();
}
else if (_wcsicmp(L"iTunes", str) == 0)
{
- if (!g_iTunes)
- {
- g_iTunes = new CPlayerITunes();
- }
- parent->player = g_iTunes;
+ parent->player = CPlayerITunes::Create();
}
else if (_wcsicmp(L"MediaMonkey", str) == 0)
{
- if (!g_Winamp)
- {
- g_Winamp = new CPlayerWinamp(WA_MEDIAMONKEY);
- }
- parent->player = g_Winamp;
+ parent->player = CPlayerWinamp::Create(WA_MEDIAMONKEY);
}
else if (_wcsicmp(L"Spotify", str) == 0)
{
- if (!g_Spotify)
- {
- g_Spotify = new CPlayerSpotify();
- }
- parent->player = g_Spotify;
+ parent->player = CPlayerSpotify::Create();
}
else if (_wcsicmp(L"WinAmp", str) == 0)
{
- if (!g_Winamp)
- {
- g_Winamp = new CPlayerWinamp(WA_WINAMP);
- }
- parent->player = g_Winamp;
+ parent->player = CPlayerWinamp::Create(WA_WINAMP);
}
else if (_wcsicmp(L"WLM", str) == 0)
{
- if (!g_WLM)
- {
- g_WLM = new CPlayerWLM();
- }
- parent->player = g_WLM;
+ parent->player = CPlayerWLM::Create();
}
else if (_wcsicmp(L"WMP", str) == 0)
{
- if (!g_WMP)
- {
- g_WMP = new CPlayerWMP();
- }
- parent->player = g_WMP;
+ parent->player = CPlayerWMP::Create();
}
else
{
@@ -331,6 +288,11 @@ void Finalize(HMODULE instance, UINT id)
delete child;
g_Measures.erase(i);
+
+ if (g_Measures.empty())
+ {
+ CInternet::Finalize();
+ }
}
}
@@ -359,8 +321,6 @@ UINT Update(UINT id)
parent->trackCount != player->GetTrackCount())
{
ExecuteCommand(parent->trackChangeAction, parent->window);
-
- // TODO: First is true..
parent->trackCount = player->GetTrackCount();
}
}
@@ -423,6 +383,9 @@ LPCTSTR GetString(UINT id, UINT flags)
case MEASURE_ALBUM:
return player->GetAlbum();
+ case MEASURE_LYRICS:
+ return player->GetLyrics();
+
case MEASURE_COVER:
return player->GetCoverPath();
diff --git a/Plugins/PluginNowPlaying/NowPlaying.h b/Plugins/PluginNowPlaying/NowPlaying.h
index e0eff26f..b3576504 100644
--- a/Plugins/PluginNowPlaying/NowPlaying.h
+++ b/Plugins/PluginNowPlaying/NowPlaying.h
@@ -27,7 +27,6 @@ struct ParentMeasure
UINT childCount;
UINT trackCount;
CPlayer* player;
- HANDLE thread;
HWND window;
std::wstring name;
std::wstring iniFile;
@@ -35,7 +34,7 @@ struct ParentMeasure
std::wstring playerPath;
bool disableLeadingZero;
- ParentMeasure() : player(NULL), thread(NULL) {}
+ ParentMeasure() : player(NULL) {}
};
struct ChildMeasure
diff --git a/Plugins/PluginNowPlaying/Player.cpp b/Plugins/PluginNowPlaying/Player.cpp
index 22c088c9..01db1acf 100644
--- a/Plugins/PluginNowPlaying/Player.cpp
+++ b/Plugins/PluginNowPlaying/Player.cpp
@@ -19,6 +19,8 @@
#include "StdAfx.h"
#include "Player.h"
+extern std::wstring g_CachePath;
+
/*
** CPlayer
**
@@ -36,8 +38,11 @@ CPlayer::CPlayer() :
m_Duration(),
m_Position(),
m_Rating(),
- m_Volume()
+ m_Volume(),
+ m_CriticalSection(),
+ m_InternetThread()
{
+ InitializeCriticalSection(&m_CriticalSection);
}
/*
@@ -48,6 +53,7 @@ CPlayer::CPlayer() :
*/
CPlayer::~CPlayer()
{
+ DeleteCriticalSection(&m_CriticalSection);
}
/*
@@ -110,6 +116,131 @@ void CPlayer::UpdateMeasure()
}
}
+/*
+** GetCacheFile
+**
+** Creates escaped path to cache file (without extension)
+**
+*/
+std::wstring CPlayer::GetCacheFile()
+{
+ std::wstring path = g_CachePath;
+
+ if (m_Artist.empty() || m_Title.empty())
+ {
+ path += L"temp";
+ }
+ else
+ {
+ std::wstring name = m_Artist;
+ name += L" - ";
+ name += m_Title;
+
+ // Replace reserved chars with _
+ std::wstring::size_type pos = 0;
+ while ((pos = name.find_first_of(L"\\/:*?\"<>|", pos)) != std::wstring::npos) name[pos] = L'_';
+
+ path += name;
+ }
+
+ return path;
+}
+
+/*
+** FindCover
+**
+** Default implementation for getting cover.
+**
+*/
+void CPlayer::FindCover()
+{
+ m_CoverPath = GetCacheFile();
+
+ if (!CCover::GetCached(m_CoverPath))
+ {
+ TagLib::FileRef fr(m_FilePath.c_str());
+ if (fr.isNull() || !fr.tag() || !CCover::GetEmbedded(fr, m_CoverPath))
+ {
+ std::wstring trackFolder = CCover::GetFileFolder(m_FilePath);
+
+ if (!CCover::GetLocal(L"cover", trackFolder, m_CoverPath) &&
+ !CCover::GetLocal(L"folder", trackFolder, m_CoverPath))
+ {
+ // Nothing found
+ m_CoverPath.clear();
+ }
+ }
+ }
+}
+
+/*
+** FindLyrics
+**
+** Default implementation for getting lyrics.
+**
+*/
+void CPlayer::FindLyrics()
+{
+ if (TryEnterCriticalSection(&m_CriticalSection))
+ {
+ m_Lyrics.clear();
+
+ unsigned int id;
+ HANDLE thread = (HANDLE)_beginthreadex(NULL, 0, LyricsThreadProc, this, 0, &id);
+ if (thread)
+ {
+ m_InternetThread = thread;
+ }
+ else
+ {
+ LSLog(LOG_DEBUG, L"Rainmeter", L"NowPlayingPlugin: Failed to start lyrics thread.");
+ }
+
+ LeaveCriticalSection(&m_CriticalSection);
+ }
+}
+
+/*
+** LyricsThreadProc
+**
+** Thread to download lyrics.
+**
+*/
+unsigned __stdcall CPlayer::LyricsThreadProc(void* pParam)
+{
+ CPlayer* player = (CPlayer*)pParam;
+
+ EnterCriticalSection(&player->m_CriticalSection);
+ std::wstring lyrics;
+ bool found;
+
+ while (true)
+ {
+ UINT beforeCount = player->GetTrackCount();
+ found = CLyrics::GetFromInternet(player->m_Artist, player->m_Title, lyrics);
+ UINT afterCount = player->GetTrackCount();
+
+ if (beforeCount == afterCount)
+ {
+ // We're on the same track
+ break;
+ }
+
+ // Track changed, fetch lyrics for it
+ }
+
+ if (found)
+ {
+ player->m_Lyrics = lyrics;
+ }
+
+ CloseHandle(player->m_InternetThread);
+ player->m_InternetThread = NULL;
+ LeaveCriticalSection(&player->m_CriticalSection);
+
+ return 0;
+}
+
/*
** ClearData
**
@@ -125,6 +256,7 @@ void CPlayer::ClearData()
m_Artist.clear();
m_Album.clear();
m_Title.clear();
+ m_Lyrics.clear();
m_FilePath.clear();
m_CoverPath.clear();
}
diff --git a/Plugins/PluginNowPlaying/Player.h b/Plugins/PluginNowPlaying/Player.h
index bf3e95ff..a34c74aa 100644
--- a/Plugins/PluginNowPlaying/Player.h
+++ b/Plugins/PluginNowPlaying/Player.h
@@ -19,8 +19,11 @@
#ifndef __PLAYER_H__
#define __PLAYER_H__
+#include "fileref.h"
#include "tag.h"
#include "Cover.h"
+#include "Internet.h"
+#include "Lyrics.h"
enum PLAYSTATE
{
@@ -45,8 +48,7 @@ enum MEASURETYPE
MEASURE_FILE
};
-class CPlayer :
- public CCover
+class CPlayer
{
public:
CPlayer();
@@ -60,6 +62,10 @@ public:
bool IsInitialized() { return m_Initialized; }
UINT GetTrackCount() { return m_TrackCount; }
+
+ std::wstring GetCacheFile();
+ void FindCover();
+ void FindLyrics();
virtual void Pause() {}
virtual void Play() {}
@@ -105,6 +111,12 @@ protected:
UINT m_Position; // Current position in seconds
UINT m_Rating; // Track rating from 0 to 100
UINT m_Volume; // Volume from 0 to 100
+
+private:
+ static unsigned __stdcall LyricsThreadProc(void* pParam);
+
+ HANDLE m_InternetThread;
+ CRITICAL_SECTION m_CriticalSection;
};
#endif
\ No newline at end of file
diff --git a/Plugins/PluginNowPlaying/PlayerAIMP.cpp b/Plugins/PluginNowPlaying/PlayerAIMP.cpp
index 3cd148f9..199c6b17 100644
--- a/Plugins/PluginNowPlaying/PlayerAIMP.cpp
+++ b/Plugins/PluginNowPlaying/PlayerAIMP.cpp
@@ -21,8 +21,9 @@
#include "AIMP/aimp2_sdk.h"
#include "Winamp/wa_ipc.h"
-extern CPlayer* g_AIMP;
+CPlayer* CPlayerAIMP::c_Player = NULL;
+// TODO
/*
** CPlayerAIMP
**
@@ -30,10 +31,10 @@ extern CPlayer* g_AIMP;
**
*/
CPlayerAIMP::CPlayerAIMP() : CPlayer(),
- m_FileMap(),
- m_FileMapHandle(),
m_Window(),
- m_WinampWindow()
+ m_WinampWindow(),
+ m_FileMap(),
+ m_FileMapHandle()
{
}
@@ -45,74 +46,69 @@ CPlayerAIMP::CPlayerAIMP() : CPlayer(),
*/
CPlayerAIMP::~CPlayerAIMP()
{
- g_AIMP = NULL;
+ c_Player = NULL;
if (m_FileMap) UnmapViewOfFile(m_FileMap);
if (m_FileMapHandle) CloseHandle(m_FileMapHandle);
}
/*
-** Initialize
+** Create
**
-** Find AIMP window and mapped object.
+** Creates a shared class object.
**
*/
-bool CPlayerAIMP::Initialize()
+CPlayer* CPlayerAIMP::Create()
{
- m_Window = FindWindow(L"AIMP2_RemoteInfo", L"AIMP2_RemoteInfo");
- m_WinampWindow = FindWindow(L"Winamp v1.x", NULL);
-
- if (m_Window)
+ if (!c_Player)
{
- m_FileMapHandle = OpenFileMapping(FILE_MAP_READ, FALSE, L"AIMP2_RemoteInfo");
- if (!m_FileMapHandle)
- {
- LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: AIMP - Unable to access mapping.");
- return false;
- }
-
- m_FileMap = (LPVOID)MapViewOfFile(m_FileMapHandle, FILE_MAP_READ, 0, 0, 2048);
- if (!m_FileMap)
- {
- LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: AIMP - Unable to view mapping.");
- return false;
- }
-
- return true;
+ c_Player = new CPlayerAIMP();
}
- return false;
+ return c_Player;
}
-bool CPlayerAIMP::CheckActive()
+/*
+** CheckWindow
+**
+** Try to find AIMP periodically.
+**
+*/
+bool CPlayerAIMP::CheckWindow()
{
- if (m_Window)
- {
- if (!IsWindow(m_Window))
- {
- m_Window = NULL;
- m_WinampWindow = NULL;
- if (m_FileMap) UnmapViewOfFile(m_FileMap);
- if (m_FileMapHandle) CloseHandle(m_FileMapHandle);
- ClearData();
- return false;
- }
-
- return true;
- }
- else
- {
- static DWORD oldTime = 0;
- DWORD time = GetTickCount();
+ static DWORD oldTime = 0;
+ DWORD time = GetTickCount();
- // Try to find AIMP every 5 seconds
- if (time - oldTime > 5000)
- {
- oldTime = time;
- return Initialize();
- }
+ // Try to find AIMP every 5 seconds
+ if (time - oldTime > 5000)
+ {
+ oldTime = time;
+ m_Window = FindWindow(L"AIMP2_RemoteInfo", L"AIMP2_RemoteInfo");
- return false;
+ if (m_Window)
+ {
+ m_WinampWindow = FindWindow(L"Winamp v1.x", NULL);
+
+ m_FileMapHandle = OpenFileMapping(FILE_MAP_READ, FALSE, L"AIMP2_RemoteInfo");
+ if (m_FileMapHandle)
+ {
+ m_FileMap = (LPVOID)MapViewOfFile(m_FileMapHandle, FILE_MAP_READ, 0, 0, 2048);
+ if (m_FileMap)
+ {
+ m_Initialized = true;
+ }
+ else
+ {
+ LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: Unable to view AIMP file mapping.");
+ }
+ }
+ else
+ {
+ LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: AIMP - Unable to access AIMP file mapping.");
+ }
+ }
}
+
+ return m_Initialized;
}
/*
@@ -123,29 +119,43 @@ bool CPlayerAIMP::CheckActive()
*/
void CPlayerAIMP::UpdateData()
{
- static long oldFileSize;
- static UINT oldTitleLen;
-
- if (!CheckActive())
+ static long oldFileSize = 0;
+ static UINT oldTitleLen = 0;
+
+ if (!m_Initialized)
{
- // Make sure AIMP is running
- if (oldFileSize != 0)
+ if (oldTitleLen != 0)
{
oldFileSize = 0;
oldTitleLen = 0;
}
- return;
+
+ if (!CheckWindow())
+ {
+ return;
+ }
}
+ // If initialized
m_State = (PLAYSTATE)SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_Player);
if (m_State == PLAYER_STOPPED)
{
- if (oldFileSize != 0)
+ // Make sure AIMP is still active
+ if (!IsWindow(m_Window))
+ {
+ m_Initialized = false;
+ if (m_FileMap) UnmapViewOfFile(m_FileMap);
+ if (m_FileMapHandle) CloseHandle(m_FileMapHandle);
+ }
+
+ if (oldTitleLen != 0)
{
oldFileSize = 0;
oldTitleLen = 0;
ClearData();
}
+
+ // Don't continue if AIMP has quit or is stopped
return;
}
@@ -154,7 +164,7 @@ void CPlayerAIMP::UpdateData()
AIMP2FileInfo* info = (AIMP2FileInfo*)m_FileMap;
if (info->cbSizeOf > 0 &&
- info->nFileSize != oldFileSize || // FileSize and TitleLen are probably unique enough
+ info->nFileSize != oldFileSize || // Avoid reading the same file
info->nTitleLen != oldTitleLen)
{
oldFileSize = info->nFileSize;
@@ -191,7 +201,12 @@ void CPlayerAIMP::UpdateData()
// Find cover if needed
if (m_HasCoverMeasure)
{
- GetCover(m_Artist, m_Title, m_FilePath, m_CoverPath);
+ FindCover();
+ }
+
+ if (m_HasLyricsMeasure)
+ {
+ FindLyrics();
}
}
}
diff --git a/Plugins/PluginNowPlaying/PlayerAIMP.h b/Plugins/PluginNowPlaying/PlayerAIMP.h
index 84ad6c0c..f59274e1 100644
--- a/Plugins/PluginNowPlaying/PlayerAIMP.h
+++ b/Plugins/PluginNowPlaying/PlayerAIMP.h
@@ -24,8 +24,9 @@
class CPlayerAIMP : public CPlayer
{
public:
- CPlayerAIMP();
- ~CPlayerAIMP();
+ virtual ~CPlayerAIMP();
+
+ static CPlayer* Create();
virtual void UpdateData();
@@ -40,14 +41,19 @@ public:
virtual void ClosePlayer();
virtual void OpenPlayer(std::wstring& path);
+protected:
+ CPlayerAIMP();
+
private:
bool Initialize();
- bool CheckActive();
+ bool CheckWindow();
- LPVOID m_FileMap;
- HANDLE m_FileMapHandle;
+ static CPlayer* c_Player;
+
HWND m_Window; // AIMP window
HWND m_WinampWindow; // AIMP Winamp API window
+ LPVOID m_FileMap;
+ HANDLE m_FileMapHandle;
};
#endif
diff --git a/Plugins/PluginNowPlaying/PlayerCAD.cpp b/Plugins/PluginNowPlaying/PlayerCAD.cpp
index 290716b9..65bd5316 100644
--- a/Plugins/PluginNowPlaying/PlayerCAD.cpp
+++ b/Plugins/PluginNowPlaying/PlayerCAD.cpp
@@ -20,7 +20,7 @@
#include "PlayerCAD.h"
#include "CAD/cad_sdk.h"
-extern CPlayer* g_CAD;
+CPlayer* CPlayerCAD::c_Player = NULL;
extern std::wstring g_SettingsFile;
// This player emulates the CD Art Display IPC interface, which is supported by
@@ -47,10 +47,26 @@ CPlayerCAD::CPlayerCAD() : CPlayer(),
*/
CPlayerCAD::~CPlayerCAD()
{
- g_CAD = NULL;
+ c_Player = NULL;
Uninitialize();
}
+/*
+** Create
+**
+** Creates a shared class object.
+**
+*/
+CPlayer* CPlayerCAD::Create()
+{
+ if (!c_Player)
+ {
+ c_Player = new CPlayerCAD();
+ }
+
+ return c_Player;
+}
+
/*
** Initialize
**
@@ -113,6 +129,7 @@ void CPlayerCAD::Initialize()
if (m_PlayerWindow)
{
+ m_Initialized = true;
SendMessage(m_PlayerWindow, WM_USER, (WPARAM)m_Window, IPC_SET_CALLBACK_HWND);
m_State = (PLAYSTATE)SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_PLAYER_STATE);
@@ -143,37 +160,37 @@ void CPlayerCAD::Uninitialize()
*/
LRESULT CALLBACK CPlayerCAD::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
- static CPlayerCAD* p;
+ static CPlayerCAD* player;
switch (msg)
{
case WM_CREATE:
// Get pointer to the CPlayerCAD class from the CreateWindow call
- p = (CPlayerCAD*)((CREATESTRUCT*)lParam)->lpCreateParams;
+ player = (CPlayerCAD*)((CREATESTRUCT*)lParam)->lpCreateParams;
return 0;
case WM_DESTROY:
- SendMessage(p->m_PlayerWindow, WM_USER, 0, IPC_SHUTDOWN_NOTIFICATION);
+ SendMessage(player->m_PlayerWindow, WM_USER, 0, IPC_SHUTDOWN_NOTIFICATION);
return 0;
case WM_USER:
switch (lParam)
{
case IPC_TRACK_CHANGED_NOTIFICATION:
- SendMessage(p->m_PlayerWindow, WM_USER, 0, IPC_GET_CURRENT_TRACK);
+ SendMessage(player->m_PlayerWindow, WM_USER, 0, IPC_GET_CURRENT_TRACK);
break;
case IPC_PLAYER_STATE_CHANGED_NOTIFICATION:
- p->m_State = (PLAYSTATE)wParam;
- if (p->m_State == PLAYER_STOPPED)
+ player->m_State = (PLAYSTATE)wParam;
+ if (player->m_State == PLAYER_STOPPED)
{
- p->ClearData();
+ player->ClearData();
}
break;
case IPC_SHUTDOWN_NOTIFICATION:
- p->m_PlayerWindow = NULL;
- p->ClearData();
+ player->m_Initialized = false;
+ player->ClearData();
break;
}
return 0;
@@ -184,19 +201,19 @@ LRESULT CALLBACK CPlayerCAD::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
if (cds->dwData == IPC_CURRENT_TRACK_INFO)
{
// TODO: Sent on track update?
- ++p->m_TrackCount;
+ ++player->m_TrackCount;
std::wstring data = (WCHAR*)cds->lpData;
std::wstring::size_type len = data.find_first_of(L'\t');
- p->m_Title.assign(data, 0, len);
+ player->m_Title.assign(data, 0, len);
data.erase(0, ++len);
len = data.find_first_of(L'\t');
- p->m_Artist.assign(data, 0, len);
+ player->m_Artist.assign(data, 0, len);
data.erase(0, ++len);
len = data.find_first_of(L'\t');
- p->m_Album.assign(data, 0, len);
+ player->m_Album.assign(data, 0, len);
data.erase(0, ++len);
len = data.find_first_of(L'\t'); // Skip genre
@@ -206,23 +223,28 @@ LRESULT CALLBACK CPlayerCAD::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
data.erase(0, ++len);
len = data.find_first_of(L'\t');
- p->m_Duration = _wtoi(data.substr(0, len).c_str());
+ player->m_Duration = _wtoi(data.substr(0, len).c_str());
data.erase(0, ++len);
len = data.find_first_of(L'\t');
- p->m_FilePath.assign(data, 0, len);
+ player->m_FilePath.assign(data, 0, len);
data.erase(0, ++len);
len = data.find_first_of(L'\t');
UINT rating = (_wtoi(data.substr(0, len).c_str()) + 1) / 2; // From 0 - 10 to 0 - 5
- p->m_Rating = rating;
+ player->m_Rating = rating;
data.erase(0, ++len);
len = data.find_first_of(L'\t');
- p->m_CoverPath.assign(data, 0, len);
+ player->m_CoverPath.assign(data, 0, len);
data.erase(0, ++len);
+
+ if (player->m_HasLyricsMeasure)
+ {
+ player->FindLyrics();
+ }
}
- else if (cds->dwData == IPC_REGISTER_PLAYER && !p->m_PlayerWindow)
+ else if (cds->dwData == IPC_REGISTER_PLAYER && !player->m_Initialized)
{
std::wstring data = (WCHAR*)cds->lpData;
if (data[0] == L'1')
@@ -238,7 +260,7 @@ LRESULT CALLBACK CPlayerCAD::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
data.erase(0, ++len);
len = data.find_first_of(L'\t');
- p->m_PlayerPath.assign(data, 0, len);
+ player->m_PlayerPath.assign(data, 0, len);
data.erase(0, ++len);
LPCTSTR classSz = className.empty() ? NULL : className.c_str();
@@ -247,17 +269,18 @@ LRESULT CALLBACK CPlayerCAD::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
WritePrivateProfileString(L"NowPlaying.dll", L"ClassName", classSz, file);
WritePrivateProfileString(L"NowPlaying.dll", L"WindowName", windowSz, file);
- WritePrivateProfileString(L"NowPlaying.dll", L"PlayerPath", p->m_PlayerPath.c_str(), file);
+ WritePrivateProfileString(L"NowPlaying.dll", L"PlayerPath", player->m_PlayerPath.c_str(), file);
- p->m_PlayerWindow = FindWindow(classSz, windowSz);
+ player->m_PlayerWindow = FindWindow(classSz, windowSz);
- if (p->m_PlayerWindow)
+ if (player->m_PlayerWindow)
{
- p->m_State = (PLAYSTATE)SendMessage(p->m_PlayerWindow, WM_USER, 0, IPC_GET_PLAYER_STATE);
+ player->m_Initialized = true;
+ player->m_State = (PLAYSTATE)SendMessage(player->m_PlayerWindow, WM_USER, 0, IPC_GET_PLAYER_STATE);
- if (p->m_State != PLAYER_STOPPED)
+ if (player->m_State != PLAYER_STOPPED)
{
- SendMessage(p->m_PlayerWindow, WM_USER, 0, IPC_GET_CURRENT_TRACK);
+ SendMessage(player->m_PlayerWindow, WM_USER, 0, IPC_GET_CURRENT_TRACK);
}
}
}
@@ -392,7 +415,8 @@ void CPlayerCAD::SetVolume(int volume)
void CPlayerCAD::ClosePlayer()
{
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_CLOSE_PLAYER);
- m_PlayerWindow = NULL;
+ // TODO
+ m_Initialized = false;
ClearData();
}
diff --git a/Plugins/PluginNowPlaying/PlayerCAD.h b/Plugins/PluginNowPlaying/PlayerCAD.h
index 202ba198..0ad6ad3e 100644
--- a/Plugins/PluginNowPlaying/PlayerCAD.h
+++ b/Plugins/PluginNowPlaying/PlayerCAD.h
@@ -24,8 +24,9 @@
class CPlayerCAD : public CPlayer
{
public:
- CPlayerCAD();
- ~CPlayerCAD();
+ virtual ~CPlayerCAD();
+
+ static CPlayer* Create();
virtual void UpdateData();
@@ -40,11 +41,16 @@ public:
virtual void ClosePlayer();
virtual void OpenPlayer(std::wstring& path);
+protected:
+ CPlayerCAD();
+
private:
void Initialize();
void Uninitialize();
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static CPlayer* c_Player;
+
HWND m_Window;
HWND m_PlayerWindow;
std::wstring m_PlayerPath;
diff --git a/Plugins/PluginNowPlaying/PlayerFoobar.cpp b/Plugins/PluginNowPlaying/PlayerFoobar.cpp
index 91969a87..012d24a4 100644
--- a/Plugins/PluginNowPlaying/PlayerFoobar.cpp
+++ b/Plugins/PluginNowPlaying/PlayerFoobar.cpp
@@ -19,7 +19,7 @@
#include "StdAfx.h"
#include "PlayerFoobar.h"
-extern CPlayer* g_Foobar;
+CPlayer* CPlayerFoobar::c_Player = NULL;
/*
** CPlayerFoobar
@@ -42,10 +42,26 @@ CPlayerFoobar::CPlayerFoobar() : CPlayer(),
*/
CPlayerFoobar::~CPlayerFoobar()
{
- g_Foobar = NULL;
+ c_Player = NULL;
Uninitialize();
}
+/*
+** Create
+**
+** Creates a shared class object.
+**
+*/
+CPlayer* CPlayerFoobar::Create()
+{
+ if (!c_Player)
+ {
+ c_Player = new CPlayerFoobar();
+ }
+
+ return c_Player;
+}
+
/*
** Initialize
**
@@ -89,6 +105,7 @@ void CPlayerFoobar::Initialize()
}
else
{
+ m_Initialized = true;
SendMessage(m_FooWindow, WM_USER, (WPARAM)m_Window, FOO_SETCALLBACK);
}
}
@@ -164,7 +181,7 @@ LRESULT CALLBACK CPlayerFoobar::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
break;
case FOO_PLAYERQUIT:
- player->m_FooWindow = NULL;
+ player->m_Initialized = false;
player->ClearData();
break;
}
@@ -221,7 +238,12 @@ LRESULT CALLBACK CPlayerFoobar::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
if (player->m_HasCoverMeasure || player->m_InstanceCount == 0)
{
- GetCover(player->m_Artist, player->m_Title, player->m_FilePath, player->m_CoverPath);
+ player->FindCover();
+ }
+
+ if (player->m_HasLyricsMeasure)
+ {
+ player->FindLyrics();
}
}
}
@@ -339,7 +361,7 @@ void CPlayerFoobar::ClosePlayer()
*/
void CPlayerFoobar::OpenPlayer(std::wstring& path)
{
- if (!m_FooWindow)
+ if (!m_Initialized)
{
if (path.empty())
{
diff --git a/Plugins/PluginNowPlaying/PlayerFoobar.h b/Plugins/PluginNowPlaying/PlayerFoobar.h
index 5abb717d..bd740479 100644
--- a/Plugins/PluginNowPlaying/PlayerFoobar.h
+++ b/Plugins/PluginNowPlaying/PlayerFoobar.h
@@ -24,8 +24,9 @@
class CPlayerFoobar : public CPlayer
{
public:
- CPlayerFoobar();
- ~CPlayerFoobar();
+ virtual ~CPlayerFoobar();
+
+ static CPlayer* Create();
virtual void UpdateData();
@@ -40,6 +41,9 @@ public:
virtual void ClosePlayer();
virtual void OpenPlayer(std::wstring& path);
+protected:
+ CPlayerFoobar();
+
private:
enum FOOMESSAGE
{
@@ -73,6 +77,8 @@ private:
void Uninitialize();
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static CPlayer* c_Player;
+
HWND m_Window; // Our reciever window
HWND m_FooWindow; // Foobar receiver window
};
diff --git a/Plugins/PluginNowPlaying/PlayerITunes.cpp b/Plugins/PluginNowPlaying/PlayerITunes.cpp
index 24a31043..52690f79 100644
--- a/Plugins/PluginNowPlaying/PlayerITunes.cpp
+++ b/Plugins/PluginNowPlaying/PlayerITunes.cpp
@@ -19,7 +19,7 @@
#include "StdAfx.h"
#include "PlayerITunes.h"
-extern CPlayer* g_iTunes;
+CPlayer* CPlayerITunes::c_Player = NULL;
/*
** CEventHandler
@@ -129,11 +129,27 @@ CPlayerITunes::CPlayerITunes() : CPlayer(),
*/
CPlayerITunes::~CPlayerITunes()
{
- g_iTunes = NULL;
+ c_Player = NULL;
Uninitialize();
CoUninitialize();
}
+/*
+** Create
+**
+** Creates a shared class object.
+**
+*/
+CPlayer* CPlayerITunes::Create()
+{
+ if (!c_Player)
+ {
+ c_Player = new CPlayerITunes();
+ }
+
+ return c_Player;
+}
+
/*
** Initialize
**
@@ -216,7 +232,6 @@ void CPlayerITunes::Uninitialize()
if (m_Initialized)
{
m_Initialized = false;
- m_UserQuitPrompt = true;
if (m_iTunes)
{
m_iTunes->Release();
@@ -304,6 +319,7 @@ void CPlayerITunes::OnTrackChange()
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;
@@ -319,45 +335,54 @@ void CPlayerITunes::OnTrackChange()
++m_TrackCount;
m_FilePath = tmpStr;
- if (m_HasCoverMeasure && !GetCachedCover(m_Artist, m_Title, m_CoverPath))
+ if (m_HasCoverMeasure)
{
- // Art not in cache, check for embedded art
- IITArtworkCollection* artworkCollection;
- hr = track->get_Artwork(&artworkCollection);
-
- if (SUCCEEDED(hr))
+ m_CoverPath = GetCacheFile();
+ if (!CCover::GetCached(m_CoverPath))
{
- long count;
- artworkCollection->get_Count(&count);
+ // Art not in cache, check for embedded art through iTunes interface
+ IITArtworkCollection* artworkCollection;
+ hr = track->get_Artwork(&artworkCollection);
- if (count > 0)
+ if (SUCCEEDED(hr))
{
- IITArtwork* artwork;
- hr = artworkCollection->get_Item(1, &artwork);
+ long count;
+ artworkCollection->get_Count(&count);
- if (SUCCEEDED(hr))
+ if (count > 0)
{
- tmpStr = m_CoverPath.c_str();
- hr = artwork->SaveArtworkToFile(tmpStr);
- if (FAILED(hr))
- {
- m_CoverPath.clear();
- }
+ IITArtwork* artwork;
+ hr = artworkCollection->get_Item(1, &artwork);
- artwork->Release();
+ if (SUCCEEDED(hr))
+ {
+ tmpStr = m_CoverPath.c_str();
+ hr = artwork->SaveArtworkToFile(tmpStr);
+ if (FAILED(hr))
+ {
+ m_CoverPath.clear();
+ }
+
+ artwork->Release();
+ }
}
+ else
+ {
+ m_CoverPath.clear();
+ }
+
+ artworkCollection->Release();
}
else
{
m_CoverPath.clear();
}
+ }
+ }
- artworkCollection->Release();
- }
- else
- {
- m_CoverPath.clear();
- }
+ if (m_HasLyricsMeasure)
+ {
+ FindLyrics();
}
}
}
diff --git a/Plugins/PluginNowPlaying/PlayerITunes.h b/Plugins/PluginNowPlaying/PlayerITunes.h
index 62259342..e3f69cb1 100644
--- a/Plugins/PluginNowPlaying/PlayerITunes.h
+++ b/Plugins/PluginNowPlaying/PlayerITunes.h
@@ -35,8 +35,9 @@
class CPlayerITunes : public CPlayer
{
public:
- CPlayerITunes();
- ~CPlayerITunes();
+ virtual ~CPlayerITunes();
+
+ static CPlayer* Create();
virtual void UpdateData();
@@ -51,6 +52,9 @@ public:
virtual void ClosePlayer();
virtual void OpenPlayer(std::wstring& path);
+protected:
+ CPlayerITunes();
+
private:
class CEventHandler : public _IiTunesEvents
{
@@ -83,6 +87,8 @@ private:
void OnVolumeChange(int volume);
bool CheckWindow();
+ static CPlayer* c_Player;
+
bool m_UserQuitPrompt;
IiTunes* m_iTunes;
CEventHandler* m_iTunesEvent;
diff --git a/Plugins/PluginNowPlaying/PlayerSpotify.cpp b/Plugins/PluginNowPlaying/PlayerSpotify.cpp
index 1acabc44..c33763c3 100644
--- a/Plugins/PluginNowPlaying/PlayerSpotify.cpp
+++ b/Plugins/PluginNowPlaying/PlayerSpotify.cpp
@@ -19,7 +19,7 @@
#include "StdAfx.h"
#include "PlayerSpotify.h"
-extern CPlayer* g_Spotify;
+CPlayer* CPlayerSpotify::c_Player = NULL;
/*
** CPlayerSpotify
@@ -40,7 +40,23 @@ CPlayerSpotify::CPlayerSpotify() : CPlayer(),
*/
CPlayerSpotify::~CPlayerSpotify()
{
- g_Spotify = NULL;
+ c_Player = NULL;
+}
+
+/*
+** Create
+**
+** Creates a shared class object.
+**
+*/
+CPlayer* CPlayerSpotify::Create()
+{
+ if (!c_Player)
+ {
+ c_Player = new CPlayerSpotify();
+ }
+
+ return c_Player;
}
/*
@@ -98,6 +114,11 @@ void CPlayerSpotify::UpdateData()
m_Title = track;
m_Artist = artist;
++m_TrackCount;
+
+ if (m_HasLyricsMeasure)
+ {
+ FindLyrics();
+ }
}
return;
}
diff --git a/Plugins/PluginNowPlaying/PlayerSpotify.h b/Plugins/PluginNowPlaying/PlayerSpotify.h
index ee03125d..ded97a9a 100644
--- a/Plugins/PluginNowPlaying/PlayerSpotify.h
+++ b/Plugins/PluginNowPlaying/PlayerSpotify.h
@@ -24,8 +24,9 @@
class CPlayerSpotify : public CPlayer
{
public:
- CPlayerSpotify();
- ~CPlayerSpotify();
+ virtual ~CPlayerSpotify();
+
+ static CPlayer* Create();
virtual void Pause() { return Play(); }
virtual void Play();
@@ -36,6 +37,9 @@ public:
virtual void OpenPlayer(std::wstring& path);
virtual void UpdateData();
+protected:
+ CPlayerSpotify();
+
private:
enum SPOTIFYCOMMAND
{
@@ -50,6 +54,8 @@ private:
bool CheckWindow();
+ static CPlayer* c_Player;
+
HWND m_Window;
};
diff --git a/Plugins/PluginNowPlaying/PlayerWLM.cpp b/Plugins/PluginNowPlaying/PlayerWLM.cpp
index edcc272c..3a870421 100644
--- a/Plugins/PluginNowPlaying/PlayerWLM.cpp
+++ b/Plugins/PluginNowPlaying/PlayerWLM.cpp
@@ -19,7 +19,7 @@
#include "StdAfx.h"
#include "PlayerWLM.h"
-extern CPlayer* g_WLM;
+CPlayer* CPlayerWLM::c_Player = NULL;
// This player emulates the MSN/WLM Messenger 'Listening to' interface, which is
// supported by OpenPandora, Last.fm, Media Player Classic, TTPlayer, Zune, etc.
@@ -54,6 +54,8 @@ CPlayerWLM::CPlayerWLM() : CPlayer(),
NULL,
hInstance,
this);
+
+ m_Initialized = true;
}
/*
@@ -64,11 +66,27 @@ CPlayerWLM::CPlayerWLM() : CPlayer(),
*/
CPlayerWLM::~CPlayerWLM()
{
- g_WLM = NULL;
+ c_Player = NULL;
DestroyWindow(m_Window);
UnregisterClass(L"MsnMsgrUIManager", GetModuleHandle(NULL));
}
+/*
+** Create
+**
+** Creates a shared class object.
+**
+*/
+CPlayer* CPlayerWLM::Create()
+{
+ if (!c_Player)
+ {
+ c_Player = new CPlayerWLM();
+ }
+
+ return c_Player;
+}
+
LRESULT CALLBACK CPlayerWLM::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static CPlayerWLM* player;
@@ -99,6 +117,7 @@ LRESULT CALLBACK CPlayerWLM::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
if (playing)
{
+ ++player->m_TrackCount;
player->m_State = PLAYER_PLAYING;
data.erase(0, 3); // Get rid of the status
@@ -119,6 +138,11 @@ LRESULT CALLBACK CPlayerWLM::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
len = data.find_first_of(L'\\');
player->m_Album = data.substr(0, len);
+
+ if (player->m_HasLyricsMeasure)
+ {
+ player->FindLyrics();
+ }
}
else
{
diff --git a/Plugins/PluginNowPlaying/PlayerWLM.h b/Plugins/PluginNowPlaying/PlayerWLM.h
index 5f797513..b27bfa9c 100644
--- a/Plugins/PluginNowPlaying/PlayerWLM.h
+++ b/Plugins/PluginNowPlaying/PlayerWLM.h
@@ -24,8 +24,9 @@
class CPlayerWLM : public CPlayer
{
public:
- CPlayerWLM();
- ~CPlayerWLM();
+ virtual ~CPlayerWLM();
+
+ static CPlayer* Create();
virtual void UpdateData();
@@ -35,10 +36,15 @@ public:
virtual void Next();
virtual void Previous();
+protected:
+ CPlayerWLM();
+
private:
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void SendKeyInput(WORD key);
+ static CPlayer* c_Player;
+
HWND m_Window;
};
diff --git a/Plugins/PluginNowPlaying/PlayerWMP.cpp b/Plugins/PluginNowPlaying/PlayerWMP.cpp
index 9e22643d..f3fda6b3 100644
--- a/Plugins/PluginNowPlaying/PlayerWMP.cpp
+++ b/Plugins/PluginNowPlaying/PlayerWMP.cpp
@@ -19,7 +19,7 @@
#include "StdAfx.h"
#include "PlayerWMP.h"
-extern CPlayer* g_WMP;
+CPlayer* CPlayerWMP::c_Player = NULL;
/*
** CRemoteHost
@@ -170,11 +170,27 @@ CPlayerWMP::CPlayerWMP() : CPlayer(),
*/
CPlayerWMP::~CPlayerWMP()
{
- g_WMP = NULL;
+ c_Player = NULL;
Uninitialize();
m_ComModule.Term();
}
+/*
+** Create
+**
+** Creates a shared class object.
+**
+*/
+CPlayer* CPlayerWMP::Create()
+{
+ if (!c_Player)
+ {
+ c_Player = new CPlayerWMP();
+ }
+
+ return c_Player;
+}
+
/*
** Initialize
**
@@ -450,9 +466,14 @@ void CPlayerWMP::UpdateData()
}
else
{
- GetCover(m_Artist, m_Title, m_FilePath, m_CoverPath);
+ FindCover();
}
}
+
+ if (m_HasLyricsMeasure)
+ {
+ FindLyrics();
+ }
}
}
}
diff --git a/Plugins/PluginNowPlaying/PlayerWMP.h b/Plugins/PluginNowPlaying/PlayerWMP.h
index e1c1d565..70973840 100644
--- a/Plugins/PluginNowPlaying/PlayerWMP.h
+++ b/Plugins/PluginNowPlaying/PlayerWMP.h
@@ -34,8 +34,9 @@
class CPlayerWMP : public CPlayer
{
public:
- CPlayerWMP();
- ~CPlayerWMP();
+ virtual ~CPlayerWMP();
+
+ static CPlayer* Create();
virtual void UpdateData();
@@ -50,6 +51,9 @@ public:
virtual void OpenPlayer(std::wstring& path);
virtual void ClosePlayer();
+protected:
+ CPlayerWMP();
+
private:
class CRemoteHost :
public CComObjectRootEx,
@@ -129,6 +133,8 @@ private:
void Initialize();
void Uninitialize();
+ static CPlayer* c_Player;
+
bool m_TrackChanged;
HWND m_Window;
CAxWindow* m_AxWindow;
diff --git a/Plugins/PluginNowPlaying/PlayerWinamp.cpp b/Plugins/PluginNowPlaying/PlayerWinamp.cpp
index 2d85ff07..28b8a143 100644
--- a/Plugins/PluginNowPlaying/PlayerWinamp.cpp
+++ b/Plugins/PluginNowPlaying/PlayerWinamp.cpp
@@ -21,7 +21,7 @@
#include "Winamp/wa_ipc.h"
#include "Winamp/wa_cmd.h"
-extern CPlayer* g_Winamp;
+CPlayer* CPlayerWinamp::c_Player = NULL;
// This player retrieves data through the Winamp IPC interface.
@@ -32,9 +32,11 @@ extern CPlayer* g_Winamp;
**
*/
CPlayerWinamp::CPlayerWinamp(WINAMPTYPE type) : CPlayer(),
- m_WinampType(type),
+ m_Window(),
m_UseUnicodeAPI(false),
- m_Window()
+ m_WinampType(type),
+ m_WinampHandle(),
+ m_WinampAddress()
{
}
@@ -46,10 +48,26 @@ CPlayerWinamp::CPlayerWinamp(WINAMPTYPE type) : CPlayer(),
*/
CPlayerWinamp::~CPlayerWinamp()
{
- g_Winamp = NULL;
+ c_Player = NULL;
if (m_WinampHandle) CloseHandle(m_WinampHandle);
}
+/*
+** Create
+**
+** Creates a shared class object.
+**
+*/
+CPlayer* CPlayerWinamp::Create(WINAMPTYPE type)
+{
+ if (!c_Player)
+ {
+ c_Player = new CPlayerWinamp(type);
+ }
+
+ return c_Player;
+}
+
/*
** CheckWindow
**
@@ -204,63 +222,70 @@ void CPlayerWinamp::UpdateData()
}
}
- // Find cover if needed
- if (m_HasCoverMeasure &&
- !GetCachedCover(m_Artist, m_Title, m_CoverPath) &&
- !GetEmbeddedCover(fr, m_CoverPath))
+ if (m_HasLyricsMeasure)
{
- std::wstring trackFolder = GetFileFolder(m_FilePath);
+ FindLyrics();
+ }
- if (!m_Album.empty())
+ // Find cover if needed
+ if (m_HasCoverMeasure)
+ {
+ m_CoverPath = GetCacheFile();
+ if (!CCover::GetCached(m_CoverPath) &&
+ !CCover::GetEmbedded(fr, m_CoverPath))
{
- // 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)
+ 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 (GetLocalCover(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 (!GetLocalCover(L"cover", trackFolder, m_CoverPath) &&
- !GetLocalCover(L"folder", trackFolder, m_CoverPath))
- {
- // Nothing found
- m_CoverPath.clear();
- }
-
}
}
}
diff --git a/Plugins/PluginNowPlaying/PlayerWinamp.h b/Plugins/PluginNowPlaying/PlayerWinamp.h
index 003661d7..b75e6069 100644
--- a/Plugins/PluginNowPlaying/PlayerWinamp.h
+++ b/Plugins/PluginNowPlaying/PlayerWinamp.h
@@ -30,8 +30,9 @@ enum WINAMPTYPE
class CPlayerWinamp : public CPlayer
{
public:
- CPlayerWinamp(WINAMPTYPE type);
- ~CPlayerWinamp();
+ virtual ~CPlayerWinamp();
+
+ static CPlayer* Create(WINAMPTYPE type);
virtual void UpdateData();
@@ -46,12 +47,17 @@ public:
virtual void ClosePlayer();
virtual void OpenPlayer(std::wstring& path);
+protected:
+ CPlayerWinamp(WINAMPTYPE type);
+
private:
bool CheckWindow();
+ static CPlayer* c_Player;
+
+ HWND m_Window; // Winamp window
bool m_UseUnicodeAPI;
WINAMPTYPE m_WinampType;
- HWND m_Window; // Winamp window
HANDLE m_WinampHandle; // Handle to Winamp process
LPCVOID m_WinampAddress;
};
diff --git a/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj b/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj
index 06bfe18f..26b1d03c 100644
--- a/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj
+++ b/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj
@@ -122,6 +122,7 @@
.\x32/Debug/NowPlaying.pdb
.\x32/Debug/NowPlaying.lib
MachineX86
+ WinInet.lib;%(AdditionalDependencies)
@@ -162,6 +163,7 @@
.\x64/Debug/NowPlaying.pdb
.\x64/Debug/NowPlaying.lib
MachineX64
+ WinInet.lib;%(AdditionalDependencies)
@@ -198,7 +200,7 @@
0x0409
- Rainmeter.lib;Wininet.lib;%(AdditionalDependencies)
+ Rainmeter.lib;WinInet.lib;%(AdditionalDependencies)
../../TestBench/x32/Release/Plugins/NowPlaying.dll
true
..\..\Library\x32\Release;%(AdditionalLibraryDirectories)
@@ -243,7 +245,7 @@
/LTCG %(AdditionalOptions)
- Rainmeter.lib;%(AdditionalDependencies)
+ Rainmeter.lib;WinInet.lib;%(AdditionalDependencies)
../../TestBench/x64/Release/Plugins/NowPlaying.dll
true
..\..\Library\x64\Release;%(AdditionalLibraryDirectories)
@@ -256,6 +258,8 @@
+
+
@@ -344,6 +348,8 @@
+
+
diff --git a/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters b/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters
index aa1ee991..8d176448 100644
--- a/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters
+++ b/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters
@@ -267,6 +267,12 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
@@ -326,6 +332,12 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
diff --git a/Plugins/PluginNowPlaying/StdAfx.h b/Plugins/PluginNowPlaying/StdAfx.h
index 7220d915..44785b53 100644
--- a/Plugins/PluginNowPlaying/StdAfx.h
+++ b/Plugins/PluginNowPlaying/StdAfx.h
@@ -20,7 +20,8 @@
#define __STDAFX_H__
// WinAPI
-#include
+#include
+#include
// STL
#include
@@ -32,7 +33,4 @@
// Rainmeter's exported functions
#include "../../Library/Export.h"
-// TagLib
-#include "fileref.h"
-
#endif