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:
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;
|
||||
}
|
Reference in New Issue
Block a user