mirror of
https://github.com/chibicitiberiu/rainmeter-studio.git
synced 2024-02-24 04:33:31 +00:00
NowPlayingPlugin:
- Added preliminary support to display lyrics (PlayerType=LYRICS) - Applied r825 fix on TrackChangeAction= (sends bang to correct window without the need of #CURRENTCONFIG#) - Some refactoring
This commit is contained in:
parent
6aa004eb22
commit
d633f4b586
@ -19,76 +19,25 @@
|
|||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#include "Cover.h"
|
#include "Cover.h"
|
||||||
|
|
||||||
extern std::wstring g_CachePath;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** GetCover
|
** GetCached
|
||||||
**
|
|
||||||
** 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
|
|
||||||
**
|
**
|
||||||
** Checks if cover art is in cache.
|
** 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;
|
path += L".art";
|
||||||
if (artist.empty() || title.empty())
|
return (_waccess(path.c_str(), 0) == 0) ? true : false;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** GetLocalArt
|
** GetLocal
|
||||||
**
|
**
|
||||||
** Attemps to find local cover art in various formats.
|
** 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;
|
std::wstring testPath = folder;
|
||||||
testPath += filename;
|
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.
|
** 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;
|
bool found = false;
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#ifndef __COVER_H__
|
#ifndef __COVER_H__
|
||||||
#define __COVER_H__
|
#define __COVER_H__
|
||||||
|
|
||||||
|
// TagLib
|
||||||
|
#include "fileref.h"
|
||||||
#include "apefile.h"
|
#include "apefile.h"
|
||||||
#include "apetag.h"
|
#include "apetag.h"
|
||||||
#include "asffile.h"
|
#include "asffile.h"
|
||||||
@ -40,10 +42,9 @@
|
|||||||
class CCover
|
class CCover
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void GetCover(const std::wstring& artist, const std::wstring& title, const std::wstring& file, std::wstring& target);
|
static bool GetCached(std::wstring& path);
|
||||||
static bool GetCachedCover(const std::wstring& artist, const std::wstring& title, std::wstring& target);
|
static bool GetLocal(std::wstring filename, const std::wstring& folder, std::wstring& target);
|
||||||
static bool GetLocalCover(std::wstring filename, const std::wstring& folder, std::wstring& target);
|
static bool GetEmbedded(const TagLib::FileRef& fr, std::wstring& target);
|
||||||
static bool GetEmbeddedCover(const TagLib::FileRef& fr, std::wstring& target);
|
|
||||||
static std::wstring GetFileFolder(const std::wstring& file);
|
static std::wstring GetFileFolder(const std::wstring& file);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
281
Plugins/PluginNowPlaying/Internet.cpp
Normal file
281
Plugins/PluginNowPlaying/Internet.cpp
Normal file
@ -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) // &#x; or &#X; - 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;
|
||||||
|
}
|
37
Plugins/PluginNowPlaying/Internet.h
Normal file
37
Plugins/PluginNowPlaying/Internet.h
Normal file
@ -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
|
204
Plugins/PluginNowPlaying/Lyrics.cpp
Normal file
204
Plugins/PluginNowPlaying/Lyrics.cpp
Normal file
@ -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"<!");
|
||||||
|
data.resize(pos);
|
||||||
|
CInternet::DecodeReferences(data);
|
||||||
|
|
||||||
|
pos = data.find(L"[...]");
|
||||||
|
if (pos != std::wstring::npos)
|
||||||
|
{
|
||||||
|
// Skip incomplete lyrics
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = data.find(L"<p>");
|
||||||
|
if (pos != std::wstring::npos)
|
||||||
|
{
|
||||||
|
// Skip unavailable lyrics
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((pos = data.find(L"<br />"), 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"<p>", pos);
|
||||||
|
if (pos != std::wstring::npos)
|
||||||
|
{
|
||||||
|
pos += 3;
|
||||||
|
data.erase(0, pos);
|
||||||
|
|
||||||
|
pos = data.find(L"</p>");
|
||||||
|
data.resize(pos);
|
||||||
|
|
||||||
|
CInternet::DecodeReferences(data);
|
||||||
|
|
||||||
|
while ((pos = data.find(L"<br/>"), pos) != std::wstring::npos)
|
||||||
|
{
|
||||||
|
data.erase(pos, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
33
Plugins/PluginNowPlaying/Lyrics.h
Normal file
33
Plugins/PluginNowPlaying/Lyrics.h
Normal file
@ -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
|
@ -19,6 +19,7 @@
|
|||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#include "../../Library/DisableThreadLibraryCalls.h" // contains DllMain entry point
|
#include "../../Library/DisableThreadLibraryCalls.h" // contains DllMain entry point
|
||||||
#include "NowPlaying.h"
|
#include "NowPlaying.h"
|
||||||
|
#include "Internet.h"
|
||||||
#include "PlayerAIMP.h"
|
#include "PlayerAIMP.h"
|
||||||
#include "PlayerCAD.h"
|
#include "PlayerCAD.h"
|
||||||
#include "PlayerFoobar.h"
|
#include "PlayerFoobar.h"
|
||||||
@ -28,17 +29,7 @@
|
|||||||
#include "PlayerWLM.h"
|
#include "PlayerWLM.h"
|
||||||
#include "PlayerWMP.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<UINT, ChildMeasure*> g_Measures;
|
static std::map<UINT, ChildMeasure*> g_Measures;
|
||||||
static bool g_DisableLeazingZero = false;
|
|
||||||
std::wstring g_CachePath;
|
std::wstring g_CachePath;
|
||||||
std::wstring g_SettingsFile;
|
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.");
|
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
|
// 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 (_wcsicmp(L"AIMP", str) == 0)
|
||||||
{
|
{
|
||||||
if (!g_AIMP)
|
parent->player = CPlayerAIMP::Create();
|
||||||
{
|
|
||||||
g_AIMP = new CPlayerAIMP();
|
|
||||||
}
|
|
||||||
parent->player = g_AIMP;
|
|
||||||
}
|
}
|
||||||
else if (_wcsicmp(L"CAD", str) == 0)
|
else if (_wcsicmp(L"CAD", str) == 0)
|
||||||
{
|
{
|
||||||
if (!g_CAD)
|
parent->player = CPlayerCAD::Create();
|
||||||
{
|
|
||||||
g_CAD = new CPlayerCAD();
|
|
||||||
}
|
|
||||||
parent->player = g_CAD;
|
|
||||||
}
|
}
|
||||||
else if (_wcsicmp(L"foobar2000", str) == 0)
|
else if (_wcsicmp(L"foobar2000", str) == 0)
|
||||||
{
|
{
|
||||||
if (!g_Foobar)
|
parent->player = CPlayerFoobar::Create();
|
||||||
{
|
|
||||||
g_Foobar = new CPlayerFoobar();
|
|
||||||
}
|
|
||||||
parent->player = g_Foobar;
|
|
||||||
}
|
}
|
||||||
else if (_wcsicmp(L"iTunes", str) == 0)
|
else if (_wcsicmp(L"iTunes", str) == 0)
|
||||||
{
|
{
|
||||||
if (!g_iTunes)
|
parent->player = CPlayerITunes::Create();
|
||||||
{
|
|
||||||
g_iTunes = new CPlayerITunes();
|
|
||||||
}
|
|
||||||
parent->player = g_iTunes;
|
|
||||||
}
|
}
|
||||||
else if (_wcsicmp(L"MediaMonkey", str) == 0)
|
else if (_wcsicmp(L"MediaMonkey", str) == 0)
|
||||||
{
|
{
|
||||||
if (!g_Winamp)
|
parent->player = CPlayerWinamp::Create(WA_MEDIAMONKEY);
|
||||||
{
|
|
||||||
g_Winamp = new CPlayerWinamp(WA_MEDIAMONKEY);
|
|
||||||
}
|
|
||||||
parent->player = g_Winamp;
|
|
||||||
}
|
}
|
||||||
else if (_wcsicmp(L"Spotify", str) == 0)
|
else if (_wcsicmp(L"Spotify", str) == 0)
|
||||||
{
|
{
|
||||||
if (!g_Spotify)
|
parent->player = CPlayerSpotify::Create();
|
||||||
{
|
|
||||||
g_Spotify = new CPlayerSpotify();
|
|
||||||
}
|
|
||||||
parent->player = g_Spotify;
|
|
||||||
}
|
}
|
||||||
else if (_wcsicmp(L"WinAmp", str) == 0)
|
else if (_wcsicmp(L"WinAmp", str) == 0)
|
||||||
{
|
{
|
||||||
if (!g_Winamp)
|
parent->player = CPlayerWinamp::Create(WA_WINAMP);
|
||||||
{
|
|
||||||
g_Winamp = new CPlayerWinamp(WA_WINAMP);
|
|
||||||
}
|
|
||||||
parent->player = g_Winamp;
|
|
||||||
}
|
}
|
||||||
else if (_wcsicmp(L"WLM", str) == 0)
|
else if (_wcsicmp(L"WLM", str) == 0)
|
||||||
{
|
{
|
||||||
if (!g_WLM)
|
parent->player = CPlayerWLM::Create();
|
||||||
{
|
|
||||||
g_WLM = new CPlayerWLM();
|
|
||||||
}
|
|
||||||
parent->player = g_WLM;
|
|
||||||
}
|
}
|
||||||
else if (_wcsicmp(L"WMP", str) == 0)
|
else if (_wcsicmp(L"WMP", str) == 0)
|
||||||
{
|
{
|
||||||
if (!g_WMP)
|
parent->player = CPlayerWMP::Create();
|
||||||
{
|
|
||||||
g_WMP = new CPlayerWMP();
|
|
||||||
}
|
|
||||||
parent->player = g_WMP;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -331,6 +288,11 @@ void Finalize(HMODULE instance, UINT id)
|
|||||||
|
|
||||||
delete child;
|
delete child;
|
||||||
g_Measures.erase(i);
|
g_Measures.erase(i);
|
||||||
|
|
||||||
|
if (g_Measures.empty())
|
||||||
|
{
|
||||||
|
CInternet::Finalize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,8 +321,6 @@ UINT Update(UINT id)
|
|||||||
parent->trackCount != player->GetTrackCount())
|
parent->trackCount != player->GetTrackCount())
|
||||||
{
|
{
|
||||||
ExecuteCommand(parent->trackChangeAction, parent->window);
|
ExecuteCommand(parent->trackChangeAction, parent->window);
|
||||||
|
|
||||||
// TODO: First is true..
|
|
||||||
parent->trackCount = player->GetTrackCount();
|
parent->trackCount = player->GetTrackCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,6 +383,9 @@ LPCTSTR GetString(UINT id, UINT flags)
|
|||||||
case MEASURE_ALBUM:
|
case MEASURE_ALBUM:
|
||||||
return player->GetAlbum();
|
return player->GetAlbum();
|
||||||
|
|
||||||
|
case MEASURE_LYRICS:
|
||||||
|
return player->GetLyrics();
|
||||||
|
|
||||||
case MEASURE_COVER:
|
case MEASURE_COVER:
|
||||||
return player->GetCoverPath();
|
return player->GetCoverPath();
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ struct ParentMeasure
|
|||||||
UINT childCount;
|
UINT childCount;
|
||||||
UINT trackCount;
|
UINT trackCount;
|
||||||
CPlayer* player;
|
CPlayer* player;
|
||||||
HANDLE thread;
|
|
||||||
HWND window;
|
HWND window;
|
||||||
std::wstring name;
|
std::wstring name;
|
||||||
std::wstring iniFile;
|
std::wstring iniFile;
|
||||||
@ -35,7 +34,7 @@ struct ParentMeasure
|
|||||||
std::wstring playerPath;
|
std::wstring playerPath;
|
||||||
bool disableLeadingZero;
|
bool disableLeadingZero;
|
||||||
|
|
||||||
ParentMeasure() : player(NULL), thread(NULL) {}
|
ParentMeasure() : player(NULL) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ChildMeasure
|
struct ChildMeasure
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
|
|
||||||
|
extern std::wstring g_CachePath;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CPlayer
|
** CPlayer
|
||||||
**
|
**
|
||||||
@ -36,8 +38,11 @@ CPlayer::CPlayer() :
|
|||||||
m_Duration(),
|
m_Duration(),
|
||||||
m_Position(),
|
m_Position(),
|
||||||
m_Rating(),
|
m_Rating(),
|
||||||
m_Volume()
|
m_Volume(),
|
||||||
|
m_CriticalSection(),
|
||||||
|
m_InternetThread()
|
||||||
{
|
{
|
||||||
|
InitializeCriticalSection(&m_CriticalSection);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -48,6 +53,7 @@ CPlayer::CPlayer() :
|
|||||||
*/
|
*/
|
||||||
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
|
** ClearData
|
||||||
**
|
**
|
||||||
@ -125,6 +256,7 @@ void CPlayer::ClearData()
|
|||||||
m_Artist.clear();
|
m_Artist.clear();
|
||||||
m_Album.clear();
|
m_Album.clear();
|
||||||
m_Title.clear();
|
m_Title.clear();
|
||||||
|
m_Lyrics.clear();
|
||||||
m_FilePath.clear();
|
m_FilePath.clear();
|
||||||
m_CoverPath.clear();
|
m_CoverPath.clear();
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,11 @@
|
|||||||
#ifndef __PLAYER_H__
|
#ifndef __PLAYER_H__
|
||||||
#define __PLAYER_H__
|
#define __PLAYER_H__
|
||||||
|
|
||||||
|
#include "fileref.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include "Cover.h"
|
#include "Cover.h"
|
||||||
|
#include "Internet.h"
|
||||||
|
#include "Lyrics.h"
|
||||||
|
|
||||||
enum PLAYSTATE
|
enum PLAYSTATE
|
||||||
{
|
{
|
||||||
@ -45,8 +48,7 @@ enum MEASURETYPE
|
|||||||
MEASURE_FILE
|
MEASURE_FILE
|
||||||
};
|
};
|
||||||
|
|
||||||
class CPlayer :
|
class CPlayer
|
||||||
public CCover
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CPlayer();
|
CPlayer();
|
||||||
@ -61,6 +63,10 @@ public:
|
|||||||
bool IsInitialized() { return m_Initialized; }
|
bool IsInitialized() { return m_Initialized; }
|
||||||
UINT GetTrackCount() { return m_TrackCount; }
|
UINT GetTrackCount() { return m_TrackCount; }
|
||||||
|
|
||||||
|
std::wstring GetCacheFile();
|
||||||
|
void FindCover();
|
||||||
|
void FindLyrics();
|
||||||
|
|
||||||
virtual void Pause() {}
|
virtual void Pause() {}
|
||||||
virtual void Play() {}
|
virtual void Play() {}
|
||||||
virtual void Stop() {}
|
virtual void Stop() {}
|
||||||
@ -105,6 +111,12 @@ protected:
|
|||||||
UINT m_Position; // Current position in seconds
|
UINT m_Position; // Current position in seconds
|
||||||
UINT m_Rating; // Track rating from 0 to 100
|
UINT m_Rating; // Track rating from 0 to 100
|
||||||
UINT m_Volume; // Volume 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
|
#endif
|
@ -21,8 +21,9 @@
|
|||||||
#include "AIMP/aimp2_sdk.h"
|
#include "AIMP/aimp2_sdk.h"
|
||||||
#include "Winamp/wa_ipc.h"
|
#include "Winamp/wa_ipc.h"
|
||||||
|
|
||||||
extern CPlayer* g_AIMP;
|
CPlayer* CPlayerAIMP::c_Player = NULL;
|
||||||
|
|
||||||
|
// TODO
|
||||||
/*
|
/*
|
||||||
** CPlayerAIMP
|
** CPlayerAIMP
|
||||||
**
|
**
|
||||||
@ -30,10 +31,10 @@ extern CPlayer* g_AIMP;
|
|||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
CPlayerAIMP::CPlayerAIMP() : CPlayer(),
|
CPlayerAIMP::CPlayerAIMP() : CPlayer(),
|
||||||
m_FileMap(),
|
|
||||||
m_FileMapHandle(),
|
|
||||||
m_Window(),
|
m_Window(),
|
||||||
m_WinampWindow()
|
m_WinampWindow(),
|
||||||
|
m_FileMap(),
|
||||||
|
m_FileMapHandle()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,74 +46,69 @@ CPlayerAIMP::CPlayerAIMP() : CPlayer(),
|
|||||||
*/
|
*/
|
||||||
CPlayerAIMP::~CPlayerAIMP()
|
CPlayerAIMP::~CPlayerAIMP()
|
||||||
{
|
{
|
||||||
g_AIMP = NULL;
|
c_Player = NULL;
|
||||||
if (m_FileMap) UnmapViewOfFile(m_FileMap);
|
if (m_FileMap) UnmapViewOfFile(m_FileMap);
|
||||||
if (m_FileMapHandle) CloseHandle(m_FileMapHandle);
|
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");
|
if (!c_Player)
|
||||||
m_WinampWindow = FindWindow(L"Winamp v1.x", NULL);
|
|
||||||
|
|
||||||
if (m_Window)
|
|
||||||
{
|
{
|
||||||
m_FileMapHandle = OpenFileMapping(FILE_MAP_READ, FALSE, L"AIMP2_RemoteInfo");
|
c_Player = new CPlayerAIMP();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return c_Player;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CPlayerAIMP::CheckActive()
|
/*
|
||||||
|
** CheckWindow
|
||||||
|
**
|
||||||
|
** Try to find AIMP periodically.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
bool CPlayerAIMP::CheckWindow()
|
||||||
{
|
{
|
||||||
if (m_Window)
|
static DWORD oldTime = 0;
|
||||||
|
DWORD time = GetTickCount();
|
||||||
|
|
||||||
|
// Try to find AIMP every 5 seconds
|
||||||
|
if (time - oldTime > 5000)
|
||||||
{
|
{
|
||||||
if (!IsWindow(m_Window))
|
oldTime = time;
|
||||||
|
m_Window = FindWindow(L"AIMP2_RemoteInfo", L"AIMP2_RemoteInfo");
|
||||||
|
|
||||||
|
if (m_Window)
|
||||||
{
|
{
|
||||||
m_Window = NULL;
|
m_WinampWindow = FindWindow(L"Winamp v1.x", NULL);
|
||||||
m_WinampWindow = NULL;
|
|
||||||
if (m_FileMap) UnmapViewOfFile(m_FileMap);
|
m_FileMapHandle = OpenFileMapping(FILE_MAP_READ, FALSE, L"AIMP2_RemoteInfo");
|
||||||
if (m_FileMapHandle) CloseHandle(m_FileMapHandle);
|
if (m_FileMapHandle)
|
||||||
ClearData();
|
{
|
||||||
return false;
|
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 true;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
static DWORD oldTime = 0;
|
|
||||||
DWORD time = GetTickCount();
|
|
||||||
|
|
||||||
// Try to find AIMP every 5 seconds
|
return m_Initialized;
|
||||||
if (time - oldTime > 5000)
|
|
||||||
{
|
|
||||||
oldTime = time;
|
|
||||||
return Initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -123,29 +119,43 @@ bool CPlayerAIMP::CheckActive()
|
|||||||
*/
|
*/
|
||||||
void CPlayerAIMP::UpdateData()
|
void CPlayerAIMP::UpdateData()
|
||||||
{
|
{
|
||||||
static long oldFileSize;
|
static long oldFileSize = 0;
|
||||||
static UINT oldTitleLen;
|
static UINT oldTitleLen = 0;
|
||||||
|
|
||||||
if (!CheckActive())
|
if (!m_Initialized)
|
||||||
{
|
{
|
||||||
// Make sure AIMP is running
|
if (oldTitleLen != 0)
|
||||||
if (oldFileSize != 0)
|
|
||||||
{
|
{
|
||||||
oldFileSize = 0;
|
oldFileSize = 0;
|
||||||
oldTitleLen = 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);
|
m_State = (PLAYSTATE)SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_Player);
|
||||||
if (m_State == PLAYER_STOPPED)
|
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;
|
oldFileSize = 0;
|
||||||
oldTitleLen = 0;
|
oldTitleLen = 0;
|
||||||
ClearData();
|
ClearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't continue if AIMP has quit or is stopped
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +164,7 @@ void CPlayerAIMP::UpdateData()
|
|||||||
|
|
||||||
AIMP2FileInfo* info = (AIMP2FileInfo*)m_FileMap;
|
AIMP2FileInfo* info = (AIMP2FileInfo*)m_FileMap;
|
||||||
if (info->cbSizeOf > 0 &&
|
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)
|
info->nTitleLen != oldTitleLen)
|
||||||
{
|
{
|
||||||
oldFileSize = info->nFileSize;
|
oldFileSize = info->nFileSize;
|
||||||
@ -191,7 +201,12 @@ void CPlayerAIMP::UpdateData()
|
|||||||
// Find cover if needed
|
// Find cover if needed
|
||||||
if (m_HasCoverMeasure)
|
if (m_HasCoverMeasure)
|
||||||
{
|
{
|
||||||
GetCover(m_Artist, m_Title, m_FilePath, m_CoverPath);
|
FindCover();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_HasLyricsMeasure)
|
||||||
|
{
|
||||||
|
FindLyrics();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,9 @@
|
|||||||
class CPlayerAIMP : public CPlayer
|
class CPlayerAIMP : public CPlayer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CPlayerAIMP();
|
virtual ~CPlayerAIMP();
|
||||||
~CPlayerAIMP();
|
|
||||||
|
static CPlayer* Create();
|
||||||
|
|
||||||
virtual void UpdateData();
|
virtual void UpdateData();
|
||||||
|
|
||||||
@ -40,14 +41,19 @@ public:
|
|||||||
virtual void ClosePlayer();
|
virtual void ClosePlayer();
|
||||||
virtual void OpenPlayer(std::wstring& path);
|
virtual void OpenPlayer(std::wstring& path);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CPlayerAIMP();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool Initialize();
|
bool Initialize();
|
||||||
bool CheckActive();
|
bool CheckWindow();
|
||||||
|
|
||||||
|
static CPlayer* c_Player;
|
||||||
|
|
||||||
LPVOID m_FileMap;
|
|
||||||
HANDLE m_FileMapHandle;
|
|
||||||
HWND m_Window; // AIMP window
|
HWND m_Window; // AIMP window
|
||||||
HWND m_WinampWindow; // AIMP Winamp API window
|
HWND m_WinampWindow; // AIMP Winamp API window
|
||||||
|
LPVOID m_FileMap;
|
||||||
|
HANDLE m_FileMapHandle;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include "PlayerCAD.h"
|
#include "PlayerCAD.h"
|
||||||
#include "CAD/cad_sdk.h"
|
#include "CAD/cad_sdk.h"
|
||||||
|
|
||||||
extern CPlayer* g_CAD;
|
CPlayer* CPlayerCAD::c_Player = NULL;
|
||||||
extern std::wstring g_SettingsFile;
|
extern std::wstring g_SettingsFile;
|
||||||
|
|
||||||
// This player emulates the CD Art Display IPC interface, which is supported by
|
// This player emulates the CD Art Display IPC interface, which is supported by
|
||||||
@ -47,10 +47,26 @@ CPlayerCAD::CPlayerCAD() : CPlayer(),
|
|||||||
*/
|
*/
|
||||||
CPlayerCAD::~CPlayerCAD()
|
CPlayerCAD::~CPlayerCAD()
|
||||||
{
|
{
|
||||||
g_CAD = NULL;
|
c_Player = NULL;
|
||||||
Uninitialize();
|
Uninitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Create
|
||||||
|
**
|
||||||
|
** Creates a shared class object.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
CPlayer* CPlayerCAD::Create()
|
||||||
|
{
|
||||||
|
if (!c_Player)
|
||||||
|
{
|
||||||
|
c_Player = new CPlayerCAD();
|
||||||
|
}
|
||||||
|
|
||||||
|
return c_Player;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Initialize
|
** Initialize
|
||||||
**
|
**
|
||||||
@ -113,6 +129,7 @@ void CPlayerCAD::Initialize()
|
|||||||
|
|
||||||
if (m_PlayerWindow)
|
if (m_PlayerWindow)
|
||||||
{
|
{
|
||||||
|
m_Initialized = true;
|
||||||
SendMessage(m_PlayerWindow, WM_USER, (WPARAM)m_Window, IPC_SET_CALLBACK_HWND);
|
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);
|
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)
|
LRESULT CALLBACK CPlayerCAD::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
static CPlayerCAD* p;
|
static CPlayerCAD* player;
|
||||||
|
|
||||||
switch (msg)
|
switch (msg)
|
||||||
{
|
{
|
||||||
case WM_CREATE:
|
case WM_CREATE:
|
||||||
// Get pointer to the CPlayerCAD class from the CreateWindow call
|
// Get pointer to the CPlayerCAD class from the CreateWindow call
|
||||||
p = (CPlayerCAD*)((CREATESTRUCT*)lParam)->lpCreateParams;
|
player = (CPlayerCAD*)((CREATESTRUCT*)lParam)->lpCreateParams;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case WM_DESTROY:
|
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;
|
return 0;
|
||||||
|
|
||||||
case WM_USER:
|
case WM_USER:
|
||||||
switch (lParam)
|
switch (lParam)
|
||||||
{
|
{
|
||||||
case IPC_TRACK_CHANGED_NOTIFICATION:
|
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;
|
break;
|
||||||
|
|
||||||
case IPC_PLAYER_STATE_CHANGED_NOTIFICATION:
|
case IPC_PLAYER_STATE_CHANGED_NOTIFICATION:
|
||||||
p->m_State = (PLAYSTATE)wParam;
|
player->m_State = (PLAYSTATE)wParam;
|
||||||
if (p->m_State == PLAYER_STOPPED)
|
if (player->m_State == PLAYER_STOPPED)
|
||||||
{
|
{
|
||||||
p->ClearData();
|
player->ClearData();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPC_SHUTDOWN_NOTIFICATION:
|
case IPC_SHUTDOWN_NOTIFICATION:
|
||||||
p->m_PlayerWindow = NULL;
|
player->m_Initialized = false;
|
||||||
p->ClearData();
|
player->ClearData();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -184,19 +201,19 @@ LRESULT CALLBACK CPlayerCAD::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
|
|||||||
if (cds->dwData == IPC_CURRENT_TRACK_INFO)
|
if (cds->dwData == IPC_CURRENT_TRACK_INFO)
|
||||||
{
|
{
|
||||||
// TODO: Sent on track update?
|
// TODO: Sent on track update?
|
||||||
++p->m_TrackCount;
|
++player->m_TrackCount;
|
||||||
|
|
||||||
std::wstring data = (WCHAR*)cds->lpData;
|
std::wstring data = (WCHAR*)cds->lpData;
|
||||||
std::wstring::size_type len = data.find_first_of(L'\t');
|
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);
|
data.erase(0, ++len);
|
||||||
|
|
||||||
len = data.find_first_of(L'\t');
|
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);
|
data.erase(0, ++len);
|
||||||
|
|
||||||
len = data.find_first_of(L'\t');
|
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);
|
data.erase(0, ++len);
|
||||||
|
|
||||||
len = data.find_first_of(L'\t'); // Skip genre
|
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);
|
data.erase(0, ++len);
|
||||||
|
|
||||||
len = data.find_first_of(L'\t');
|
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);
|
data.erase(0, ++len);
|
||||||
|
|
||||||
len = data.find_first_of(L'\t');
|
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);
|
data.erase(0, ++len);
|
||||||
|
|
||||||
len = data.find_first_of(L'\t');
|
len = data.find_first_of(L'\t');
|
||||||
UINT rating = (_wtoi(data.substr(0, len).c_str()) + 1) / 2; // From 0 - 10 to 0 - 5
|
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);
|
data.erase(0, ++len);
|
||||||
|
|
||||||
len = data.find_first_of(L'\t');
|
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);
|
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;
|
std::wstring data = (WCHAR*)cds->lpData;
|
||||||
if (data[0] == L'1')
|
if (data[0] == L'1')
|
||||||
@ -238,7 +260,7 @@ LRESULT CALLBACK CPlayerCAD::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
|
|||||||
data.erase(0, ++len);
|
data.erase(0, ++len);
|
||||||
|
|
||||||
len = data.find_first_of(L'\t');
|
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);
|
data.erase(0, ++len);
|
||||||
|
|
||||||
LPCTSTR classSz = className.empty() ? NULL : className.c_str();
|
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"ClassName", classSz, file);
|
||||||
WritePrivateProfileString(L"NowPlaying.dll", L"WindowName", windowSz, 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()
|
void CPlayerCAD::ClosePlayer()
|
||||||
{
|
{
|
||||||
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_CLOSE_PLAYER);
|
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_CLOSE_PLAYER);
|
||||||
m_PlayerWindow = NULL;
|
// TODO
|
||||||
|
m_Initialized = false;
|
||||||
ClearData();
|
ClearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,8 +24,9 @@
|
|||||||
class CPlayerCAD : public CPlayer
|
class CPlayerCAD : public CPlayer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CPlayerCAD();
|
virtual ~CPlayerCAD();
|
||||||
~CPlayerCAD();
|
|
||||||
|
static CPlayer* Create();
|
||||||
|
|
||||||
virtual void UpdateData();
|
virtual void UpdateData();
|
||||||
|
|
||||||
@ -40,11 +41,16 @@ public:
|
|||||||
virtual void ClosePlayer();
|
virtual void ClosePlayer();
|
||||||
virtual void OpenPlayer(std::wstring& path);
|
virtual void OpenPlayer(std::wstring& path);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CPlayerCAD();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Initialize();
|
void Initialize();
|
||||||
void Uninitialize();
|
void Uninitialize();
|
||||||
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
static CPlayer* c_Player;
|
||||||
|
|
||||||
HWND m_Window;
|
HWND m_Window;
|
||||||
HWND m_PlayerWindow;
|
HWND m_PlayerWindow;
|
||||||
std::wstring m_PlayerPath;
|
std::wstring m_PlayerPath;
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#include "PlayerFoobar.h"
|
#include "PlayerFoobar.h"
|
||||||
|
|
||||||
extern CPlayer* g_Foobar;
|
CPlayer* CPlayerFoobar::c_Player = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CPlayerFoobar
|
** CPlayerFoobar
|
||||||
@ -42,10 +42,26 @@ CPlayerFoobar::CPlayerFoobar() : CPlayer(),
|
|||||||
*/
|
*/
|
||||||
CPlayerFoobar::~CPlayerFoobar()
|
CPlayerFoobar::~CPlayerFoobar()
|
||||||
{
|
{
|
||||||
g_Foobar = NULL;
|
c_Player = NULL;
|
||||||
Uninitialize();
|
Uninitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Create
|
||||||
|
**
|
||||||
|
** Creates a shared class object.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
CPlayer* CPlayerFoobar::Create()
|
||||||
|
{
|
||||||
|
if (!c_Player)
|
||||||
|
{
|
||||||
|
c_Player = new CPlayerFoobar();
|
||||||
|
}
|
||||||
|
|
||||||
|
return c_Player;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Initialize
|
** Initialize
|
||||||
**
|
**
|
||||||
@ -89,6 +105,7 @@ void CPlayerFoobar::Initialize()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
m_Initialized = true;
|
||||||
SendMessage(m_FooWindow, WM_USER, (WPARAM)m_Window, FOO_SETCALLBACK);
|
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;
|
break;
|
||||||
|
|
||||||
case FOO_PLAYERQUIT:
|
case FOO_PLAYERQUIT:
|
||||||
player->m_FooWindow = NULL;
|
player->m_Initialized = false;
|
||||||
player->ClearData();
|
player->ClearData();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -221,7 +238,12 @@ LRESULT CALLBACK CPlayerFoobar::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
|
|||||||
|
|
||||||
if (player->m_HasCoverMeasure || player->m_InstanceCount == 0)
|
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)
|
void CPlayerFoobar::OpenPlayer(std::wstring& path)
|
||||||
{
|
{
|
||||||
if (!m_FooWindow)
|
if (!m_Initialized)
|
||||||
{
|
{
|
||||||
if (path.empty())
|
if (path.empty())
|
||||||
{
|
{
|
||||||
|
@ -24,8 +24,9 @@
|
|||||||
class CPlayerFoobar : public CPlayer
|
class CPlayerFoobar : public CPlayer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CPlayerFoobar();
|
virtual ~CPlayerFoobar();
|
||||||
~CPlayerFoobar();
|
|
||||||
|
static CPlayer* Create();
|
||||||
|
|
||||||
virtual void UpdateData();
|
virtual void UpdateData();
|
||||||
|
|
||||||
@ -40,6 +41,9 @@ public:
|
|||||||
virtual void ClosePlayer();
|
virtual void ClosePlayer();
|
||||||
virtual void OpenPlayer(std::wstring& path);
|
virtual void OpenPlayer(std::wstring& path);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CPlayerFoobar();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum FOOMESSAGE
|
enum FOOMESSAGE
|
||||||
{
|
{
|
||||||
@ -73,6 +77,8 @@ private:
|
|||||||
void Uninitialize();
|
void Uninitialize();
|
||||||
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
static CPlayer* c_Player;
|
||||||
|
|
||||||
HWND m_Window; // Our reciever window
|
HWND m_Window; // Our reciever window
|
||||||
HWND m_FooWindow; // Foobar receiver window
|
HWND m_FooWindow; // Foobar receiver window
|
||||||
};
|
};
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#include "PlayerITunes.h"
|
#include "PlayerITunes.h"
|
||||||
|
|
||||||
extern CPlayer* g_iTunes;
|
CPlayer* CPlayerITunes::c_Player = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CEventHandler
|
** CEventHandler
|
||||||
@ -129,11 +129,27 @@ CPlayerITunes::CPlayerITunes() : CPlayer(),
|
|||||||
*/
|
*/
|
||||||
CPlayerITunes::~CPlayerITunes()
|
CPlayerITunes::~CPlayerITunes()
|
||||||
{
|
{
|
||||||
g_iTunes = NULL;
|
c_Player = NULL;
|
||||||
Uninitialize();
|
Uninitialize();
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Create
|
||||||
|
**
|
||||||
|
** Creates a shared class object.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
CPlayer* CPlayerITunes::Create()
|
||||||
|
{
|
||||||
|
if (!c_Player)
|
||||||
|
{
|
||||||
|
c_Player = new CPlayerITunes();
|
||||||
|
}
|
||||||
|
|
||||||
|
return c_Player;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Initialize
|
** Initialize
|
||||||
**
|
**
|
||||||
@ -216,7 +232,6 @@ void CPlayerITunes::Uninitialize()
|
|||||||
if (m_Initialized)
|
if (m_Initialized)
|
||||||
{
|
{
|
||||||
m_Initialized = false;
|
m_Initialized = false;
|
||||||
m_UserQuitPrompt = true;
|
|
||||||
if (m_iTunes)
|
if (m_iTunes)
|
||||||
{
|
{
|
||||||
m_iTunes->Release();
|
m_iTunes->Release();
|
||||||
@ -304,6 +319,7 @@ void CPlayerITunes::OnTrackChange()
|
|||||||
track->get_Duration(&tmpVal);
|
track->get_Duration(&tmpVal);
|
||||||
m_Duration = (UINT)tmpVal;
|
m_Duration = (UINT)tmpVal;
|
||||||
|
|
||||||
|
// Rating is 0 - 100, divide to 0 - 5
|
||||||
track->get_Rating(&tmpVal);
|
track->get_Rating(&tmpVal);
|
||||||
tmpVal /= 20L;
|
tmpVal /= 20L;
|
||||||
m_Rating = (UINT)tmpVal;
|
m_Rating = (UINT)tmpVal;
|
||||||
@ -319,45 +335,54 @@ void CPlayerITunes::OnTrackChange()
|
|||||||
++m_TrackCount;
|
++m_TrackCount;
|
||||||
m_FilePath = tmpStr;
|
m_FilePath = tmpStr;
|
||||||
|
|
||||||
if (m_HasCoverMeasure && !GetCachedCover(m_Artist, m_Title, m_CoverPath))
|
if (m_HasCoverMeasure)
|
||||||
{
|
{
|
||||||
// Art not in cache, check for embedded art
|
m_CoverPath = GetCacheFile();
|
||||||
IITArtworkCollection* artworkCollection;
|
if (!CCover::GetCached(m_CoverPath))
|
||||||
hr = track->get_Artwork(&artworkCollection);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
{
|
||||||
long count;
|
// Art not in cache, check for embedded art through iTunes interface
|
||||||
artworkCollection->get_Count(&count);
|
IITArtworkCollection* artworkCollection;
|
||||||
|
hr = track->get_Artwork(&artworkCollection);
|
||||||
|
|
||||||
if (count > 0)
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
IITArtwork* artwork;
|
long count;
|
||||||
hr = artworkCollection->get_Item(1, &artwork);
|
artworkCollection->get_Count(&count);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (count > 0)
|
||||||
{
|
{
|
||||||
tmpStr = m_CoverPath.c_str();
|
IITArtwork* artwork;
|
||||||
hr = artwork->SaveArtworkToFile(tmpStr);
|
hr = artworkCollection->get_Item(1, &artwork);
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
m_CoverPath.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
m_CoverPath.clear();
|
m_CoverPath.clear();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
artworkCollection->Release();
|
if (m_HasLyricsMeasure)
|
||||||
}
|
{
|
||||||
else
|
FindLyrics();
|
||||||
{
|
|
||||||
m_CoverPath.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,9 @@
|
|||||||
class CPlayerITunes : public CPlayer
|
class CPlayerITunes : public CPlayer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CPlayerITunes();
|
virtual ~CPlayerITunes();
|
||||||
~CPlayerITunes();
|
|
||||||
|
static CPlayer* Create();
|
||||||
|
|
||||||
virtual void UpdateData();
|
virtual void UpdateData();
|
||||||
|
|
||||||
@ -51,6 +52,9 @@ public:
|
|||||||
virtual void ClosePlayer();
|
virtual void ClosePlayer();
|
||||||
virtual void OpenPlayer(std::wstring& path);
|
virtual void OpenPlayer(std::wstring& path);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CPlayerITunes();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class CEventHandler : public _IiTunesEvents
|
class CEventHandler : public _IiTunesEvents
|
||||||
{
|
{
|
||||||
@ -83,6 +87,8 @@ private:
|
|||||||
void OnVolumeChange(int volume);
|
void OnVolumeChange(int volume);
|
||||||
bool CheckWindow();
|
bool CheckWindow();
|
||||||
|
|
||||||
|
static CPlayer* c_Player;
|
||||||
|
|
||||||
bool m_UserQuitPrompt;
|
bool m_UserQuitPrompt;
|
||||||
IiTunes* m_iTunes;
|
IiTunes* m_iTunes;
|
||||||
CEventHandler* m_iTunesEvent;
|
CEventHandler* m_iTunesEvent;
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#include "PlayerSpotify.h"
|
#include "PlayerSpotify.h"
|
||||||
|
|
||||||
extern CPlayer* g_Spotify;
|
CPlayer* CPlayerSpotify::c_Player = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CPlayerSpotify
|
** CPlayerSpotify
|
||||||
@ -40,7 +40,23 @@ CPlayerSpotify::CPlayerSpotify() : CPlayer(),
|
|||||||
*/
|
*/
|
||||||
CPlayerSpotify::~CPlayerSpotify()
|
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_Title = track;
|
||||||
m_Artist = artist;
|
m_Artist = artist;
|
||||||
++m_TrackCount;
|
++m_TrackCount;
|
||||||
|
|
||||||
|
if (m_HasLyricsMeasure)
|
||||||
|
{
|
||||||
|
FindLyrics();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,9 @@
|
|||||||
class CPlayerSpotify : public CPlayer
|
class CPlayerSpotify : public CPlayer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CPlayerSpotify();
|
virtual ~CPlayerSpotify();
|
||||||
~CPlayerSpotify();
|
|
||||||
|
static CPlayer* Create();
|
||||||
|
|
||||||
virtual void Pause() { return Play(); }
|
virtual void Pause() { return Play(); }
|
||||||
virtual void Play();
|
virtual void Play();
|
||||||
@ -36,6 +37,9 @@ public:
|
|||||||
virtual void OpenPlayer(std::wstring& path);
|
virtual void OpenPlayer(std::wstring& path);
|
||||||
virtual void UpdateData();
|
virtual void UpdateData();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CPlayerSpotify();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum SPOTIFYCOMMAND
|
enum SPOTIFYCOMMAND
|
||||||
{
|
{
|
||||||
@ -50,6 +54,8 @@ private:
|
|||||||
|
|
||||||
bool CheckWindow();
|
bool CheckWindow();
|
||||||
|
|
||||||
|
static CPlayer* c_Player;
|
||||||
|
|
||||||
HWND m_Window;
|
HWND m_Window;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#include "PlayerWLM.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
|
// This player emulates the MSN/WLM Messenger 'Listening to' interface, which is
|
||||||
// supported by OpenPandora, Last.fm, Media Player Classic, TTPlayer, Zune, etc.
|
// supported by OpenPandora, Last.fm, Media Player Classic, TTPlayer, Zune, etc.
|
||||||
@ -54,6 +54,8 @@ CPlayerWLM::CPlayerWLM() : CPlayer(),
|
|||||||
NULL,
|
NULL,
|
||||||
hInstance,
|
hInstance,
|
||||||
this);
|
this);
|
||||||
|
|
||||||
|
m_Initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -64,11 +66,27 @@ CPlayerWLM::CPlayerWLM() : CPlayer(),
|
|||||||
*/
|
*/
|
||||||
CPlayerWLM::~CPlayerWLM()
|
CPlayerWLM::~CPlayerWLM()
|
||||||
{
|
{
|
||||||
g_WLM = NULL;
|
c_Player = NULL;
|
||||||
DestroyWindow(m_Window);
|
DestroyWindow(m_Window);
|
||||||
UnregisterClass(L"MsnMsgrUIManager", GetModuleHandle(NULL));
|
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)
|
LRESULT CALLBACK CPlayerWLM::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
static CPlayerWLM* player;
|
static CPlayerWLM* player;
|
||||||
@ -99,6 +117,7 @@ LRESULT CALLBACK CPlayerWLM::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
|
|||||||
|
|
||||||
if (playing)
|
if (playing)
|
||||||
{
|
{
|
||||||
|
++player->m_TrackCount;
|
||||||
player->m_State = PLAYER_PLAYING;
|
player->m_State = PLAYER_PLAYING;
|
||||||
data.erase(0, 3); // Get rid of the status
|
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'\\');
|
len = data.find_first_of(L'\\');
|
||||||
player->m_Album = data.substr(0, len);
|
player->m_Album = data.substr(0, len);
|
||||||
|
|
||||||
|
if (player->m_HasLyricsMeasure)
|
||||||
|
{
|
||||||
|
player->FindLyrics();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -24,8 +24,9 @@
|
|||||||
class CPlayerWLM : public CPlayer
|
class CPlayerWLM : public CPlayer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CPlayerWLM();
|
virtual ~CPlayerWLM();
|
||||||
~CPlayerWLM();
|
|
||||||
|
static CPlayer* Create();
|
||||||
|
|
||||||
virtual void UpdateData();
|
virtual void UpdateData();
|
||||||
|
|
||||||
@ -35,10 +36,15 @@ public:
|
|||||||
virtual void Next();
|
virtual void Next();
|
||||||
virtual void Previous();
|
virtual void Previous();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CPlayerWLM();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
void SendKeyInput(WORD key);
|
void SendKeyInput(WORD key);
|
||||||
|
|
||||||
|
static CPlayer* c_Player;
|
||||||
|
|
||||||
HWND m_Window;
|
HWND m_Window;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#include "PlayerWMP.h"
|
#include "PlayerWMP.h"
|
||||||
|
|
||||||
extern CPlayer* g_WMP;
|
CPlayer* CPlayerWMP::c_Player = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CRemoteHost
|
** CRemoteHost
|
||||||
@ -170,11 +170,27 @@ CPlayerWMP::CPlayerWMP() : CPlayer(),
|
|||||||
*/
|
*/
|
||||||
CPlayerWMP::~CPlayerWMP()
|
CPlayerWMP::~CPlayerWMP()
|
||||||
{
|
{
|
||||||
g_WMP = NULL;
|
c_Player = NULL;
|
||||||
Uninitialize();
|
Uninitialize();
|
||||||
m_ComModule.Term();
|
m_ComModule.Term();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Create
|
||||||
|
**
|
||||||
|
** Creates a shared class object.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
CPlayer* CPlayerWMP::Create()
|
||||||
|
{
|
||||||
|
if (!c_Player)
|
||||||
|
{
|
||||||
|
c_Player = new CPlayerWMP();
|
||||||
|
}
|
||||||
|
|
||||||
|
return c_Player;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Initialize
|
** Initialize
|
||||||
**
|
**
|
||||||
@ -450,9 +466,14 @@ void CPlayerWMP::UpdateData()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GetCover(m_Artist, m_Title, m_FilePath, m_CoverPath);
|
FindCover();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_HasLyricsMeasure)
|
||||||
|
{
|
||||||
|
FindLyrics();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,9 @@
|
|||||||
class CPlayerWMP : public CPlayer
|
class CPlayerWMP : public CPlayer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CPlayerWMP();
|
virtual ~CPlayerWMP();
|
||||||
~CPlayerWMP();
|
|
||||||
|
static CPlayer* Create();
|
||||||
|
|
||||||
virtual void UpdateData();
|
virtual void UpdateData();
|
||||||
|
|
||||||
@ -50,6 +51,9 @@ public:
|
|||||||
virtual void OpenPlayer(std::wstring& path);
|
virtual void OpenPlayer(std::wstring& path);
|
||||||
virtual void ClosePlayer();
|
virtual void ClosePlayer();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CPlayerWMP();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class CRemoteHost :
|
class CRemoteHost :
|
||||||
public CComObjectRootEx<CComSingleThreadModel>,
|
public CComObjectRootEx<CComSingleThreadModel>,
|
||||||
@ -129,6 +133,8 @@ private:
|
|||||||
void Initialize();
|
void Initialize();
|
||||||
void Uninitialize();
|
void Uninitialize();
|
||||||
|
|
||||||
|
static CPlayer* c_Player;
|
||||||
|
|
||||||
bool m_TrackChanged;
|
bool m_TrackChanged;
|
||||||
HWND m_Window;
|
HWND m_Window;
|
||||||
CAxWindow* m_AxWindow;
|
CAxWindow* m_AxWindow;
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#include "Winamp/wa_ipc.h"
|
#include "Winamp/wa_ipc.h"
|
||||||
#include "Winamp/wa_cmd.h"
|
#include "Winamp/wa_cmd.h"
|
||||||
|
|
||||||
extern CPlayer* g_Winamp;
|
CPlayer* CPlayerWinamp::c_Player = NULL;
|
||||||
|
|
||||||
// This player retrieves data through the Winamp IPC interface.
|
// This player retrieves data through the Winamp IPC interface.
|
||||||
|
|
||||||
@ -32,9 +32,11 @@ extern CPlayer* g_Winamp;
|
|||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
CPlayerWinamp::CPlayerWinamp(WINAMPTYPE type) : CPlayer(),
|
CPlayerWinamp::CPlayerWinamp(WINAMPTYPE type) : CPlayer(),
|
||||||
m_WinampType(type),
|
m_Window(),
|
||||||
m_UseUnicodeAPI(false),
|
m_UseUnicodeAPI(false),
|
||||||
m_Window()
|
m_WinampType(type),
|
||||||
|
m_WinampHandle(),
|
||||||
|
m_WinampAddress()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,10 +48,26 @@ CPlayerWinamp::CPlayerWinamp(WINAMPTYPE type) : CPlayer(),
|
|||||||
*/
|
*/
|
||||||
CPlayerWinamp::~CPlayerWinamp()
|
CPlayerWinamp::~CPlayerWinamp()
|
||||||
{
|
{
|
||||||
g_Winamp = NULL;
|
c_Player = NULL;
|
||||||
if (m_WinampHandle) CloseHandle(m_WinampHandle);
|
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
|
** CheckWindow
|
||||||
**
|
**
|
||||||
@ -204,63 +222,70 @@ void CPlayerWinamp::UpdateData()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find cover if needed
|
if (m_HasLyricsMeasure)
|
||||||
if (m_HasCoverMeasure &&
|
|
||||||
!GetCachedCover(m_Artist, m_Title, m_CoverPath) &&
|
|
||||||
!GetEmbeddedCover(fr, m_CoverPath))
|
|
||||||
{
|
{
|
||||||
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 trackFolder = CCover::GetFileFolder(m_FilePath);
|
||||||
std::wstring file = m_Album;
|
|
||||||
std::wstring::size_type end = file.length();
|
if (!m_Album.empty())
|
||||||
for (std::wstring::size_type pos = 0; pos < end; ++pos)
|
|
||||||
{
|
{
|
||||||
// Replace reserved chars according to Winamp specs
|
// Winamp stores covers usually as %album%.jpg
|
||||||
switch (file[pos])
|
std::wstring file = m_Album;
|
||||||
|
std::wstring::size_type end = file.length();
|
||||||
|
for (std::wstring::size_type pos = 0; pos < end; ++pos)
|
||||||
{
|
{
|
||||||
case L'?':
|
// Replace reserved chars according to Winamp specs
|
||||||
case L'*':
|
switch (file[pos])
|
||||||
case L'|':
|
{
|
||||||
file[pos] = L'_';
|
case L'?':
|
||||||
break;
|
case L'*':
|
||||||
|
case L'|':
|
||||||
|
file[pos] = L'_';
|
||||||
|
break;
|
||||||
|
|
||||||
case L'/':
|
case L'/':
|
||||||
case L'\\':
|
case L'\\':
|
||||||
case L':':
|
case L':':
|
||||||
file[pos] = L'-';
|
file[pos] = L'-';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case L'\"':
|
case L'\"':
|
||||||
file[pos] = L'\'';
|
file[pos] = L'\'';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case L'<':
|
case L'<':
|
||||||
file[pos] = L'(';
|
file[pos] = L'(';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case L'>':
|
case L'>':
|
||||||
file[pos] = L')';
|
file[pos] = L')';
|
||||||
break;
|
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
|
// Nothing found
|
||||||
return;
|
m_CoverPath.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetLocalCover(L"cover", trackFolder, m_CoverPath) &&
|
|
||||||
!GetLocalCover(L"folder", trackFolder, m_CoverPath))
|
|
||||||
{
|
|
||||||
// Nothing found
|
|
||||||
m_CoverPath.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,9 @@ enum WINAMPTYPE
|
|||||||
class CPlayerWinamp : public CPlayer
|
class CPlayerWinamp : public CPlayer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CPlayerWinamp(WINAMPTYPE type);
|
virtual ~CPlayerWinamp();
|
||||||
~CPlayerWinamp();
|
|
||||||
|
static CPlayer* Create(WINAMPTYPE type);
|
||||||
|
|
||||||
virtual void UpdateData();
|
virtual void UpdateData();
|
||||||
|
|
||||||
@ -46,12 +47,17 @@ public:
|
|||||||
virtual void ClosePlayer();
|
virtual void ClosePlayer();
|
||||||
virtual void OpenPlayer(std::wstring& path);
|
virtual void OpenPlayer(std::wstring& path);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CPlayerWinamp(WINAMPTYPE type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool CheckWindow();
|
bool CheckWindow();
|
||||||
|
|
||||||
|
static CPlayer* c_Player;
|
||||||
|
|
||||||
|
HWND m_Window; // Winamp window
|
||||||
bool m_UseUnicodeAPI;
|
bool m_UseUnicodeAPI;
|
||||||
WINAMPTYPE m_WinampType;
|
WINAMPTYPE m_WinampType;
|
||||||
HWND m_Window; // Winamp window
|
|
||||||
HANDLE m_WinampHandle; // Handle to Winamp process
|
HANDLE m_WinampHandle; // Handle to Winamp process
|
||||||
LPCVOID m_WinampAddress;
|
LPCVOID m_WinampAddress;
|
||||||
};
|
};
|
||||||
|
@ -122,6 +122,7 @@
|
|||||||
<ProgramDatabaseFile>.\x32/Debug/NowPlaying.pdb</ProgramDatabaseFile>
|
<ProgramDatabaseFile>.\x32/Debug/NowPlaying.pdb</ProgramDatabaseFile>
|
||||||
<ImportLibrary>.\x32/Debug/NowPlaying.lib</ImportLibrary>
|
<ImportLibrary>.\x32/Debug/NowPlaying.lib</ImportLibrary>
|
||||||
<TargetMachine>MachineX86</TargetMachine>
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
<AdditionalDependencies>WinInet.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -162,6 +163,7 @@
|
|||||||
<ProgramDatabaseFile>.\x64/Debug/NowPlaying.pdb</ProgramDatabaseFile>
|
<ProgramDatabaseFile>.\x64/Debug/NowPlaying.pdb</ProgramDatabaseFile>
|
||||||
<ImportLibrary>.\x64/Debug/NowPlaying.lib</ImportLibrary>
|
<ImportLibrary>.\x64/Debug/NowPlaying.lib</ImportLibrary>
|
||||||
<TargetMachine>MachineX64</TargetMachine>
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
<AdditionalDependencies>WinInet.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@ -198,7 +200,7 @@
|
|||||||
<Culture>0x0409</Culture>
|
<Culture>0x0409</Culture>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>Rainmeter.lib;Wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Rainmeter.lib;WinInet.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<OutputFile>../../TestBench/x32/Release/Plugins/NowPlaying.dll</OutputFile>
|
<OutputFile>../../TestBench/x32/Release/Plugins/NowPlaying.dll</OutputFile>
|
||||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
<AdditionalLibraryDirectories>..\..\Library\x32\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\..\Library\x32\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
@ -243,7 +245,7 @@
|
|||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalOptions>/LTCG %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/LTCG %(AdditionalOptions)</AdditionalOptions>
|
||||||
<AdditionalDependencies>Rainmeter.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Rainmeter.lib;WinInet.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<OutputFile>../../TestBench/x64/Release/Plugins/NowPlaying.dll</OutputFile>
|
<OutputFile>../../TestBench/x64/Release/Plugins/NowPlaying.dll</OutputFile>
|
||||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
<AdditionalLibraryDirectories>..\..\Library\x64\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\..\Library\x64\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
@ -256,6 +258,8 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="Cover.cpp" />
|
<ClCompile Include="Cover.cpp" />
|
||||||
|
<ClCompile Include="Internet.cpp" />
|
||||||
|
<ClCompile Include="Lyrics.cpp" />
|
||||||
<ClCompile Include="NowPlaying.cpp" />
|
<ClCompile Include="NowPlaying.cpp" />
|
||||||
<ClCompile Include="Player.cpp" />
|
<ClCompile Include="Player.cpp" />
|
||||||
<ClCompile Include="PlayerAIMP.cpp" />
|
<ClCompile Include="PlayerAIMP.cpp" />
|
||||||
@ -344,6 +348,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Cover.h" />
|
<ClInclude Include="Cover.h" />
|
||||||
|
<ClInclude Include="Internet.h" />
|
||||||
|
<ClInclude Include="Lyrics.h" />
|
||||||
<ClInclude Include="NowPlaying.h" />
|
<ClInclude Include="NowPlaying.h" />
|
||||||
<ClInclude Include="Player.h" />
|
<ClInclude Include="Player.h" />
|
||||||
<ClInclude Include="PlayerAIMP.h" />
|
<ClInclude Include="PlayerAIMP.h" />
|
||||||
|
@ -267,6 +267,12 @@
|
|||||||
<ClCompile Include="Cover.cpp">
|
<ClCompile Include="Cover.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Lyrics.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Internet.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="SDKs\AIMP\aimp2_sdk.h">
|
<ClInclude Include="SDKs\AIMP\aimp2_sdk.h">
|
||||||
@ -326,6 +332,12 @@
|
|||||||
<ClInclude Include="Cover.h">
|
<ClInclude Include="Cover.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Lyrics.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Internet.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="PluginNowPlaying.rc">
|
<ResourceCompile Include="PluginNowPlaying.rc">
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
#define __STDAFX_H__
|
#define __STDAFX_H__
|
||||||
|
|
||||||
// WinAPI
|
// WinAPI
|
||||||
#include <windows.h>
|
#include <Windows.h>
|
||||||
|
#include <WinInet.h>
|
||||||
|
|
||||||
// STL
|
// STL
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -32,7 +33,4 @@
|
|||||||
// Rainmeter's exported functions
|
// Rainmeter's exported functions
|
||||||
#include "../../Library/Export.h"
|
#include "../../Library/Export.h"
|
||||||
|
|
||||||
// TagLib
|
|
||||||
#include "fileref.h"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user