mirror of
https://github.com/chibicitiberiu/rainmeter-studio.git
synced 2024-02-24 04:33:31 +00:00
NowPlayingPlugin:
- Fixed that PlayerName=, TrackChangeAction=, and DisableLeadingZero= were global (i.e. only usable from the first loaded skin) - Code refactoring and cleanup
This commit is contained in:
parent
67cc4c7c6c
commit
6aa004eb22
332
Plugins/PluginNowPlaying/Cover.cpp
Normal file
332
Plugins/PluginNowPlaying/Cover.cpp
Normal file
@ -0,0 +1,332 @@
|
||||
/*
|
||||
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 "Cover.h"
|
||||
|
||||
extern std::wstring g_CachePath;
|
||||
|
||||
/*
|
||||
** GetCover
|
||||
**
|
||||
** Default implementation for getting cover.
|
||||
**
|
||||
*/
|
||||
void CCover::GetCover(const std::wstring& artist, const std::wstring& title, const std::wstring& file, std::wstring& target)
|
||||
{
|
||||
if (!GetCachedCover(artist, title, target))
|
||||
{
|
||||
TagLib::FileRef fr(file.c_str());
|
||||
if (fr.isNull() || !fr.tag() || !GetEmbeddedCover(fr, target))
|
||||
{
|
||||
std::wstring trackFolder = GetFileFolder(file);
|
||||
|
||||
if (!GetLocalCover(L"cover", trackFolder, target) &&
|
||||
!GetLocalCover(L"folder", trackFolder, target))
|
||||
{
|
||||
// Nothing found
|
||||
target.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** GetCachedArt
|
||||
**
|
||||
** Checks if cover art is in cache.
|
||||
**
|
||||
*/
|
||||
bool CCover::GetCachedCover(const std::wstring& artist, const std::wstring& title, std::wstring& target)
|
||||
{
|
||||
target = g_CachePath;
|
||||
if (artist.empty() || title.empty())
|
||||
{
|
||||
target += L"temp.art";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, save it as "Artist - Title.art"
|
||||
std::wstring name = artist;
|
||||
name += L" - ";
|
||||
name += title;
|
||||
|
||||
// Replace reserved chars with _
|
||||
std::wstring::size_type pos = 0;
|
||||
while ((pos = name.find_first_of(L"\\/:*?\"<>|", pos)) != std::wstring::npos) name[pos] = L'_';
|
||||
|
||||
target += name;
|
||||
target += L".art";
|
||||
if (_waccess(target.c_str(), 0) == 0)
|
||||
{
|
||||
// Art found in cache
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** GetLocalArt
|
||||
**
|
||||
** Attemps to find local cover art in various formats.
|
||||
**
|
||||
*/
|
||||
bool CCover::GetLocalCover(std::wstring filename, const std::wstring& folder, std::wstring& target)
|
||||
{
|
||||
std::wstring testPath = folder;
|
||||
testPath += filename;
|
||||
testPath += L".";
|
||||
std::wstring::size_type origLen = testPath.length();
|
||||
|
||||
const int extCount = 4;
|
||||
LPCTSTR extName[extCount] = { L"jpg", L"jpeg", L"png", L"bmp" };
|
||||
|
||||
for (int i = 0; i < extCount; ++i)
|
||||
{
|
||||
testPath += extName[i];
|
||||
if (_waccess(testPath.c_str(), 0) == 0)
|
||||
{
|
||||
target = testPath;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get rid of the added extension
|
||||
testPath.resize(origLen);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** GetEmbeddedArt
|
||||
**
|
||||
** Attempts to extract cover art from audio files.
|
||||
**
|
||||
*/
|
||||
bool CCover::GetEmbeddedCover(const TagLib::FileRef& fr, std::wstring& target)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
if (TagLib::MPEG::File* file = dynamic_cast<TagLib::MPEG::File*>(fr.file()))
|
||||
{
|
||||
if (file->ID3v2Tag())
|
||||
{
|
||||
found = ExtractID3(file->ID3v2Tag(), target);
|
||||
}
|
||||
if (!found && file->APETag())
|
||||
{
|
||||
found = ExtractAPE(file->APETag(), target);
|
||||
}
|
||||
}
|
||||
else if (TagLib::MP4::File* file = dynamic_cast<TagLib::MP4::File*>(fr.file()))
|
||||
{
|
||||
if (file->tag())
|
||||
{
|
||||
found = ExtractMP4(file, target);
|
||||
}
|
||||
}
|
||||
else if (TagLib::FLAC::File* file = dynamic_cast<TagLib::FLAC::File*>(fr.file()))
|
||||
{
|
||||
found = ExtractFLAC(file, target);
|
||||
|
||||
if (!found && file->ID3v2Tag())
|
||||
{
|
||||
found = ExtractID3(file->ID3v2Tag(), target);
|
||||
}
|
||||
}
|
||||
else if (TagLib::ASF::File* file = dynamic_cast<TagLib::ASF::File*>(fr.file()))
|
||||
{
|
||||
found = ExtractASF(file, target);
|
||||
}
|
||||
else if (TagLib::APE::File* file = dynamic_cast<TagLib::APE::File*>(fr.file()))
|
||||
{
|
||||
if (file->APETag())
|
||||
{
|
||||
found = ExtractAPE(file->APETag(), target);
|
||||
}
|
||||
}
|
||||
else if (TagLib::MPC::File* file = dynamic_cast<TagLib::MPC::File*>(fr.file()))
|
||||
{
|
||||
if (file->APETag())
|
||||
{
|
||||
found = ExtractAPE(file->APETag(), target);
|
||||
}
|
||||
}
|
||||
else if (TagLib::WavPack::File* file = dynamic_cast<TagLib::WavPack::File*>(fr.file()))
|
||||
{
|
||||
if (file->APETag())
|
||||
{
|
||||
found = ExtractAPE(file->APETag(), target);
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
** GetFileFolder
|
||||
**
|
||||
** Returns path without filename.
|
||||
**
|
||||
*/
|
||||
std::wstring CCover::GetFileFolder(const std::wstring& file)
|
||||
{
|
||||
std::wstring::size_type pos = file.find_last_of(L'\\');
|
||||
if (pos != std::wstring::npos)
|
||||
{
|
||||
return file.substr(0, ++pos);
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
/*
|
||||
** ExtractAPE
|
||||
**
|
||||
** Extracts cover art embedded in APE tags.
|
||||
**
|
||||
*/
|
||||
bool CCover::ExtractAPE(TagLib::APE::Tag* tag, const std::wstring& target)
|
||||
{
|
||||
const TagLib::APE::ItemListMap& listMap = tag->itemListMap();
|
||||
if (listMap.contains("COVER ART (FRONT)"))
|
||||
{
|
||||
const TagLib::ByteVector nullStringTerminator(1, 0);
|
||||
|
||||
TagLib::ByteVector item = listMap["COVER ART (FRONT)"].value();
|
||||
int pos = item.find(nullStringTerminator); // Skip the filename
|
||||
|
||||
if (++pos > 0)
|
||||
{
|
||||
const TagLib::ByteVector& pic = item.mid(pos);
|
||||
return WriteCover(pic, target);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** ExtractID3
|
||||
**
|
||||
** Extracts cover art embedded in ID3v2 tags.
|
||||
**
|
||||
*/
|
||||
bool CCover::ExtractID3(TagLib::ID3v2::Tag* tag, const std::wstring& target)
|
||||
{
|
||||
const TagLib::ID3v2::FrameList& frameList = tag->frameList("APIC");
|
||||
if (!frameList.isEmpty())
|
||||
{
|
||||
// Grab the first image
|
||||
TagLib::ID3v2::AttachedPictureFrame* frame = static_cast<TagLib::ID3v2::AttachedPictureFrame*>(frameList.front());
|
||||
return WriteCover(frame->picture(), target);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** ExtractASF
|
||||
**
|
||||
** Extracts cover art embedded in ASF/WMA files.
|
||||
**
|
||||
*/
|
||||
bool CCover::ExtractASF(TagLib::ASF::File* file, const std::wstring& target)
|
||||
{
|
||||
const TagLib::ASF::AttributeListMap& attrListMap = file->tag()->attributeListMap();
|
||||
if (attrListMap.contains("WM/Picture"))
|
||||
{
|
||||
const TagLib::ASF::AttributeList& attrList = attrListMap["WM/Picture"];
|
||||
|
||||
if (!attrList.isEmpty())
|
||||
{
|
||||
// Let's grab the first cover. TODO: Check/loop for correct type
|
||||
TagLib::ASF::Picture wmpic = attrList[0].toPicture();
|
||||
if (wmpic.isValid())
|
||||
{
|
||||
return WriteCover(wmpic.picture(), target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** ExtractFLAC
|
||||
**
|
||||
** Extracts cover art embedded in FLAC files.
|
||||
**
|
||||
*/
|
||||
bool CCover::ExtractFLAC(TagLib::FLAC::File* file, const std::wstring& target)
|
||||
{
|
||||
const TagLib::List<TagLib::FLAC::Picture*>& picList = file->pictureList();
|
||||
if (!picList.isEmpty())
|
||||
{
|
||||
// Let's grab the first image
|
||||
TagLib::FLAC::Picture* pic = picList[0];
|
||||
return WriteCover(pic->data(), target);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** ExtractMP4
|
||||
**
|
||||
** Extracts cover art embedded in MP4-like files.
|
||||
**
|
||||
*/
|
||||
bool CCover::ExtractMP4(TagLib::MP4::File* file, const std::wstring& target)
|
||||
{
|
||||
TagLib::MP4::Tag* tag = file->tag();
|
||||
if (tag->itemListMap().contains("covr"))
|
||||
{
|
||||
TagLib::MP4::CoverArtList coverList = tag->itemListMap()["covr"].toCoverArtList();
|
||||
if (coverList[0].data().size() > 0)
|
||||
{
|
||||
return WriteCover(coverList[0].data(), target);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** WriteCover
|
||||
**
|
||||
** Write cover data to file.
|
||||
**
|
||||
*/
|
||||
bool CCover::WriteCover(const TagLib::ByteVector& data, const std::wstring& target)
|
||||
{
|
||||
bool written = false;
|
||||
|
||||
FILE* f = _wfopen(target.c_str(), L"wb");
|
||||
if (f)
|
||||
{
|
||||
written = (fwrite(data.data(), 1, data.size(), f) == data.size());
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
58
Plugins/PluginNowPlaying/Cover.h
Normal file
58
Plugins/PluginNowPlaying/Cover.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
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 __COVER_H__
|
||||
#define __COVER_H__
|
||||
|
||||
#include "apefile.h"
|
||||
#include "apetag.h"
|
||||
#include "asffile.h"
|
||||
#include "attachedpictureframe.h"
|
||||
#include "commentsframe.h"
|
||||
#include "flacfile.h"
|
||||
#include "id3v1genres.h"
|
||||
#include "id3v2tag.h"
|
||||
#include "mpcfile.h"
|
||||
#include "mp4file.h"
|
||||
#include "mpegfile.h"
|
||||
#include "tag.h"
|
||||
#include "taglib.h"
|
||||
#include "textidentificationframe.h"
|
||||
#include "tstring.h"
|
||||
#include "vorbisfile.h"
|
||||
#include "wavpackfile.h"
|
||||
|
||||
class CCover
|
||||
{
|
||||
public:
|
||||
static void GetCover(const std::wstring& artist, const std::wstring& title, const std::wstring& file, std::wstring& target);
|
||||
static bool GetCachedCover(const std::wstring& artist, const std::wstring& title, std::wstring& target);
|
||||
static bool GetLocalCover(std::wstring filename, const std::wstring& folder, std::wstring& target);
|
||||
static bool GetEmbeddedCover(const TagLib::FileRef& fr, std::wstring& target);
|
||||
static std::wstring GetFileFolder(const std::wstring& file);
|
||||
|
||||
private:
|
||||
static bool ExtractAPE(TagLib::APE::Tag* tag, const std::wstring& target);
|
||||
static bool ExtractID3(TagLib::ID3v2::Tag* tag, const std::wstring& target);
|
||||
static bool ExtractASF(TagLib::ASF::File* file, const std::wstring& target);
|
||||
static bool ExtractFLAC(TagLib::FLAC::File* file, const std::wstring& target);
|
||||
static bool ExtractMP4(TagLib::MP4::File* file, const std::wstring& target);
|
||||
static bool WriteCover(const TagLib::ByteVector& data, const std::wstring& target);
|
||||
};
|
||||
|
||||
#endif
|
@ -37,31 +37,11 @@ CPlayer* g_Winamp = NULL;
|
||||
CPlayer* g_WLM = NULL;
|
||||
CPlayer* g_WMP = NULL;
|
||||
|
||||
static MeasureMap g_Values;
|
||||
static std::map<UINT, ChildMeasure*> g_Measures;
|
||||
static bool g_DisableLeazingZero = false;
|
||||
std::wstring g_CachePath;
|
||||
std::wstring g_SettingsFile;
|
||||
|
||||
void SecondsToTime(UINT seconds, WCHAR* buffer)
|
||||
{
|
||||
int hours = seconds;
|
||||
int mins = seconds;
|
||||
hours /= 3600;
|
||||
mins %= 3600;
|
||||
int secs = mins;
|
||||
mins /= 60;
|
||||
secs %= 60;
|
||||
|
||||
if (hours)
|
||||
{
|
||||
_snwprintf_s(buffer, 32, _TRUNCATE, g_DisableLeazingZero ? L"%i:%02i:%02i" : L"%02i:%02i:%02i", hours, mins, secs);
|
||||
}
|
||||
else
|
||||
{
|
||||
_snwprintf_s(buffer, 32, _TRUNCATE, g_DisableLeazingZero ? L"%i:%02i" : L"%02i:%02i", mins, secs);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize
|
||||
**
|
||||
@ -70,7 +50,7 @@ void SecondsToTime(UINT seconds, WCHAR* buffer)
|
||||
*/
|
||||
UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
|
||||
{
|
||||
if (g_Values.empty())
|
||||
if (g_Measures.empty())
|
||||
{
|
||||
// Get path to temporary folder (for cover art cache)
|
||||
WCHAR buffer[MAX_PATH];
|
||||
@ -87,10 +67,17 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
|
||||
g_SettingsFile = PluginBridge(L"getvariable", str.c_str());
|
||||
g_SettingsFile += L"Plugins.ini";
|
||||
}
|
||||
else
|
||||
{
|
||||
LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: Unable to get path to Plugins.ini.");
|
||||
}
|
||||
}
|
||||
|
||||
// Data is stored in two structs: ChildMeasure and ParentMeasure. ParentMeasure is created for measures
|
||||
// with PlayerName=someplayer. ChildMeasure is created for all measures and points to ParentMeasure as
|
||||
// referenced in PlayerName=[section].
|
||||
ChildMeasure* child = new ChildMeasure;
|
||||
UINT maxValue = 0;
|
||||
MeasureData* data = new MeasureData;
|
||||
|
||||
// Read settings from the ini-file
|
||||
LPCTSTR str = ReadConfigString(section, L"PlayerName", NULL);
|
||||
@ -98,36 +85,43 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
|
||||
{
|
||||
if (str[0] == L'[')
|
||||
{
|
||||
// PlayerName starts with [ so use referenced section
|
||||
int len = wcslen(str) - 2;
|
||||
if (len > 0)
|
||||
{
|
||||
MeasureMap::iterator it = g_Values.begin();
|
||||
for ( ; it != g_Values.end(); ++it)
|
||||
std::map<UINT, ChildMeasure*>::iterator it = g_Measures.begin();
|
||||
for ( ; it != g_Measures.end(); ++it)
|
||||
{
|
||||
if (wcsncmp(&str[1], it->second->section.c_str(), len) == 0 &&
|
||||
wcscmp(iniFile, it->second->iniFile.c_str()) == 0)
|
||||
if (wcsncmp(&str[1], it->second->parent->name.c_str(), len) == 0 &&
|
||||
wcscmp(iniFile, it->second->parent->iniFile.c_str()) == 0)
|
||||
{
|
||||
// Use same player instance as pointed section
|
||||
data->player = it->second->player;
|
||||
// Use same ParentMeasure as referenced section
|
||||
child->parent = it->second->parent;
|
||||
++child->parent->childCount;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!data->player)
|
||||
if (!child->parent)
|
||||
{
|
||||
// The referenced section doesn't exist
|
||||
std::wstring error = L"NowPlayingPlugin: PlayerName=";
|
||||
error += str;
|
||||
error += L" in section [";
|
||||
error += L" in [";
|
||||
error += section;
|
||||
error += L"] does not exist.";
|
||||
LSLog(LOG_WARNING, L"Rainmeter", error.c_str());
|
||||
delete child;
|
||||
return maxValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data->section = section;
|
||||
data->iniFile = iniFile;
|
||||
// ParentMeasure is created when PlayerName is an actual player (and not a reference)
|
||||
ParentMeasure* parent = new ParentMeasure;
|
||||
parent->name = section;
|
||||
parent->iniFile = iniFile;
|
||||
|
||||
if (_wcsicmp(L"AIMP", str) == 0)
|
||||
{
|
||||
@ -135,7 +129,7 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
|
||||
{
|
||||
g_AIMP = new CPlayerAIMP();
|
||||
}
|
||||
data->player = g_AIMP;
|
||||
parent->player = g_AIMP;
|
||||
}
|
||||
else if (_wcsicmp(L"CAD", str) == 0)
|
||||
{
|
||||
@ -143,7 +137,7 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
|
||||
{
|
||||
g_CAD = new CPlayerCAD();
|
||||
}
|
||||
data->player = g_CAD;
|
||||
parent->player = g_CAD;
|
||||
}
|
||||
else if (_wcsicmp(L"foobar2000", str) == 0)
|
||||
{
|
||||
@ -151,7 +145,7 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
|
||||
{
|
||||
g_Foobar = new CPlayerFoobar();
|
||||
}
|
||||
data->player = g_Foobar;
|
||||
parent->player = g_Foobar;
|
||||
}
|
||||
else if (_wcsicmp(L"iTunes", str) == 0)
|
||||
{
|
||||
@ -159,7 +153,7 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
|
||||
{
|
||||
g_iTunes = new CPlayerITunes();
|
||||
}
|
||||
data->player = g_iTunes;
|
||||
parent->player = g_iTunes;
|
||||
}
|
||||
else if (_wcsicmp(L"MediaMonkey", str) == 0)
|
||||
{
|
||||
@ -167,7 +161,7 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
|
||||
{
|
||||
g_Winamp = new CPlayerWinamp(WA_MEDIAMONKEY);
|
||||
}
|
||||
data->player = g_Winamp;
|
||||
parent->player = g_Winamp;
|
||||
}
|
||||
else if (_wcsicmp(L"Spotify", str) == 0)
|
||||
{
|
||||
@ -175,7 +169,7 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
|
||||
{
|
||||
g_Spotify = new CPlayerSpotify();
|
||||
}
|
||||
data->player = g_Spotify;
|
||||
parent->player = g_Spotify;
|
||||
}
|
||||
else if (_wcsicmp(L"WinAmp", str) == 0)
|
||||
{
|
||||
@ -183,7 +177,7 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
|
||||
{
|
||||
g_Winamp = new CPlayerWinamp(WA_WINAMP);
|
||||
}
|
||||
data->player = g_Winamp;
|
||||
parent->player = g_Winamp;
|
||||
}
|
||||
else if (_wcsicmp(L"WLM", str) == 0)
|
||||
{
|
||||
@ -191,7 +185,7 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
|
||||
{
|
||||
g_WLM = new CPlayerWLM();
|
||||
}
|
||||
data->player = g_WLM;
|
||||
parent->player = g_WLM;
|
||||
}
|
||||
else if (_wcsicmp(L"WMP", str) == 0)
|
||||
{
|
||||
@ -199,7 +193,7 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
|
||||
{
|
||||
g_WMP = new CPlayerWMP();
|
||||
}
|
||||
data->player = g_WMP;
|
||||
parent->player = g_WMP;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -215,27 +209,31 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
|
||||
error += section;
|
||||
error += L"] is not valid.";
|
||||
LSLog(LOG_ERROR, L"Rainmeter", error.c_str());
|
||||
delete data;
|
||||
delete parent;
|
||||
delete child;
|
||||
return maxValue;
|
||||
}
|
||||
|
||||
str = ReadConfigString(section, L"PlayerPath", NULL);
|
||||
if (str && *str)
|
||||
parent->id = id;
|
||||
parent->childCount = 1;
|
||||
parent->player->AddInstance();
|
||||
parent->playerPath = ReadConfigString(section, L"PlayerPath", L"");
|
||||
parent->trackChangeAction = ReadConfigString(section, L"TrackChangeAction", L"");
|
||||
|
||||
if (!parent->trackChangeAction.empty())
|
||||
{
|
||||
data->player->SetPlayerPath(str);
|
||||
// Get window handle to send the bang later on
|
||||
parent->window = FindMeterWindow(parent->iniFile);
|
||||
parent->trackCount = 1;
|
||||
}
|
||||
|
||||
str = ReadConfigString(section, L"DisableLeadingZero", NULL);
|
||||
if (str && *str)
|
||||
str = ReadConfigString(section, L"DisableLeadingZero", L"0");
|
||||
if (str)
|
||||
{
|
||||
g_DisableLeazingZero = (1 == _wtoi(str));
|
||||
parent->disableLeadingZero = (1 == _wtoi(str));
|
||||
}
|
||||
|
||||
str = ReadConfigString(section, L"TrackChangeAction", NULL);
|
||||
if (str && *str)
|
||||
{
|
||||
data->player->SetTrackChangeAction(str);
|
||||
}
|
||||
child->parent = parent;
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,55 +242,69 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
|
||||
{
|
||||
if (_wcsicmp(L"ARTIST", str) == 0)
|
||||
{
|
||||
data->measure = MEASURE_ARTIST;
|
||||
child->type = MEASURE_ARTIST;
|
||||
}
|
||||
else if (_wcsicmp(L"TITLE", str) == 0)
|
||||
{
|
||||
data->measure = MEASURE_TITLE;
|
||||
child->type = MEASURE_TITLE;
|
||||
}
|
||||
else if (_wcsicmp(L"ALBUM", str) == 0)
|
||||
{
|
||||
data->measure = MEASURE_ALBUM;
|
||||
child->type = MEASURE_ALBUM;
|
||||
}
|
||||
else if (_wcsicmp(L"LYRICS", str) == 0)
|
||||
{
|
||||
child->type = MEASURE_LYRICS;
|
||||
}
|
||||
else if (_wcsicmp(L"COVER", str) == 0)
|
||||
{
|
||||
data->measure = MEASURE_COVER;
|
||||
child->type = MEASURE_COVER;
|
||||
}
|
||||
else if (_wcsicmp(L"DURATION", str) == 0)
|
||||
{
|
||||
data->measure = MEASURE_DURATION;
|
||||
child->type = MEASURE_DURATION;
|
||||
}
|
||||
else if (_wcsicmp(L"POSITION", str) == 0)
|
||||
{
|
||||
data->measure = MEASURE_POSITION;
|
||||
child->type = MEASURE_POSITION;
|
||||
}
|
||||
else if (_wcsicmp(L"PROGRESS", str) == 0)
|
||||
{
|
||||
data->measure = MEASURE_PROGRESS;
|
||||
child->type = MEASURE_PROGRESS;
|
||||
maxValue = 100;
|
||||
}
|
||||
else if (_wcsicmp(L"RATING", str) == 0)
|
||||
{
|
||||
data->measure = MEASURE_RATING;
|
||||
child->type = MEASURE_RATING;
|
||||
maxValue = 5;
|
||||
}
|
||||
else if (_wcsicmp(L"STATE", str) == 0)
|
||||
{
|
||||
data->measure = MEASURE_STATE;
|
||||
child->type = MEASURE_STATE;
|
||||
}
|
||||
else if (_wcsicmp(L"VOLUME", str) == 0)
|
||||
{
|
||||
data->measure = MEASURE_VOLUME;
|
||||
child->type = MEASURE_VOLUME;
|
||||
maxValue = 100;
|
||||
}
|
||||
else if (_wcsicmp(L"FILE", str) == 0)
|
||||
{
|
||||
data->measure = MEASURE_FILE;
|
||||
child->type = MEASURE_FILE;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::wstring error = L"NowPlayingPlugin: PlayerType=";
|
||||
error += str;
|
||||
error += L" in section [";
|
||||
error += section;
|
||||
error += L"] is not valid.";
|
||||
LSLog(LOG_WARNING, L"Rainmeter", error.c_str());
|
||||
}
|
||||
|
||||
child->parent->player->AddMeasure(child->type);
|
||||
}
|
||||
|
||||
data->player->AddInstance(data->measure);
|
||||
g_Values[id] = data;
|
||||
g_Measures[id] = child;
|
||||
return maxValue;
|
||||
}
|
||||
|
||||
@ -304,16 +316,26 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
|
||||
*/
|
||||
void Finalize(HMODULE instance, UINT id)
|
||||
{
|
||||
MeasureMap::iterator i = g_Values.find(id);
|
||||
if (i != g_Values.end())
|
||||
std::map<UINT, ChildMeasure*>::iterator i = g_Measures.find(id);
|
||||
if (i != g_Measures.end())
|
||||
{
|
||||
(*i).second->player->RemoveInstance();
|
||||
delete (*i).second;
|
||||
g_Values.erase(i);
|
||||
ChildMeasure* child = (*i).second;
|
||||
ParentMeasure* parent = child->parent;
|
||||
CPlayer* player = parent->player;
|
||||
|
||||
if (--parent->childCount == 0)
|
||||
{
|
||||
player->RemoveInstance();
|
||||
delete parent;
|
||||
}
|
||||
|
||||
delete child;
|
||||
g_Measures.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
** Update
|
||||
**
|
||||
** Called on each update.
|
||||
@ -321,18 +343,29 @@ void Finalize(HMODULE instance, UINT id)
|
||||
*/
|
||||
UINT Update(UINT id)
|
||||
{
|
||||
MeasureMap::iterator i = g_Values.find(id);
|
||||
if (i != g_Values.end())
|
||||
std::map<UINT, ChildMeasure*>::iterator i = g_Measures.find(id);
|
||||
if (i != g_Measures.end())
|
||||
{
|
||||
if (!(*i).second->section.empty())
|
||||
ChildMeasure* child = (*i).second;
|
||||
ParentMeasure* parent = child->parent;
|
||||
CPlayer* player = parent->player;
|
||||
|
||||
if (parent->id == id)
|
||||
{
|
||||
// Only allow main measure to update
|
||||
(*i).second->player->UpdateData();
|
||||
player->UpdateMeasure();
|
||||
|
||||
// Execute TrackChangeAction= if necessary
|
||||
if (!parent->trackChangeAction.empty() &&
|
||||
parent->trackCount != player->GetTrackCount())
|
||||
{
|
||||
ExecuteCommand(parent->trackChangeAction, parent->window);
|
||||
|
||||
// TODO: First is true..
|
||||
parent->trackCount = player->GetTrackCount();
|
||||
}
|
||||
}
|
||||
|
||||
CPlayer* player = (*i).second->player;
|
||||
|
||||
switch ((*i).second->measure)
|
||||
switch (child->type)
|
||||
{
|
||||
case MEASURE_DURATION:
|
||||
return player->GetDuration();
|
||||
@ -351,7 +384,7 @@ UINT Update(UINT id)
|
||||
return player->GetRating();
|
||||
|
||||
case MEASURE_STATE:
|
||||
return (int)player->GetState();
|
||||
return (UINT)player->GetState();
|
||||
|
||||
case MEASURE_VOLUME:
|
||||
return player->GetVolume();
|
||||
@ -371,13 +404,15 @@ UINT Update(UINT id)
|
||||
*/
|
||||
LPCTSTR GetString(UINT id, UINT flags)
|
||||
{
|
||||
MeasureMap::iterator i = g_Values.find(id);
|
||||
if (i != g_Values.end())
|
||||
std::map<UINT, ChildMeasure*>::iterator i = g_Measures.find(id);
|
||||
if (i != g_Measures.end())
|
||||
{
|
||||
CPlayer* player = (*i).second->player;
|
||||
ChildMeasure* child = (*i).second;
|
||||
ParentMeasure* parent = child->parent;
|
||||
CPlayer* player = parent->player;
|
||||
static WCHAR buffer[32];
|
||||
|
||||
switch ((*i).second->measure)
|
||||
switch (child->type)
|
||||
{
|
||||
case MEASURE_ARTIST:
|
||||
return player->GetArtist();
|
||||
@ -392,21 +427,16 @@ LPCTSTR GetString(UINT id, UINT flags)
|
||||
return player->GetCoverPath();
|
||||
|
||||
case MEASURE_DURATION:
|
||||
SecondsToTime(player->GetDuration(), buffer);
|
||||
SecondsToTime(player->GetDuration(), parent->disableLeadingZero, buffer);
|
||||
return buffer;
|
||||
|
||||
case MEASURE_POSITION:
|
||||
SecondsToTime(player->GetPosition(), buffer);
|
||||
SecondsToTime(player->GetPosition(), parent->disableLeadingZero, buffer);
|
||||
return buffer;
|
||||
|
||||
case MEASURE_PROGRESS:
|
||||
if (player->GetDuration())
|
||||
{
|
||||
int res = (player->GetPosition() * 100) / player->GetDuration();
|
||||
_itow(res, buffer, 10);
|
||||
return buffer;
|
||||
}
|
||||
return L"0";
|
||||
_itow(player->GetDuration() ? ((player->GetPosition() * 100) / player->GetDuration()) : 0, buffer, 10);
|
||||
return buffer;
|
||||
|
||||
case MEASURE_RATING:
|
||||
_itow(player->GetRating(), buffer, 10);
|
||||
@ -426,8 +456,7 @@ LPCTSTR GetString(UINT id, UINT flags)
|
||||
}
|
||||
else
|
||||
{
|
||||
// For invalid PlayerName=
|
||||
return L"0";
|
||||
return L"Error: Invalid player.";
|
||||
}
|
||||
|
||||
return L"";
|
||||
@ -441,12 +470,21 @@ LPCTSTR GetString(UINT id, UINT flags)
|
||||
*/
|
||||
void ExecuteBang(LPCTSTR bang, UINT id)
|
||||
{
|
||||
MeasureMap::iterator i = g_Values.find(id);
|
||||
if (i != g_Values.end())
|
||||
std::map<UINT, ChildMeasure*>::iterator i = g_Measures.find(id);
|
||||
if (i != g_Measures.end())
|
||||
{
|
||||
CPlayer* player = (*i).second->player;
|
||||
ChildMeasure* child = (*i).second;
|
||||
ParentMeasure* parent = child->parent;
|
||||
CPlayer* player = parent->player;
|
||||
|
||||
if (_wcsicmp(bang, L"Pause") == 0)
|
||||
if (!player->IsInitialized())
|
||||
{
|
||||
if (_wcsicmp(bang, L"OpenPlayer") == 0 || _wcsicmp(bang, L"TogglePlayer") == 0)
|
||||
{
|
||||
player->OpenPlayer(parent->playerPath);
|
||||
}
|
||||
}
|
||||
else if (_wcsicmp(bang, L"Pause") == 0)
|
||||
{
|
||||
player->Pause();
|
||||
}
|
||||
@ -456,7 +494,7 @@ void ExecuteBang(LPCTSTR bang, UINT id)
|
||||
}
|
||||
else if (_wcsicmp(bang, L"PlayPause") == 0)
|
||||
{
|
||||
player->PlayPause();
|
||||
(player->GetState() != PLAYER_PLAYING) ? player->Play() : player->Pause();
|
||||
}
|
||||
else if (_wcsicmp(bang, L"Stop") == 0)
|
||||
{
|
||||
@ -470,24 +508,18 @@ void ExecuteBang(LPCTSTR bang, UINT id)
|
||||
{
|
||||
player->Previous();
|
||||
}
|
||||
else if (_wcsicmp(bang, L"ClosePlayer") == 0)
|
||||
else if (_wcsicmp(bang, L"ClosePlayer") == 0 || _wcsicmp(bang, L"TogglePlayer") == 0)
|
||||
{
|
||||
player->ClosePlayer();
|
||||
}
|
||||
else if (_wcsicmp(bang, L"OpenPlayer") == 0)
|
||||
{
|
||||
player->OpenPlayer();
|
||||
}
|
||||
else if (_wcsicmp(bang, L"TogglePlayer") == 0)
|
||||
{
|
||||
player->TogglePlayer();
|
||||
}
|
||||
else
|
||||
{
|
||||
LPCTSTR arg = wcschr(bang, L' ');
|
||||
|
||||
if (++arg) // Skip the space
|
||||
if (arg)
|
||||
{
|
||||
++arg; // Skip the space
|
||||
|
||||
if (wcsnicmp(bang, L"SetPosition", 11) == 0)
|
||||
{
|
||||
int position = (_wtoi(arg) * player->GetDuration()) / 100;
|
||||
@ -544,3 +576,71 @@ LPCTSTR GetPluginAuthor()
|
||||
{
|
||||
return L"Birunthan Mohanathas (www.poiru.net)";
|
||||
}
|
||||
|
||||
void SecondsToTime(UINT seconds, bool leadingZero, WCHAR* buffer)
|
||||
{
|
||||
int hours = seconds;
|
||||
int mins = seconds;
|
||||
hours /= 3600;
|
||||
mins %= 3600;
|
||||
int secs = mins;
|
||||
mins /= 60;
|
||||
secs %= 60;
|
||||
|
||||
if (hours)
|
||||
{
|
||||
_snwprintf_s(buffer, 32, _TRUNCATE, leadingZero ? L"%i:%02i:%02i" : L"%02i:%02i:%02i", hours, mins, secs);
|
||||
}
|
||||
else
|
||||
{
|
||||
_snwprintf_s(buffer, 32, _TRUNCATE, leadingZero ? L"%i:%02i" : L"%02i:%02i", mins, secs);
|
||||
}
|
||||
}
|
||||
|
||||
void ExecuteCommand(std::wstring& command, HWND wnd)
|
||||
{
|
||||
COPYDATASTRUCT cds;
|
||||
cds.dwData = 1;
|
||||
cds.cbData = (DWORD)(command.size() + 1) * sizeof(WCHAR);
|
||||
cds.lpData = (void*)command.c_str();
|
||||
|
||||
// Send bang to the Rainmeter window
|
||||
SendMessage(wnd, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds);
|
||||
}
|
||||
|
||||
bool BelongToSameProcess(HWND wnd)
|
||||
{
|
||||
DWORD procId = 0;
|
||||
GetWindowThreadProcessId(wnd, &procId);
|
||||
|
||||
return (procId == GetCurrentProcessId());
|
||||
}
|
||||
|
||||
HWND FindMeterWindow(HWND parent)
|
||||
{
|
||||
HWND wnd = NULL;
|
||||
while (wnd = FindWindowEx(parent, wnd, L"RainmeterMeterWindow", NULL))
|
||||
{
|
||||
if (BelongToSameProcess(wnd))
|
||||
{
|
||||
return wnd;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HWND FindMeterWindow(const std::wstring& iniFile)
|
||||
{
|
||||
std::wstring str = PluginBridge(L"getconfig", iniFile.c_str());
|
||||
if (!str.empty())
|
||||
{
|
||||
str = PluginBridge(L"getwindow", str.c_str());
|
||||
if (str != L"error")
|
||||
{
|
||||
return (HWND)UlongToPtr(wcstoul(str.c_str(), NULL, 10));
|
||||
}
|
||||
}
|
||||
|
||||
return FindMeterWindow(NULL); // Use old way to find
|
||||
}
|
||||
|
@ -21,20 +21,36 @@
|
||||
|
||||
#include "Player.h"
|
||||
|
||||
struct MeasureData
|
||||
struct ParentMeasure
|
||||
{
|
||||
std::wstring iniFile;
|
||||
std::wstring section;
|
||||
MEASURETYPE measure;
|
||||
UINT id;
|
||||
UINT childCount;
|
||||
UINT trackCount;
|
||||
CPlayer* player;
|
||||
HANDLE thread;
|
||||
HWND window;
|
||||
std::wstring name;
|
||||
std::wstring iniFile;
|
||||
std::wstring trackChangeAction;
|
||||
std::wstring playerPath;
|
||||
bool disableLeadingZero;
|
||||
|
||||
MeasureData() :
|
||||
player(NULL)
|
||||
{
|
||||
}
|
||||
ParentMeasure() : player(NULL), thread(NULL) {}
|
||||
};
|
||||
|
||||
typedef std::map<UINT, MeasureData*> MeasureMap;
|
||||
struct ChildMeasure
|
||||
{
|
||||
MEASURETYPE type;
|
||||
ParentMeasure* parent;
|
||||
|
||||
ChildMeasure() : parent(NULL) {}
|
||||
};
|
||||
|
||||
void SecondsToTime(UINT seconds, bool leadingZero, WCHAR* buffer);
|
||||
void ExecuteCommand(std::wstring& command, HWND wnd);
|
||||
bool BelongToSameProcess(HWND wnd);
|
||||
HWND FindMeterWindow(HWND parent);
|
||||
HWND FindMeterWindow(const std::wstring& iniFile);
|
||||
|
||||
/* The exported functions */
|
||||
extern "C"
|
||||
|
@ -16,13 +16,9 @@
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
// Common functions for the players
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "Player.h"
|
||||
|
||||
extern std::wstring g_CachePath;
|
||||
|
||||
/*
|
||||
** CPlayer
|
||||
**
|
||||
@ -30,13 +26,17 @@ extern std::wstring g_CachePath;
|
||||
**
|
||||
*/
|
||||
CPlayer::CPlayer() :
|
||||
m_Initialized(false),
|
||||
m_HasCoverMeasure(false),
|
||||
m_HasLyricsMeasure(false),
|
||||
m_InstanceCount(),
|
||||
m_UpdateCount(),
|
||||
m_TrackCount(),
|
||||
m_State(),
|
||||
m_Duration(),
|
||||
m_Position(),
|
||||
m_Rating(),
|
||||
m_Volume(),
|
||||
m_TrackChanged(false)
|
||||
m_Volume()
|
||||
{
|
||||
}
|
||||
|
||||
@ -51,35 +51,72 @@ CPlayer::~CPlayer()
|
||||
}
|
||||
|
||||
/*
|
||||
** ExecuteTrackChangeAction
|
||||
** AddInstance
|
||||
**
|
||||
** Called from player implementation on track change.
|
||||
** Called during initialization of main measure.
|
||||
**
|
||||
*/
|
||||
void CPlayer::ExecuteTrackChangeAction()
|
||||
void CPlayer::AddInstance()
|
||||
{
|
||||
if (!m_TrackChangeAction.empty())
|
||||
{
|
||||
HWND wnd = FindWindow(L"RainmeterMeterWindow", NULL);
|
||||
if (wnd != NULL)
|
||||
{
|
||||
COPYDATASTRUCT cds;
|
||||
cds.dwData = 1;
|
||||
cds.cbData = (DWORD)(m_TrackChangeAction.size() + 1) * sizeof(WCHAR);
|
||||
cds.lpData = (void*)m_TrackChangeAction.c_str();
|
||||
++m_InstanceCount;
|
||||
}
|
||||
|
||||
// Send the bang to the Rainmeter window
|
||||
SendMessage(wnd, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds);
|
||||
}
|
||||
/*
|
||||
** RemoveInstance
|
||||
**
|
||||
** Called during destruction of main measure.
|
||||
**
|
||||
*/
|
||||
void CPlayer::RemoveInstance()
|
||||
{
|
||||
if (--m_InstanceCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** ClearInfo
|
||||
** AddMeasure
|
||||
**
|
||||
** Called during initialization of any measure.
|
||||
**
|
||||
*/
|
||||
void CPlayer::AddMeasure(MEASURETYPE measure)
|
||||
{
|
||||
switch (measure)
|
||||
{
|
||||
case MEASURE_LYRICS:
|
||||
m_HasLyricsMeasure = true;
|
||||
break;
|
||||
|
||||
case MEASURE_COVER:
|
||||
m_HasCoverMeasure = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** UpdateMeasure
|
||||
**
|
||||
** Called during update of main measure.
|
||||
**
|
||||
*/
|
||||
void CPlayer::UpdateMeasure()
|
||||
{
|
||||
if (++m_UpdateCount == m_InstanceCount)
|
||||
{
|
||||
UpdateData();
|
||||
m_UpdateCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** ClearData
|
||||
**
|
||||
** Clear track information.
|
||||
**
|
||||
*/
|
||||
void CPlayer::ClearInfo()
|
||||
void CPlayer::ClearData()
|
||||
{
|
||||
m_Duration = 0;
|
||||
m_Position = 0;
|
||||
@ -91,297 +128,3 @@ void CPlayer::ClearInfo()
|
||||
m_FilePath.clear();
|
||||
m_CoverPath.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
** GetCachedArt
|
||||
**
|
||||
** Checks if cover art is in cache.
|
||||
**
|
||||
*/
|
||||
bool CPlayer::GetCachedArt()
|
||||
{
|
||||
m_CoverPath = g_CachePath;
|
||||
if (m_Artist.empty() || m_Title.empty())
|
||||
{
|
||||
m_CoverPath += L"temp.art";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, save it as "Artist - Title.art"
|
||||
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'_';
|
||||
|
||||
m_CoverPath += name;
|
||||
m_CoverPath += L".art";
|
||||
if (_waccess(m_CoverPath.c_str(), 0) == 0)
|
||||
{
|
||||
// Art found in cache
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** GetLocalArt
|
||||
**
|
||||
** Attemps to find local cover art in various formats.
|
||||
**
|
||||
*/
|
||||
bool CPlayer::GetLocalArt(std::wstring& folder, std::wstring filename)
|
||||
{
|
||||
std::wstring testPath = folder;
|
||||
testPath += filename;
|
||||
testPath += L".";
|
||||
std::wstring::size_type origLen = testPath.length();
|
||||
|
||||
const int extCount = 4;
|
||||
LPCTSTR extName[extCount] = { L"jpg", L"jpeg", L"png", L"bmp" };
|
||||
|
||||
for (int i = 0; i < extCount; ++i)
|
||||
{
|
||||
testPath += extName[i];
|
||||
if (_waccess(testPath.c_str(), 0) == 0)
|
||||
{
|
||||
m_CoverPath = testPath;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get rid of the added extension
|
||||
testPath.resize(origLen);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** GetEmbeddedArt
|
||||
**
|
||||
** Attempts to extract cover art from audio files.
|
||||
**
|
||||
*/
|
||||
bool CPlayer::GetEmbeddedArt(const TagLib::FileRef& fr)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
if (TagLib::MPEG::File* file = dynamic_cast<TagLib::MPEG::File*>(fr.file()))
|
||||
{
|
||||
if (file->ID3v2Tag())
|
||||
{
|
||||
found = GetArtID3(file->ID3v2Tag());
|
||||
}
|
||||
if (!found && file->APETag())
|
||||
{
|
||||
found = GetArtAPE(file->APETag());
|
||||
}
|
||||
}
|
||||
else if (TagLib::MP4::File* file = dynamic_cast<TagLib::MP4::File*>(fr.file()))
|
||||
{
|
||||
if (file->tag())
|
||||
{
|
||||
found = GetArtMP4(file);
|
||||
}
|
||||
}
|
||||
else if (TagLib::FLAC::File* file = dynamic_cast<TagLib::FLAC::File*>(fr.file()))
|
||||
{
|
||||
found = GetArtFLAC(file);
|
||||
|
||||
if (!found && file->ID3v2Tag())
|
||||
{
|
||||
found = GetArtID3(file->ID3v2Tag());
|
||||
}
|
||||
}
|
||||
else if (TagLib::ASF::File* file = dynamic_cast<TagLib::ASF::File*>(fr.file()))
|
||||
{
|
||||
found = GetArtASF(file);
|
||||
}
|
||||
else if (TagLib::APE::File* file = dynamic_cast<TagLib::APE::File*>(fr.file()))
|
||||
{
|
||||
if (file->APETag())
|
||||
{
|
||||
found = GetArtAPE(file->APETag());
|
||||
}
|
||||
}
|
||||
else if (TagLib::MPC::File* file = dynamic_cast<TagLib::MPC::File*>(fr.file()))
|
||||
{
|
||||
if (file->APETag())
|
||||
{
|
||||
found = GetArtAPE(file->APETag());
|
||||
}
|
||||
}
|
||||
else if (TagLib::WavPack::File* file = dynamic_cast<TagLib::WavPack::File*>(fr.file()))
|
||||
{
|
||||
if (file->APETag())
|
||||
{
|
||||
found = GetArtAPE(file->APETag());
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
** GetArtAPE
|
||||
**
|
||||
** Extracts cover art embedded in APE tags.
|
||||
**
|
||||
*/
|
||||
bool CPlayer::GetArtAPE(TagLib::APE::Tag* tag)
|
||||
{
|
||||
bool ret = false;
|
||||
const TagLib::APE::ItemListMap& listMap = tag->itemListMap();
|
||||
|
||||
if (listMap.contains("COVER ART (FRONT)"))
|
||||
{
|
||||
const TagLib::ByteVector nullStringTerminator(1, 0);
|
||||
|
||||
TagLib::ByteVector item = listMap["COVER ART (FRONT)"].value();
|
||||
int pos = item.find(nullStringTerminator); // Skip the filename
|
||||
|
||||
if (++pos > 0)
|
||||
{
|
||||
const TagLib::ByteVector& pic = item.mid(pos);
|
||||
|
||||
FILE* f = _wfopen(m_CoverPath.c_str(), L"wb");
|
||||
if (f)
|
||||
{
|
||||
ret = (fwrite(pic.data(), 1, pic.size(), f) == pic.size());
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
** GetArtID3
|
||||
**
|
||||
** Extracts cover art embedded in ID3v2 tags.
|
||||
**
|
||||
*/
|
||||
bool CPlayer::GetArtID3(TagLib::ID3v2::Tag* tag)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
const TagLib::ID3v2::FrameList& frameList = tag->frameList("APIC");
|
||||
if (!frameList.isEmpty())
|
||||
{
|
||||
// Grab the first image
|
||||
TagLib::ID3v2::AttachedPictureFrame* frame = static_cast<TagLib::ID3v2::AttachedPictureFrame*>(frameList.front());
|
||||
TagLib::uint size = frame->picture().size();
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
FILE* f = _wfopen(m_CoverPath.c_str(), L"wb");
|
||||
if (f)
|
||||
{
|
||||
ret = (fwrite(frame->picture().data(), 1, size, f) == size);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
** GetArtASF
|
||||
**
|
||||
** Extracts cover art embedded in ASF/WMA files.
|
||||
**
|
||||
*/
|
||||
bool CPlayer::GetArtASF(TagLib::ASF::File* file)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
const TagLib::ASF::AttributeListMap& attrListMap = file->tag()->attributeListMap();
|
||||
|
||||
if (attrListMap.contains("WM/Picture"))
|
||||
{
|
||||
const TagLib::ASF::AttributeList& attrList = attrListMap["WM/Picture"];
|
||||
|
||||
if (!attrList.isEmpty())
|
||||
{
|
||||
// Let's grab the first cover. TODO: Check/loop for correct type
|
||||
TagLib::ASF::Picture wmpic = attrList[0].toPicture();
|
||||
|
||||
if (wmpic.isValid())
|
||||
{
|
||||
FILE* f = _wfopen(m_CoverPath.c_str(), L"wb");
|
||||
if (f)
|
||||
{
|
||||
ret = (fwrite(wmpic.picture().data(), 1, wmpic.picture().size(), f) == wmpic.picture().size());
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
** GetArtFLAC
|
||||
**
|
||||
** Extracts cover art embedded in FLAC files.
|
||||
**
|
||||
*/
|
||||
bool CPlayer::GetArtFLAC(TagLib::FLAC::File* file)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
const TagLib::List<TagLib::FLAC::Picture*>& picList = file->pictureList();
|
||||
if (!picList.isEmpty())
|
||||
{
|
||||
// Let's grab the first image
|
||||
TagLib::FLAC::Picture* pic = picList[0];
|
||||
|
||||
FILE* f = _wfopen(m_CoverPath.c_str(), L"wb");
|
||||
if (f)
|
||||
{
|
||||
ret = (fwrite(pic->data().data(), 1, pic->data().size(), f) == pic->data().size());
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
** GetArtMP4
|
||||
**
|
||||
** Extracts cover art embedded in MP4-like files.
|
||||
**
|
||||
*/
|
||||
bool CPlayer::GetArtMP4(TagLib::MP4::File* file)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
TagLib::MP4::Tag* tag = file->tag();
|
||||
if (tag->itemListMap().contains("covr"))
|
||||
{
|
||||
TagLib::MP4::CoverArtList coverList = tag->itemListMap()["covr"].toCoverArtList();
|
||||
TagLib::uint size = coverList[0].data().size();
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
FILE* f = _wfopen(m_CoverPath.c_str(), L"wb");
|
||||
if (f)
|
||||
{
|
||||
ret = (fwrite(coverList[0].data().data(), 1, size, f) == size);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -19,26 +19,10 @@
|
||||
#ifndef __PLAYER_H__
|
||||
#define __PLAYER_H__
|
||||
|
||||
// TagLib
|
||||
#include "apefile.h"
|
||||
#include "apetag.h"
|
||||
#include "asffile.h"
|
||||
#include "attachedpictureframe.h"
|
||||
#include "commentsframe.h"
|
||||
#include "flacfile.h"
|
||||
#include "id3v1genres.h"
|
||||
#include "id3v2tag.h"
|
||||
#include "mpcfile.h"
|
||||
#include "mp4file.h"
|
||||
#include "mpegfile.h"
|
||||
#include "tag.h"
|
||||
#include "taglib.h"
|
||||
#include "textidentificationframe.h"
|
||||
#include "tstring.h"
|
||||
#include "vorbisfile.h"
|
||||
#include "wavpackfile.h"
|
||||
#include "Cover.h"
|
||||
|
||||
enum PLAYERSTATE
|
||||
enum PLAYSTATE
|
||||
{
|
||||
PLAYER_STOPPED,
|
||||
PLAYER_PLAYING,
|
||||
@ -50,6 +34,7 @@ enum MEASURETYPE
|
||||
MEASURE_ARTIST,
|
||||
MEASURE_TITLE,
|
||||
MEASURE_ALBUM,
|
||||
MEASURE_LYRICS,
|
||||
MEASURE_COVER,
|
||||
MEASURE_DURATION,
|
||||
MEASURE_POSITION,
|
||||
@ -60,72 +45,66 @@ enum MEASURETYPE
|
||||
MEASURE_FILE
|
||||
};
|
||||
|
||||
class CPlayer
|
||||
class CPlayer :
|
||||
public CCover
|
||||
{
|
||||
public:
|
||||
CPlayer();
|
||||
virtual ~CPlayer();
|
||||
|
||||
virtual ~CPlayer() = 0;
|
||||
|
||||
void AddInstance();
|
||||
void RemoveInstance();
|
||||
void UpdateMeasure();
|
||||
virtual void AddMeasure(MEASURETYPE measure);
|
||||
virtual void UpdateData() = 0;
|
||||
|
||||
bool IsInitialized() { return m_Initialized; }
|
||||
UINT GetTrackCount() { return m_TrackCount; }
|
||||
|
||||
virtual void Pause() {}
|
||||
virtual void Play() {}
|
||||
virtual void PlayPause() {}
|
||||
virtual void Stop() {}
|
||||
virtual void Next() {}
|
||||
virtual void Previous() {}
|
||||
virtual void SetPosition(int position) {}
|
||||
virtual void SetRating(int rating) {}
|
||||
virtual void SetVolume(int volume) {}
|
||||
virtual void OpenPlayer() {}
|
||||
virtual void OpenPlayer(std::wstring& path) {}
|
||||
virtual void ClosePlayer() {}
|
||||
virtual void TogglePlayer() {}
|
||||
|
||||
virtual void AddInstance(MEASURETYPE type) = 0;
|
||||
virtual void RemoveInstance() = 0;
|
||||
virtual void UpdateData() = 0;
|
||||
|
||||
PLAYERSTATE GetState() { return m_State; }
|
||||
PLAYSTATE GetState() { return m_State; }
|
||||
LPCTSTR GetArtist() { return m_Artist.c_str(); }
|
||||
LPCTSTR GetAlbum() { return m_Album.c_str(); }
|
||||
LPCTSTR GetTitle() { return m_Title.c_str(); }
|
||||
LPCTSTR GetFilePath() { return m_FilePath.c_str(); }
|
||||
LPCTSTR GetLyrics() { return m_Lyrics.c_str(); }
|
||||
LPCTSTR GetCoverPath() { return m_CoverPath.c_str(); }
|
||||
LPCTSTR GetPlayerPath() { return m_PlayerPath.c_str(); }
|
||||
LPCTSTR GetFilePath() { return m_FilePath.c_str(); }
|
||||
UINT GetDuration() { return m_Duration; }
|
||||
UINT GetPosition() { return m_Position; }
|
||||
UINT GetRating() { return m_Rating; }
|
||||
UINT GetVolume() { return m_Volume; }
|
||||
|
||||
void SetPlayerPath(LPCTSTR path) { m_PlayerPath = path; }
|
||||
void SetTrackChangeAction(LPCTSTR action) { m_TrackChangeAction = action; }
|
||||
void ExecuteTrackChangeAction();
|
||||
void ClearInfo();
|
||||
|
||||
bool GetCachedArt();
|
||||
bool GetLocalArt(std::wstring& folder, std::wstring filename);
|
||||
bool GetEmbeddedArt(const TagLib::FileRef& fr);
|
||||
bool GetArtAPE(TagLib::APE::Tag* tag);
|
||||
bool GetArtID3(TagLib::ID3v2::Tag* tag);
|
||||
bool GetArtASF(TagLib::ASF::File* file);
|
||||
bool GetArtFLAC(TagLib::FLAC::File* file);
|
||||
bool GetArtMP4(TagLib::MP4::File* file);
|
||||
|
||||
protected:
|
||||
int m_InstanceCount;
|
||||
bool m_TrackChanged;
|
||||
void ClearData();
|
||||
|
||||
PLAYERSTATE m_State;
|
||||
bool m_Initialized;
|
||||
bool m_HasCoverMeasure;
|
||||
bool m_HasLyricsMeasure;
|
||||
UINT m_InstanceCount;
|
||||
UINT m_UpdateCount;
|
||||
UINT m_TrackCount;
|
||||
|
||||
PLAYSTATE m_State;
|
||||
std::wstring m_Artist;
|
||||
std::wstring m_Album;
|
||||
std::wstring m_Title;
|
||||
std::wstring m_FilePath; // Path to playing file
|
||||
std::wstring m_Album;
|
||||
std::wstring m_Lyrics;
|
||||
std::wstring m_CoverPath; // Path to cover art image
|
||||
std::wstring m_PlayerPath; // Path to player executable
|
||||
std::wstring m_FilePath; // Path to playing file
|
||||
UINT m_Duration; // Track duration in seconds
|
||||
UINT m_Position; // Current position in seconds
|
||||
UINT m_Rating; // Track rating from 0 to 100
|
||||
UINT m_Volume; // Volume from 0 to 100
|
||||
|
||||
std::wstring m_TrackChangeAction;
|
||||
};
|
||||
|
||||
#endif
|
@ -30,7 +30,6 @@ extern CPlayer* g_AIMP;
|
||||
**
|
||||
*/
|
||||
CPlayerAIMP::CPlayerAIMP() : CPlayer(),
|
||||
m_HasCoverMeasure(false),
|
||||
m_FileMap(),
|
||||
m_FileMapHandle(),
|
||||
m_Window(),
|
||||
@ -46,41 +45,17 @@ CPlayerAIMP::CPlayerAIMP() : CPlayer(),
|
||||
*/
|
||||
CPlayerAIMP::~CPlayerAIMP()
|
||||
{
|
||||
g_AIMP = NULL;
|
||||
if (m_FileMap) UnmapViewOfFile(m_FileMap);
|
||||
if (m_FileMapHandle) CloseHandle(m_FileMapHandle);
|
||||
}
|
||||
|
||||
/*
|
||||
** AddInstance
|
||||
** Initialize
|
||||
**
|
||||
** Called during initialization of each measure.
|
||||
** Find AIMP window and mapped object.
|
||||
**
|
||||
*/
|
||||
void CPlayerAIMP::AddInstance(MEASURETYPE type)
|
||||
{
|
||||
++m_InstanceCount;
|
||||
|
||||
if (type == MEASURE_COVER)
|
||||
{
|
||||
m_HasCoverMeasure = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** RemoveInstance
|
||||
**
|
||||
** Called during destruction of each measure.
|
||||
**
|
||||
*/
|
||||
void CPlayerAIMP::RemoveInstance()
|
||||
{
|
||||
if (--m_InstanceCount == 0)
|
||||
{
|
||||
g_AIMP = NULL;
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
bool CPlayerAIMP::Initialize()
|
||||
{
|
||||
m_Window = FindWindow(L"AIMP2_RemoteInfo", L"AIMP2_RemoteInfo");
|
||||
@ -118,7 +93,7 @@ bool CPlayerAIMP::CheckActive()
|
||||
m_WinampWindow = NULL;
|
||||
if (m_FileMap) UnmapViewOfFile(m_FileMap);
|
||||
if (m_FileMapHandle) CloseHandle(m_FileMapHandle);
|
||||
ClearInfo();
|
||||
ClearData();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -162,24 +137,18 @@ void CPlayerAIMP::UpdateData()
|
||||
return;
|
||||
}
|
||||
|
||||
m_State = (PLAYERSTATE)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 (oldFileSize != 0)
|
||||
{
|
||||
oldFileSize = 0;
|
||||
oldTitleLen = 0;
|
||||
ClearInfo();
|
||||
ClearData();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_TrackChanged)
|
||||
{
|
||||
ExecuteTrackChangeAction();
|
||||
m_TrackChanged = false;
|
||||
}
|
||||
|
||||
m_Position = SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_POS);
|
||||
m_Volume = SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_VOLUME);
|
||||
|
||||
@ -217,37 +186,12 @@ void CPlayerAIMP::UpdateData()
|
||||
if (filepath != m_FilePath)
|
||||
{
|
||||
m_FilePath = filepath;
|
||||
m_TrackChanged = true;
|
||||
++m_TrackCount;
|
||||
|
||||
// Find cover if needed
|
||||
if (m_HasCoverMeasure)
|
||||
{
|
||||
if (GetCachedArt())
|
||||
{
|
||||
// Cover is in cache, lets use the that
|
||||
return;
|
||||
}
|
||||
|
||||
TagLib::FileRef fr(m_FilePath.c_str());
|
||||
if (!fr.isNull() && fr.tag() && GetEmbeddedArt(fr))
|
||||
{
|
||||
// Embedded art found
|
||||
return;
|
||||
}
|
||||
|
||||
// Get rid of the name and extension from filename
|
||||
std::wstring trackFolder = m_FilePath;
|
||||
std::wstring::size_type pos = trackFolder.find_last_of(L'\\');
|
||||
if (pos == std::wstring::npos) return;
|
||||
trackFolder.resize(++pos);
|
||||
|
||||
if (GetLocalArt(trackFolder, L"cover") || GetLocalArt(trackFolder, L"folder"))
|
||||
{
|
||||
// Local art found
|
||||
return;
|
||||
}
|
||||
|
||||
// Nothing found
|
||||
m_CoverPath.clear();
|
||||
GetCover(m_Artist, m_Title, m_FilePath, m_CoverPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -261,10 +205,7 @@ void CPlayerAIMP::UpdateData()
|
||||
*/
|
||||
void CPlayerAIMP::Pause()
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_PAUSE);
|
||||
}
|
||||
SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_PAUSE);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -275,21 +216,7 @@ void CPlayerAIMP::Pause()
|
||||
*/
|
||||
void CPlayerAIMP::Play()
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_PLAY);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** PlayPause
|
||||
**
|
||||
** Handles the PlayPause bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerAIMP::PlayPause()
|
||||
{
|
||||
(m_State == PLAYER_STOPPED) ? Play() : Pause();
|
||||
SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_PLAY);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -300,10 +227,7 @@ void CPlayerAIMP::PlayPause()
|
||||
*/
|
||||
void CPlayerAIMP::Stop()
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_STOP);
|
||||
}
|
||||
SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_STOP);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -314,10 +238,7 @@ void CPlayerAIMP::Stop()
|
||||
*/
|
||||
void CPlayerAIMP::Next()
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_NEXT);
|
||||
}
|
||||
SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_NEXT);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -328,10 +249,7 @@ void CPlayerAIMP::Next()
|
||||
*/
|
||||
void CPlayerAIMP::Previous()
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_PREV);
|
||||
}
|
||||
SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_PREV);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -354,7 +272,7 @@ void CPlayerAIMP::SetPosition(int position)
|
||||
void CPlayerAIMP::SetRating(int rating)
|
||||
{
|
||||
// Set rating through the AIMP Winamp API
|
||||
if (m_WinampWindow && (m_State == PLAYER_PLAYING || m_State == PLAYER_PAUSED))
|
||||
if (m_State != PLAYER_STOPPED)
|
||||
{
|
||||
if (rating < 0)
|
||||
{
|
||||
@ -389,10 +307,7 @@ void CPlayerAIMP::SetVolume(int volume)
|
||||
*/
|
||||
void CPlayerAIMP::ClosePlayer()
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
SendMessage(m_Window, WM_CLOSE, 0, 0);
|
||||
}
|
||||
SendMessage(m_Window, WM_CLOSE, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -401,9 +316,9 @@ void CPlayerAIMP::ClosePlayer()
|
||||
** Handles the OpenPlayer bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerAIMP::OpenPlayer()
|
||||
void CPlayerAIMP::OpenPlayer(std::wstring& path)
|
||||
{
|
||||
if (m_PlayerPath.empty())
|
||||
if (path.empty())
|
||||
{
|
||||
// Check for AIMP2 first
|
||||
DWORD size = 512;
|
||||
@ -427,7 +342,7 @@ void CPlayerAIMP::OpenPlayer()
|
||||
if (type == REG_SZ)
|
||||
{
|
||||
ShellExecute(NULL, L"open", data, NULL, NULL, SW_SHOW);
|
||||
m_PlayerPath = data;
|
||||
path = data;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -449,11 +364,10 @@ void CPlayerAIMP::OpenPlayer()
|
||||
{
|
||||
if (type == REG_SZ)
|
||||
{
|
||||
std::wstring path = data;
|
||||
path = data;
|
||||
path.resize(path.find_last_of(L'\\') + 1);
|
||||
path += L"AIMP3.exe";
|
||||
ShellExecute(NULL, L"open", path.c_str(), NULL, NULL, SW_SHOW);
|
||||
m_PlayerPath = path;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -463,17 +377,6 @@ void CPlayerAIMP::OpenPlayer()
|
||||
}
|
||||
else
|
||||
{
|
||||
ShellExecute(NULL, L"open", m_PlayerPath.c_str(), NULL, NULL, SW_SHOW);
|
||||
ShellExecute(NULL, L"open", path.c_str(), NULL, NULL, SW_SHOW);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** TogglePlayer
|
||||
**
|
||||
** Handles the TogglePlayer bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerAIMP::TogglePlayer()
|
||||
{
|
||||
m_Window ? ClosePlayer() : OpenPlayer();
|
||||
}
|
||||
|
@ -27,9 +27,10 @@ public:
|
||||
CPlayerAIMP();
|
||||
~CPlayerAIMP();
|
||||
|
||||
virtual void UpdateData();
|
||||
|
||||
virtual void Pause();
|
||||
virtual void Play();
|
||||
virtual void PlayPause();
|
||||
virtual void Stop();
|
||||
virtual void Next();
|
||||
virtual void Previous();
|
||||
@ -37,18 +38,12 @@ public:
|
||||
virtual void SetRating(int rating);
|
||||
virtual void SetVolume(int volume);
|
||||
virtual void ClosePlayer();
|
||||
virtual void OpenPlayer();
|
||||
virtual void TogglePlayer();
|
||||
|
||||
virtual void AddInstance(MEASURETYPE type);
|
||||
virtual void RemoveInstance();
|
||||
virtual void UpdateData();
|
||||
virtual void OpenPlayer(std::wstring& path);
|
||||
|
||||
private:
|
||||
bool Initialize();
|
||||
bool CheckActive();
|
||||
|
||||
bool m_HasCoverMeasure;
|
||||
LPVOID m_FileMap;
|
||||
HANDLE m_FileMapHandle;
|
||||
HWND m_Window; // AIMP window
|
||||
|
@ -33,7 +33,6 @@ extern std::wstring g_SettingsFile;
|
||||
**
|
||||
*/
|
||||
CPlayerCAD::CPlayerCAD() : CPlayer(),
|
||||
m_HasCoverMeasure(false),
|
||||
m_Window(),
|
||||
m_PlayerWindow()
|
||||
{
|
||||
@ -48,40 +47,10 @@ CPlayerCAD::CPlayerCAD() : CPlayer(),
|
||||
*/
|
||||
CPlayerCAD::~CPlayerCAD()
|
||||
{
|
||||
g_CAD = NULL;
|
||||
Uninitialize();
|
||||
}
|
||||
|
||||
/*
|
||||
** AddInstance
|
||||
**
|
||||
** Called during initialization of each measure.
|
||||
**
|
||||
*/
|
||||
void CPlayerCAD::AddInstance(MEASURETYPE type)
|
||||
{
|
||||
++m_InstanceCount;
|
||||
|
||||
if (type == MEASURE_COVER)
|
||||
{
|
||||
m_HasCoverMeasure = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** RemoveInstance
|
||||
**
|
||||
** Called during destruction of each measure.
|
||||
**
|
||||
*/
|
||||
void CPlayerCAD::RemoveInstance()
|
||||
{
|
||||
if (--m_InstanceCount == 0)
|
||||
{
|
||||
g_CAD = NULL;
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize
|
||||
**
|
||||
@ -145,7 +114,7 @@ void CPlayerCAD::Initialize()
|
||||
if (m_PlayerWindow)
|
||||
{
|
||||
SendMessage(m_PlayerWindow, WM_USER, (WPARAM)m_Window, IPC_SET_CALLBACK_HWND);
|
||||
m_State = (PLAYERSTATE)SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_PLAYER_STATE);
|
||||
m_State = (PLAYSTATE)SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_PLAYER_STATE);
|
||||
|
||||
if (m_State != PLAYER_STOPPED)
|
||||
{
|
||||
@ -195,16 +164,16 @@ LRESULT CALLBACK CPlayerCAD::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
|
||||
break;
|
||||
|
||||
case IPC_PLAYER_STATE_CHANGED_NOTIFICATION:
|
||||
p->m_State = (PLAYERSTATE)wParam;
|
||||
p->m_State = (PLAYSTATE)wParam;
|
||||
if (p->m_State == PLAYER_STOPPED)
|
||||
{
|
||||
p->ClearInfo();
|
||||
p->ClearData();
|
||||
}
|
||||
break;
|
||||
|
||||
case IPC_SHUTDOWN_NOTIFICATION:
|
||||
p->m_PlayerWindow = NULL;
|
||||
p->ClearInfo();
|
||||
p->ClearData();
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
@ -214,7 +183,9 @@ LRESULT CALLBACK CPlayerCAD::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
|
||||
PCOPYDATASTRUCT cds = (PCOPYDATASTRUCT)lParam;
|
||||
if (cds->dwData == IPC_CURRENT_TRACK_INFO)
|
||||
{
|
||||
p->m_TrackChanged = true;
|
||||
// TODO: Sent on track update?
|
||||
++p->m_TrackCount;
|
||||
|
||||
std::wstring data = (WCHAR*)cds->lpData;
|
||||
std::wstring::size_type len = data.find_first_of(L'\t');
|
||||
p->m_Title.assign(data, 0, len);
|
||||
@ -282,7 +253,7 @@ LRESULT CALLBACK CPlayerCAD::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
|
||||
|
||||
if (p->m_PlayerWindow)
|
||||
{
|
||||
p->m_State = (PLAYERSTATE)SendMessage(p->m_PlayerWindow, WM_USER, 0, IPC_GET_PLAYER_STATE);
|
||||
p->m_State = (PLAYSTATE)SendMessage(p->m_PlayerWindow, WM_USER, 0, IPC_GET_PLAYER_STATE);
|
||||
|
||||
if (p->m_State != PLAYER_STOPPED)
|
||||
{
|
||||
@ -311,12 +282,6 @@ void CPlayerCAD::UpdateData()
|
||||
{
|
||||
m_Position = SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_POSITION);
|
||||
m_Volume = SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_VOLUME);
|
||||
|
||||
if (m_TrackChanged)
|
||||
{
|
||||
ExecuteTrackChangeAction();
|
||||
m_TrackChanged = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -328,10 +293,7 @@ void CPlayerCAD::UpdateData()
|
||||
*/
|
||||
void CPlayerCAD::Pause()
|
||||
{
|
||||
if (m_PlayerWindow)
|
||||
{
|
||||
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_FORCEPAUSE);
|
||||
}
|
||||
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_FORCEPAUSE);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -342,25 +304,7 @@ void CPlayerCAD::Pause()
|
||||
*/
|
||||
void CPlayerCAD::Play()
|
||||
{
|
||||
if (m_PlayerWindow)
|
||||
{
|
||||
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_PLAY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
** PlayPause
|
||||
**
|
||||
** Handles the PlayPause bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerCAD::PlayPause()
|
||||
{
|
||||
if (m_PlayerWindow)
|
||||
{
|
||||
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_PLAYPAUSE);
|
||||
}
|
||||
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_PLAY);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -371,10 +315,7 @@ void CPlayerCAD::PlayPause()
|
||||
*/
|
||||
void CPlayerCAD::Stop()
|
||||
{
|
||||
if (m_PlayerWindow)
|
||||
{
|
||||
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_STOP);
|
||||
}
|
||||
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_STOP);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -385,10 +326,7 @@ void CPlayerCAD::Stop()
|
||||
*/
|
||||
void CPlayerCAD::Next()
|
||||
{
|
||||
if (m_PlayerWindow)
|
||||
{
|
||||
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_NEXT);
|
||||
}
|
||||
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_NEXT);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -399,10 +337,7 @@ void CPlayerCAD::Next()
|
||||
*/
|
||||
void CPlayerCAD::Previous()
|
||||
{
|
||||
if (m_PlayerWindow)
|
||||
{
|
||||
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_PREVIOUS);
|
||||
}
|
||||
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_PREVIOUS);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -424,12 +359,9 @@ void CPlayerCAD::SetPosition(int position)
|
||||
*/
|
||||
void CPlayerCAD::SetRating(int rating)
|
||||
{
|
||||
if (m_PlayerWindow)
|
||||
{
|
||||
m_Rating = rating;
|
||||
rating *= 2; // From 0 - 5 to 0 - 10
|
||||
SendMessage(m_PlayerWindow, WM_USER, rating, IPC_RATING_CHANGED_NOTIFICATION);
|
||||
}
|
||||
m_Rating = rating;
|
||||
rating *= 2; // From 0 - 5 to 0 - 10
|
||||
SendMessage(m_PlayerWindow, WM_USER, rating, IPC_RATING_CHANGED_NOTIFICATION);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -440,18 +372,15 @@ void CPlayerCAD::SetRating(int rating)
|
||||
*/
|
||||
void CPlayerCAD::SetVolume(int volume)
|
||||
{
|
||||
if (m_PlayerWindow)
|
||||
if (volume < 0)
|
||||
{
|
||||
if (volume < 0)
|
||||
{
|
||||
volume = 0;
|
||||
}
|
||||
else if (volume > 100)
|
||||
{
|
||||
volume = 100;
|
||||
}
|
||||
SendMessage(m_PlayerWindow, WM_USER, volume, IPC_SET_VOLUME);
|
||||
volume = 0;
|
||||
}
|
||||
else if (volume > 100)
|
||||
{
|
||||
volume = 100;
|
||||
}
|
||||
SendMessage(m_PlayerWindow, WM_USER, volume, IPC_SET_VOLUME);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -464,7 +393,7 @@ void CPlayerCAD::ClosePlayer()
|
||||
{
|
||||
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_CLOSE_PLAYER);
|
||||
m_PlayerWindow = NULL;
|
||||
ClearInfo();
|
||||
ClearData();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -473,21 +402,14 @@ void CPlayerCAD::ClosePlayer()
|
||||
** Handles the OpenPlayer bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerCAD::OpenPlayer()
|
||||
void CPlayerCAD::OpenPlayer(std::wstring& path)
|
||||
{
|
||||
if (!m_PlayerPath.empty())
|
||||
if (!path.empty())
|
||||
{
|
||||
ShellExecute(NULL, L"open", path.c_str(), NULL, NULL, SW_SHOW);
|
||||
}
|
||||
else if (!m_PlayerPath.empty())
|
||||
{
|
||||
ShellExecute(NULL, L"open", m_PlayerPath.c_str(), NULL, NULL, SW_SHOW);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** TogglePlayer
|
||||
**
|
||||
** Handles the TogglePlayer bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerCAD::TogglePlayer()
|
||||
{
|
||||
m_PlayerWindow ? ClosePlayer() : OpenPlayer();
|
||||
}
|
||||
|
@ -27,9 +27,10 @@ public:
|
||||
CPlayerCAD();
|
||||
~CPlayerCAD();
|
||||
|
||||
virtual void UpdateData();
|
||||
|
||||
virtual void Pause();
|
||||
virtual void Play();
|
||||
virtual void PlayPause();
|
||||
virtual void Stop();
|
||||
virtual void Next();
|
||||
virtual void Previous();
|
||||
@ -37,21 +38,16 @@ public:
|
||||
virtual void SetRating(int rating);
|
||||
virtual void SetVolume(int volume);
|
||||
virtual void ClosePlayer();
|
||||
virtual void OpenPlayer();
|
||||
virtual void TogglePlayer();
|
||||
|
||||
virtual void AddInstance(MEASURETYPE type);
|
||||
virtual void RemoveInstance();
|
||||
virtual void UpdateData();
|
||||
virtual void OpenPlayer(std::wstring& path);
|
||||
|
||||
private:
|
||||
void Initialize();
|
||||
void Uninitialize();
|
||||
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
bool m_HasCoverMeasure;
|
||||
HWND m_Window;
|
||||
HWND m_PlayerWindow;
|
||||
std::wstring m_PlayerPath;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -28,7 +28,6 @@ extern CPlayer* g_Foobar;
|
||||
**
|
||||
*/
|
||||
CPlayerFoobar::CPlayerFoobar() : CPlayer(),
|
||||
m_HasCoverMeasure(false),
|
||||
m_Window(),
|
||||
m_FooWindow()
|
||||
{
|
||||
@ -43,40 +42,10 @@ CPlayerFoobar::CPlayerFoobar() : CPlayer(),
|
||||
*/
|
||||
CPlayerFoobar::~CPlayerFoobar()
|
||||
{
|
||||
g_Foobar = NULL;
|
||||
Uninitialize();
|
||||
}
|
||||
|
||||
/*
|
||||
** AddInstance
|
||||
**
|
||||
** Called during initialization of each measure.
|
||||
**
|
||||
*/
|
||||
void CPlayerFoobar::AddInstance(MEASURETYPE type)
|
||||
{
|
||||
++m_InstanceCount;
|
||||
|
||||
if (type == MEASURE_COVER)
|
||||
{
|
||||
m_HasCoverMeasure = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** RemoveInstance
|
||||
**
|
||||
** Called during destruction of each measure.
|
||||
**
|
||||
*/
|
||||
void CPlayerFoobar::RemoveInstance()
|
||||
{
|
||||
if (--m_InstanceCount == 0)
|
||||
{
|
||||
g_Foobar = NULL;
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize
|
||||
**
|
||||
@ -150,7 +119,7 @@ void CPlayerFoobar::Uninitialize()
|
||||
*/
|
||||
LRESULT CALLBACK CPlayerFoobar::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static CPlayerFoobar* foobar;
|
||||
static CPlayerFoobar* player;
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
@ -158,7 +127,7 @@ LRESULT CALLBACK CPlayerFoobar::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
|
||||
{
|
||||
// Get pointer to the CPlayerFoobar class from the CreateWindow call
|
||||
LPVOID params = ((CREATESTRUCT*)lParam)->lpCreateParams;
|
||||
foobar = (CPlayerFoobar*)params;
|
||||
player = (CPlayerFoobar*)params;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -170,33 +139,33 @@ LRESULT CALLBACK CPlayerFoobar::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
|
||||
|
||||
case FOO_STATECHANGE:
|
||||
{
|
||||
PLAYERSTATE ps = (PLAYERSTATE)wParam;
|
||||
PLAYSTATE ps = (PLAYSTATE)wParam;
|
||||
if (ps == PLAYER_STOPPED)
|
||||
{
|
||||
foobar->ClearInfo();
|
||||
player->ClearData();
|
||||
}
|
||||
else
|
||||
{
|
||||
foobar->m_State = ps;
|
||||
player->m_State = ps;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FOO_TIMECHANGE:
|
||||
foobar->m_Position = (UINT)wParam;
|
||||
player->m_Position = (UINT)wParam;
|
||||
break;
|
||||
|
||||
case FOO_VOLUMECHANGE:
|
||||
foobar->m_Volume = (UINT)wParam;
|
||||
player->m_Volume = (UINT)wParam;
|
||||
break;
|
||||
|
||||
case FOO_PLAYERSTART:
|
||||
foobar->m_FooWindow = (HWND)wParam;
|
||||
player->m_FooWindow = (HWND)wParam;
|
||||
break;
|
||||
|
||||
case FOO_PLAYERQUIT:
|
||||
foobar->m_FooWindow = NULL;
|
||||
foobar->ClearInfo();
|
||||
player->m_FooWindow = NULL;
|
||||
player->ClearData();
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
@ -207,51 +176,52 @@ LRESULT CALLBACK CPlayerFoobar::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
|
||||
|
||||
if (cds->dwData == FOO_TRACKCHANGE)
|
||||
{
|
||||
if (foobar->m_State != PLAYER_PLAYING)
|
||||
if (player->m_State != PLAYER_PLAYING)
|
||||
{
|
||||
foobar->m_State = PLAYER_PLAYING;
|
||||
player->m_State = PLAYER_PLAYING;
|
||||
}
|
||||
|
||||
// In the format "TITLE ARTIST ALBUM LENGTH RATING" (seperated by \t)
|
||||
WCHAR buffer[1024];
|
||||
MultiByteToWideChar(CP_UTF8, 0, (char*)cds->lpData, cds->cbData, buffer, 1024);
|
||||
foobar->m_Artist = buffer;
|
||||
player->m_Artist = buffer;
|
||||
|
||||
WCHAR* token = wcstok(buffer, L"\t");
|
||||
if (token)
|
||||
{
|
||||
foobar->m_Title = token;
|
||||
player->m_Title = token;
|
||||
}
|
||||
token = wcstok(NULL, L"\t");
|
||||
if (token)
|
||||
{
|
||||
foobar->m_Artist = token;
|
||||
player->m_Artist = token;
|
||||
}
|
||||
token = wcstok(NULL, L"\t");
|
||||
if (token)
|
||||
{
|
||||
foobar->m_Album = token;
|
||||
player->m_Album = token;
|
||||
}
|
||||
token = wcstok(NULL, L"\t");
|
||||
if (token)
|
||||
{
|
||||
foobar->m_Duration = _wtoi(token);
|
||||
player->m_Duration = _wtoi(token);
|
||||
}
|
||||
token = wcstok(NULL, L"\t");
|
||||
if (token)
|
||||
{
|
||||
foobar->m_Rating = _wtoi(token);
|
||||
player->m_Rating = _wtoi(token);
|
||||
}
|
||||
token = wcstok(NULL, L"\t");
|
||||
if (token)
|
||||
if (token && wcscmp(token, player->m_FilePath.c_str()) != 0)
|
||||
{
|
||||
if (wcscmp(token, foobar->m_FilePath.c_str()) != 0)
|
||||
// If different file
|
||||
++player->m_TrackCount;
|
||||
player->m_FilePath = token;
|
||||
player->m_Position = 0;
|
||||
|
||||
if (player->m_HasCoverMeasure || player->m_InstanceCount == 0)
|
||||
{
|
||||
// If different file
|
||||
foobar->m_FilePath = token;
|
||||
foobar->m_TrackChanged = true;
|
||||
foobar->m_Position = 0;
|
||||
foobar->GetCoverArt(token);
|
||||
GetCover(player->m_Artist, player->m_Title, player->m_FilePath, player->m_CoverPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -263,47 +233,6 @@ LRESULT CALLBACK CPlayerFoobar::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** GetCoverArt
|
||||
**
|
||||
** Try to find cover art for file.
|
||||
**
|
||||
*/
|
||||
void CPlayerFoobar::GetCoverArt(LPTSTR filename)
|
||||
{
|
||||
// TODO: Fix temp solution
|
||||
if (m_HasCoverMeasure || m_InstanceCount == 0)
|
||||
{
|
||||
if (GetCachedArt())
|
||||
{
|
||||
// Cover is in cache, lets use the that
|
||||
return;
|
||||
}
|
||||
|
||||
TagLib::FileRef fr(filename);
|
||||
if (!fr.isNull() && fr.tag() && GetEmbeddedArt(fr))
|
||||
{
|
||||
// Embedded art found
|
||||
return;
|
||||
}
|
||||
|
||||
// Get rid of the name and extension from filename
|
||||
std::wstring trackFolder = filename;
|
||||
std::wstring::size_type pos = trackFolder.find_last_of(L'\\');
|
||||
if (pos == std::wstring::npos) return;
|
||||
trackFolder.resize(++pos);
|
||||
|
||||
if (GetLocalArt(trackFolder, L"cover") || GetLocalArt(trackFolder, L"folder"))
|
||||
{
|
||||
// Local art found
|
||||
return;
|
||||
}
|
||||
|
||||
// Nothing found
|
||||
m_CoverPath.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** UpdateData
|
||||
**
|
||||
@ -312,11 +241,6 @@ void CPlayerFoobar::GetCoverArt(LPTSTR filename)
|
||||
*/
|
||||
void CPlayerFoobar::UpdateData()
|
||||
{
|
||||
if (m_TrackChanged)
|
||||
{
|
||||
ExecuteTrackChangeAction();
|
||||
m_TrackChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -327,10 +251,7 @@ void CPlayerFoobar::UpdateData()
|
||||
*/
|
||||
void CPlayerFoobar::Pause()
|
||||
{
|
||||
if (m_FooWindow)
|
||||
{
|
||||
SendMessage(m_FooWindow, WM_USER, 0, FOO_PAUSE);
|
||||
}
|
||||
SendMessage(m_FooWindow, WM_USER, 0, FOO_PAUSE);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -341,24 +262,7 @@ void CPlayerFoobar::Pause()
|
||||
*/
|
||||
void CPlayerFoobar::Play()
|
||||
{
|
||||
if (m_FooWindow)
|
||||
{
|
||||
SendMessage(m_FooWindow, WM_USER, 0, FOO_PLAY);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** PlayPause
|
||||
**
|
||||
** Handles the PlayPause bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerFoobar::PlayPause()
|
||||
{
|
||||
if (m_FooWindow)
|
||||
{
|
||||
SendMessage(m_FooWindow, WM_USER, 0, FOO_PLAYPAUSE);
|
||||
}
|
||||
SendMessage(m_FooWindow, WM_USER, 0, FOO_PLAY);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -369,10 +273,7 @@ void CPlayerFoobar::PlayPause()
|
||||
*/
|
||||
void CPlayerFoobar::Stop()
|
||||
{
|
||||
if (m_FooWindow)
|
||||
{
|
||||
SendMessage(m_FooWindow, WM_USER, 0, FOO_STOP);
|
||||
}
|
||||
SendMessage(m_FooWindow, WM_USER, 0, FOO_STOP);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -383,10 +284,7 @@ void CPlayerFoobar::Stop()
|
||||
*/
|
||||
void CPlayerFoobar::Next()
|
||||
{
|
||||
if (m_FooWindow)
|
||||
{
|
||||
SendMessage(m_FooWindow, WM_USER, 0, FOO_NEXT);
|
||||
}
|
||||
SendMessage(m_FooWindow, WM_USER, 0, FOO_NEXT);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -397,10 +295,7 @@ void CPlayerFoobar::Next()
|
||||
*/
|
||||
void CPlayerFoobar::Previous()
|
||||
{
|
||||
if (m_FooWindow)
|
||||
{
|
||||
SendMessage(m_FooWindow, WM_USER, 0, FOO_PREVIOUS);
|
||||
}
|
||||
SendMessage(m_FooWindow, WM_USER, 0, FOO_PREVIOUS);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -411,10 +306,7 @@ void CPlayerFoobar::Previous()
|
||||
*/
|
||||
void CPlayerFoobar::SetPosition(int position)
|
||||
{
|
||||
if (m_FooWindow)
|
||||
{
|
||||
SendMessage(m_FooWindow, WM_USER, position, FOO_SETPOSITION);
|
||||
}
|
||||
SendMessage(m_FooWindow, WM_USER, position, FOO_SETPOSITION);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -425,10 +317,7 @@ void CPlayerFoobar::SetPosition(int position)
|
||||
*/
|
||||
void CPlayerFoobar::SetVolume(int volume)
|
||||
{
|
||||
if (m_FooWindow)
|
||||
{
|
||||
SendMessage(m_FooWindow, WM_USER, volume, FOO_SETVOLUME);
|
||||
}
|
||||
SendMessage(m_FooWindow, WM_USER, volume, FOO_SETVOLUME);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -439,10 +328,7 @@ void CPlayerFoobar::SetVolume(int volume)
|
||||
*/
|
||||
void CPlayerFoobar::ClosePlayer()
|
||||
{
|
||||
if (m_FooWindow)
|
||||
{
|
||||
SendMessage(m_FooWindow, WM_USER, 0, FOO_QUITPLAYER);
|
||||
}
|
||||
SendMessage(m_FooWindow, WM_USER, 0, FOO_QUITPLAYER);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -451,11 +337,11 @@ void CPlayerFoobar::ClosePlayer()
|
||||
** Handles the OpenPlayer bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerFoobar::OpenPlayer()
|
||||
void CPlayerFoobar::OpenPlayer(std::wstring& path)
|
||||
{
|
||||
if (!m_FooWindow)
|
||||
{
|
||||
if (m_PlayerPath.empty())
|
||||
if (path.empty())
|
||||
{
|
||||
// Gotta figure out where foobar2000 is located at
|
||||
HKEY hKey;
|
||||
@ -478,7 +364,7 @@ void CPlayerFoobar::OpenPlayer()
|
||||
{
|
||||
if (type == REG_SZ && data[0] == L'\"')
|
||||
{
|
||||
std::wstring path = data;
|
||||
path = data;
|
||||
path.erase(0, 1); // Get rid of the leading quote
|
||||
std::wstring::size_type pos = path.find_first_of(L'\"');
|
||||
|
||||
@ -486,7 +372,11 @@ void CPlayerFoobar::OpenPlayer()
|
||||
{
|
||||
path.resize(pos); // Get rid the last quote and everything after it
|
||||
ShellExecute(NULL, L"open", path.c_str(), NULL, NULL, SW_SHOW);
|
||||
m_PlayerPath = path;
|
||||
path = path;
|
||||
}
|
||||
else
|
||||
{
|
||||
path.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -496,7 +386,7 @@ void CPlayerFoobar::OpenPlayer()
|
||||
}
|
||||
else
|
||||
{
|
||||
ShellExecute(NULL, L"open", m_PlayerPath.c_str(), NULL, NULL, SW_SHOW);
|
||||
ShellExecute(NULL, L"open", path.c_str(), NULL, NULL, SW_SHOW);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -504,14 +394,3 @@ void CPlayerFoobar::OpenPlayer()
|
||||
SendMessage(m_FooWindow, WM_USER, 0, FOO_SHOWPLAYER);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** TogglePlayer
|
||||
**
|
||||
** Handles the TogglePlayer bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerFoobar::TogglePlayer()
|
||||
{
|
||||
m_FooWindow ? ClosePlayer() : OpenPlayer();
|
||||
}
|
||||
|
@ -27,9 +27,10 @@ public:
|
||||
CPlayerFoobar();
|
||||
~CPlayerFoobar();
|
||||
|
||||
virtual void UpdateData();
|
||||
|
||||
virtual void Pause();
|
||||
virtual void Play();
|
||||
virtual void PlayPause();
|
||||
virtual void Stop();
|
||||
virtual void Next();
|
||||
virtual void Previous();
|
||||
@ -37,12 +38,7 @@ public:
|
||||
virtual void SetRating(int rating) {}
|
||||
virtual void SetVolume(int volume);
|
||||
virtual void ClosePlayer();
|
||||
virtual void OpenPlayer();
|
||||
virtual void TogglePlayer();
|
||||
|
||||
virtual void AddInstance(MEASURETYPE type);
|
||||
virtual void RemoveInstance();
|
||||
virtual void UpdateData();
|
||||
virtual void OpenPlayer(std::wstring& path);
|
||||
|
||||
private:
|
||||
enum FOOMESSAGE
|
||||
@ -76,9 +72,7 @@ private:
|
||||
void Initialize();
|
||||
void Uninitialize();
|
||||
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
void GetCoverArt(LPTSTR filename);
|
||||
|
||||
bool m_HasCoverMeasure;
|
||||
HWND m_Window; // Our reciever window
|
||||
HWND m_FooWindow; // Foobar receiver window
|
||||
};
|
||||
|
@ -114,10 +114,7 @@ HRESULT STDMETHODCALLTYPE CPlayerITunes::CEventHandler::Invoke(DISPID dispidMemb
|
||||
**
|
||||
*/
|
||||
CPlayerITunes::CPlayerITunes() : CPlayer(),
|
||||
m_Initialized(false),
|
||||
m_UserQuitPrompt(false),
|
||||
m_HasCoverMeasure(false),
|
||||
m_Window(),
|
||||
m_iTunes(),
|
||||
m_iTunesEvent()
|
||||
{
|
||||
@ -132,41 +129,11 @@ CPlayerITunes::CPlayerITunes() : CPlayer(),
|
||||
*/
|
||||
CPlayerITunes::~CPlayerITunes()
|
||||
{
|
||||
g_iTunes = NULL;
|
||||
Uninitialize();
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
/*
|
||||
** AddInstance
|
||||
**
|
||||
** Called during initialization of each measure.
|
||||
**
|
||||
*/
|
||||
void CPlayerITunes::AddInstance(MEASURETYPE type)
|
||||
{
|
||||
++m_InstanceCount;
|
||||
|
||||
if (type == MEASURE_COVER)
|
||||
{
|
||||
m_HasCoverMeasure = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** RemoveInstance
|
||||
**
|
||||
** Called during destruction of each measure.
|
||||
**
|
||||
*/
|
||||
void CPlayerITunes::RemoveInstance()
|
||||
{
|
||||
if (--m_InstanceCount == 0)
|
||||
{
|
||||
g_iTunes = NULL;
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize
|
||||
**
|
||||
@ -256,11 +223,17 @@ void CPlayerITunes::Uninitialize()
|
||||
delete m_iTunesEvent;
|
||||
}
|
||||
|
||||
ClearInfo();
|
||||
ClearData();
|
||||
}
|
||||
}
|
||||
|
||||
bool CPlayerITunes::CheckActive()
|
||||
/*
|
||||
** CheckWindow
|
||||
**
|
||||
** Try to find iTunes periodically.
|
||||
**
|
||||
*/
|
||||
bool CPlayerITunes::CheckWindow()
|
||||
{
|
||||
static DWORD oldTime = 0;
|
||||
DWORD time = GetTickCount();
|
||||
@ -268,36 +241,9 @@ bool CPlayerITunes::CheckActive()
|
||||
if (time - oldTime > 5000)
|
||||
{
|
||||
oldTime = time;
|
||||
m_Window = FindWindow(L"iTunes", L"iTunes");
|
||||
return m_Window ? true : false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** UpdateData
|
||||
**
|
||||
** Called during each update of the main measure.
|
||||
**
|
||||
*/
|
||||
void CPlayerITunes::UpdateData()
|
||||
{
|
||||
if (m_Initialized)
|
||||
{
|
||||
if (m_TrackChanged)
|
||||
{
|
||||
ExecuteTrackChangeAction();
|
||||
m_TrackChanged = false;
|
||||
}
|
||||
|
||||
long position;
|
||||
m_iTunes->get_PlayerPosition(&position);
|
||||
m_Position = (UINT)position;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CheckActive())
|
||||
HWND wnd = FindWindow(L"iTunes", L"iTunes");
|
||||
if (wnd)
|
||||
{
|
||||
if (!m_UserQuitPrompt)
|
||||
{
|
||||
@ -309,6 +255,24 @@ void CPlayerITunes::UpdateData()
|
||||
m_UserQuitPrompt = false;
|
||||
}
|
||||
}
|
||||
|
||||
return m_Initialized;
|
||||
}
|
||||
|
||||
/*
|
||||
** UpdateData
|
||||
**
|
||||
** Called during each update of the main measure.
|
||||
**
|
||||
*/
|
||||
void CPlayerITunes::UpdateData()
|
||||
{
|
||||
if ((m_Initialized || CheckWindow()) && m_State != PLAYER_STOPPED)
|
||||
{
|
||||
long position;
|
||||
m_iTunes->get_PlayerPosition(&position);
|
||||
m_Position = (UINT)position;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -352,50 +316,47 @@ void CPlayerITunes::OnTrackChange()
|
||||
file->Release();
|
||||
if (tmpStr && wcscmp(tmpStr, m_FilePath.c_str()) != 0)
|
||||
{
|
||||
++m_TrackCount;
|
||||
m_FilePath = tmpStr;
|
||||
m_TrackChanged = true;
|
||||
|
||||
if (m_HasCoverMeasure)
|
||||
if (m_HasCoverMeasure && !GetCachedCover(m_Artist, m_Title, m_CoverPath))
|
||||
{
|
||||
if (!GetCachedArt())
|
||||
// Art not in cache, check for embedded art
|
||||
IITArtworkCollection* artworkCollection;
|
||||
hr = track->get_Artwork(&artworkCollection);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Art not in cache, check for embedded art
|
||||
IITArtworkCollection* artworkCollection;
|
||||
hr = track->get_Artwork(&artworkCollection);
|
||||
long count;
|
||||
artworkCollection->get_Count(&count);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
if (count > 0)
|
||||
{
|
||||
long count;
|
||||
artworkCollection->get_Count(&count);
|
||||
IITArtwork* artwork;
|
||||
hr = artworkCollection->get_Item(1, &artwork);
|
||||
|
||||
if (count > 0)
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IITArtwork* artwork;
|
||||
hr = artworkCollection->get_Item(1, &artwork);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
tmpStr = m_CoverPath.c_str();
|
||||
hr = artwork->SaveArtworkToFile(tmpStr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
tmpStr = m_CoverPath.c_str();
|
||||
hr = artwork->SaveArtworkToFile(tmpStr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
m_CoverPath.clear();
|
||||
}
|
||||
|
||||
artwork->Release();
|
||||
m_CoverPath.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_CoverPath.clear();
|
||||
}
|
||||
|
||||
artworkCollection->Release();
|
||||
artwork->Release();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_CoverPath.clear();
|
||||
}
|
||||
|
||||
artworkCollection->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_CoverPath.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -405,7 +366,7 @@ void CPlayerITunes::OnTrackChange()
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearInfo();
|
||||
ClearData();
|
||||
}
|
||||
}
|
||||
|
||||
@ -447,10 +408,7 @@ void CPlayerITunes::OnVolumeChange(int volume)
|
||||
*/
|
||||
void CPlayerITunes::Pause()
|
||||
{
|
||||
if (m_Initialized)
|
||||
{
|
||||
m_iTunes->Pause();
|
||||
}
|
||||
m_iTunes->Pause();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -461,24 +419,7 @@ void CPlayerITunes::Pause()
|
||||
*/
|
||||
void CPlayerITunes::Play()
|
||||
{
|
||||
if (m_Initialized)
|
||||
{
|
||||
m_iTunes->Play();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** PlayPause
|
||||
**
|
||||
** Handles the PlayPause bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerITunes::PlayPause()
|
||||
{
|
||||
if (m_Initialized)
|
||||
{
|
||||
m_iTunes->PlayPause();
|
||||
}
|
||||
m_iTunes->Play();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -489,10 +430,7 @@ void CPlayerITunes::PlayPause()
|
||||
*/
|
||||
void CPlayerITunes::Stop()
|
||||
{
|
||||
if (m_Initialized)
|
||||
{
|
||||
m_iTunes->Stop();
|
||||
}
|
||||
m_iTunes->Stop();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -503,10 +441,7 @@ void CPlayerITunes::Stop()
|
||||
*/
|
||||
void CPlayerITunes::Next()
|
||||
{
|
||||
if (m_Initialized)
|
||||
{
|
||||
m_iTunes->NextTrack();
|
||||
}
|
||||
m_iTunes->NextTrack();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -517,10 +452,7 @@ void CPlayerITunes::Next()
|
||||
*/
|
||||
void CPlayerITunes::Previous()
|
||||
{
|
||||
if (m_Initialized)
|
||||
{
|
||||
m_iTunes->PreviousTrack();
|
||||
}
|
||||
m_iTunes->PreviousTrack();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -531,10 +463,7 @@ void CPlayerITunes::Previous()
|
||||
*/
|
||||
void CPlayerITunes::SetPosition(int position)
|
||||
{
|
||||
if (m_Initialized)
|
||||
{
|
||||
m_iTunes->put_PlayerPosition((long)position);
|
||||
}
|
||||
m_iTunes->put_PlayerPosition((long)position);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -545,17 +474,14 @@ void CPlayerITunes::SetPosition(int position)
|
||||
*/
|
||||
void CPlayerITunes::SetRating(int rating)
|
||||
{
|
||||
if (m_Initialized)
|
||||
IITTrack* track;
|
||||
HRESULT hr = m_iTunes->get_CurrentTrack(&track);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
rating *= 20;
|
||||
IITTrack* track;
|
||||
HRESULT hr = m_iTunes->get_CurrentTrack(&track);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
track->put_Rating((long)rating);
|
||||
track->Release();
|
||||
}
|
||||
track->put_Rating((long)rating);
|
||||
track->Release();
|
||||
}
|
||||
}
|
||||
|
||||
@ -567,10 +493,7 @@ void CPlayerITunes::SetRating(int rating)
|
||||
*/
|
||||
void CPlayerITunes::SetVolume(int volume)
|
||||
{
|
||||
if (m_Initialized)
|
||||
{
|
||||
m_iTunes->put_SoundVolume((long)volume);
|
||||
}
|
||||
m_iTunes->put_SoundVolume((long)volume);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -581,12 +504,9 @@ void CPlayerITunes::SetVolume(int volume)
|
||||
*/
|
||||
void CPlayerITunes::ClosePlayer()
|
||||
{
|
||||
if (m_Initialized)
|
||||
{
|
||||
m_UserQuitPrompt = true;
|
||||
m_iTunes->Quit();
|
||||
Uninitialize();
|
||||
}
|
||||
m_UserQuitPrompt = true;
|
||||
m_iTunes->Quit();
|
||||
Uninitialize();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -595,18 +515,7 @@ void CPlayerITunes::ClosePlayer()
|
||||
** Handles the OpenPlayer bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerITunes::OpenPlayer()
|
||||
void CPlayerITunes::OpenPlayer(std::wstring& path)
|
||||
{
|
||||
ShellExecute(NULL, L"open", m_PlayerPath.empty() ? L"iTunes.exe" : m_PlayerPath.c_str(), NULL, NULL, SW_SHOW);
|
||||
}
|
||||
|
||||
/*
|
||||
** TogglePlayer
|
||||
**
|
||||
** Handles the TogglePlayer bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerITunes::TogglePlayer()
|
||||
{
|
||||
m_Initialized ? ClosePlayer() : OpenPlayer();
|
||||
ShellExecute(NULL, L"open", path.empty() ? L"iTunes.exe" : path.c_str(), NULL, NULL, SW_SHOW);
|
||||
}
|
||||
|
@ -38,9 +38,10 @@ public:
|
||||
CPlayerITunes();
|
||||
~CPlayerITunes();
|
||||
|
||||
virtual void UpdateData();
|
||||
|
||||
virtual void Pause();
|
||||
virtual void Play();
|
||||
virtual void PlayPause();
|
||||
virtual void Stop();
|
||||
virtual void Next();
|
||||
virtual void Previous();
|
||||
@ -48,12 +49,7 @@ public:
|
||||
virtual void SetRating(int rating);
|
||||
virtual void SetVolume(int volume);
|
||||
virtual void ClosePlayer();
|
||||
virtual void OpenPlayer();
|
||||
virtual void TogglePlayer();
|
||||
|
||||
virtual void AddInstance(MEASURETYPE type);
|
||||
virtual void RemoveInstance();
|
||||
virtual void UpdateData();
|
||||
virtual void OpenPlayer(std::wstring& path);
|
||||
|
||||
private:
|
||||
class CEventHandler : public _IiTunesEvents
|
||||
@ -85,13 +81,9 @@ private:
|
||||
void OnTrackChange();
|
||||
void OnStateChange(bool playing);
|
||||
void OnVolumeChange(int volume);
|
||||
bool CheckActive();
|
||||
bool CheckWindow();
|
||||
|
||||
bool m_Initialized;
|
||||
bool m_UserQuitPrompt;
|
||||
bool m_HasCoverMeasure;
|
||||
HWND m_Window;
|
||||
|
||||
IiTunes* m_iTunes;
|
||||
CEventHandler* m_iTunesEvent;
|
||||
};
|
||||
|
@ -30,7 +30,6 @@ extern CPlayer* g_Spotify;
|
||||
CPlayerSpotify::CPlayerSpotify() : CPlayer(),
|
||||
m_Window()
|
||||
{
|
||||
GetWindow();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -41,32 +40,33 @@ CPlayerSpotify::CPlayerSpotify() : CPlayer(),
|
||||
*/
|
||||
CPlayerSpotify::~CPlayerSpotify()
|
||||
{
|
||||
g_Spotify = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** AddInstance
|
||||
** CheckWindow
|
||||
**
|
||||
** Called during initialization of each measure.
|
||||
** Try to find Spotify periodically.
|
||||
**
|
||||
*/
|
||||
void CPlayerSpotify::AddInstance(MEASURETYPE type)
|
||||
bool CPlayerSpotify::CheckWindow()
|
||||
{
|
||||
++m_InstanceCount;
|
||||
}
|
||||
|
||||
/*
|
||||
** RemoveInstance
|
||||
**
|
||||
** Called during destruction of each measure.
|
||||
**
|
||||
*/
|
||||
void CPlayerSpotify::RemoveInstance()
|
||||
{
|
||||
if (--m_InstanceCount == 0)
|
||||
static DWORD oldTime = 0;
|
||||
DWORD time = GetTickCount();
|
||||
|
||||
// Try to find Spotify window every 5 seconds
|
||||
if (time - oldTime > 5000)
|
||||
{
|
||||
g_Spotify = NULL;
|
||||
delete this;
|
||||
oldTime = time;
|
||||
|
||||
m_Window = FindWindow(L"SpotifyMainWindow", NULL);
|
||||
if (m_Window)
|
||||
{
|
||||
m_Initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
return m_Initialized;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -77,59 +77,52 @@ void CPlayerSpotify::RemoveInstance()
|
||||
*/
|
||||
void CPlayerSpotify::UpdateData()
|
||||
{
|
||||
if (GetWindow())
|
||||
if (m_Initialized || CheckWindow())
|
||||
{
|
||||
if (m_TrackChanged)
|
||||
{
|
||||
ExecuteTrackChangeAction();
|
||||
m_TrackChanged = false;
|
||||
}
|
||||
|
||||
// Get window text
|
||||
// Parse title and artist from window title
|
||||
WCHAR buffer[256];
|
||||
buffer[0] = 0;
|
||||
GetWindowText(m_Window, buffer, 256);
|
||||
std::wstring title = buffer;
|
||||
|
||||
title.erase(0, 10); // Get rid of "Spotify - "
|
||||
std::wstring::size_type pos = title.find(L" – ");
|
||||
if (pos != std::wstring::npos)
|
||||
if (GetWindowText(m_Window, buffer, 256) > 10)
|
||||
{
|
||||
std::wstring artist = title.substr(0, pos);
|
||||
std::wstring track = title.substr(pos + 3);
|
||||
std::wstring title = buffer;
|
||||
title.erase(0, 10); // Get rid of "Spotify - "
|
||||
|
||||
if (track != m_Title && artist != m_Artist)
|
||||
std::wstring::size_type pos = title.find(L" – ");
|
||||
if (pos != std::wstring::npos)
|
||||
{
|
||||
m_Title = track;
|
||||
m_Artist = artist;
|
||||
m_TrackChanged = true;
|
||||
m_State = PLAYER_PLAYING;
|
||||
std::wstring artist = title.substr(0, pos);
|
||||
std::wstring track = title.substr(pos + 3);
|
||||
|
||||
if (track != m_Title && artist != m_Artist)
|
||||
{
|
||||
m_Title = track;
|
||||
m_Artist = artist;
|
||||
++m_TrackCount;
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (IsWindow(m_Window))
|
||||
{
|
||||
m_State = PLAYER_PAUSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearData();
|
||||
m_Initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
ClearInfo();
|
||||
}
|
||||
|
||||
bool CPlayerSpotify::GetWindow()
|
||||
{
|
||||
m_Window = FindWindow(L"SpotifyMainWindow", NULL);
|
||||
|
||||
return m_Window ? true : false;
|
||||
}
|
||||
|
||||
/*
|
||||
** PlayPause
|
||||
** Play
|
||||
**
|
||||
** Handles the PlayPause bang.
|
||||
** Handles the Play bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerSpotify::PlayPause()
|
||||
void CPlayerSpotify::Play()
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_PLAYPAUSE);
|
||||
}
|
||||
SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_PLAYPAUSE);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -140,10 +133,7 @@ void CPlayerSpotify::PlayPause()
|
||||
*/
|
||||
void CPlayerSpotify::Stop()
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_STOP);
|
||||
}
|
||||
SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_STOP);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -154,10 +144,7 @@ void CPlayerSpotify::Stop()
|
||||
*/
|
||||
void CPlayerSpotify::Next()
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_NEXT);
|
||||
}
|
||||
SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_NEXT);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -168,10 +155,7 @@ void CPlayerSpotify::Next()
|
||||
*/
|
||||
void CPlayerSpotify::Previous()
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_PREV);
|
||||
}
|
||||
SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_PREV);
|
||||
}
|
||||
|
||||
|
||||
@ -183,17 +167,14 @@ void CPlayerSpotify::Previous()
|
||||
*/
|
||||
void CPlayerSpotify::ClosePlayer()
|
||||
{
|
||||
if (m_Window)
|
||||
// A little harsh...
|
||||
DWORD pID;
|
||||
GetWindowThreadProcessId(m_Window, &pID);
|
||||
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pID);
|
||||
if (hProcess)
|
||||
{
|
||||
// A little harsh...
|
||||
DWORD pID;
|
||||
GetWindowThreadProcessId(m_Window, &pID);
|
||||
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pID);
|
||||
if (hProcess)
|
||||
{
|
||||
TerminateProcess(hProcess, 0);
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
TerminateProcess(hProcess, 0);
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,11 +184,11 @@ void CPlayerSpotify::ClosePlayer()
|
||||
** Handles the OpenPlayer bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerSpotify::OpenPlayer()
|
||||
void CPlayerSpotify::OpenPlayer(std::wstring& path)
|
||||
{
|
||||
if (!m_Window)
|
||||
if (!m_Initialized)
|
||||
{
|
||||
if (m_PlayerPath.empty())
|
||||
if (path.empty())
|
||||
{
|
||||
// Gotta figure out where Winamp is located at
|
||||
HKEY hKey;
|
||||
@ -230,11 +211,10 @@ void CPlayerSpotify::OpenPlayer()
|
||||
{
|
||||
if (type == REG_SZ)
|
||||
{
|
||||
std::wstring path = data;
|
||||
path = data;
|
||||
path.erase(0, 1); // Get rid of the leading quote
|
||||
path.resize(path.length() - 3); // And the ",0 at the end
|
||||
ShellExecute(NULL, L"open", path.c_str(), NULL, NULL, SW_SHOW);
|
||||
m_PlayerPath = path;
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,7 +223,7 @@ void CPlayerSpotify::OpenPlayer()
|
||||
}
|
||||
else
|
||||
{
|
||||
ShellExecute(NULL, L"open", m_PlayerPath.c_str(), NULL, NULL, SW_SHOW);
|
||||
ShellExecute(NULL, L"open", path.c_str(), NULL, NULL, SW_SHOW);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -253,14 +233,3 @@ void CPlayerSpotify::OpenPlayer()
|
||||
BringWindowToTop(m_Window);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** TogglePlayer
|
||||
**
|
||||
** Handles the TogglePlayer bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerSpotify::TogglePlayer()
|
||||
{
|
||||
m_Window ? ClosePlayer() : OpenPlayer();
|
||||
}
|
||||
|
@ -21,38 +21,36 @@
|
||||
|
||||
#include "Player.h"
|
||||
|
||||
#define SPOTIFY_PLAYPAUSE 917504
|
||||
#define SPOTIFY_NEXT 720896
|
||||
#define SPOTIFY_PREV 786432
|
||||
#define SPOTIFY_STOP 851968
|
||||
#define SPOTIFY_MUTE 524288
|
||||
#define SPOTIFY_VOLUMEDOWN 589824
|
||||
#define SPOTIFY_VOLUMEUP 655360
|
||||
|
||||
class CPlayerSpotify : public CPlayer
|
||||
{
|
||||
public:
|
||||
CPlayerSpotify();
|
||||
~CPlayerSpotify();
|
||||
|
||||
virtual void Pause() { return PlayPause(); }
|
||||
virtual void Play() { return PlayPause(); }
|
||||
virtual void PlayPause();
|
||||
virtual void Pause() { return Play(); }
|
||||
virtual void Play();
|
||||
virtual void Stop();
|
||||
virtual void Next();
|
||||
virtual void Previous();
|
||||
virtual void ClosePlayer();
|
||||
virtual void OpenPlayer();
|
||||
virtual void TogglePlayer();
|
||||
|
||||
virtual void AddInstance(MEASURETYPE type);
|
||||
virtual void RemoveInstance();
|
||||
virtual void OpenPlayer(std::wstring& path);
|
||||
virtual void UpdateData();
|
||||
|
||||
private:
|
||||
bool GetWindow();
|
||||
enum SPOTIFYCOMMAND
|
||||
{
|
||||
SPOTIFY_MUTE = 524288,
|
||||
SPOTIFY_VOLUMEDOWN = 589824,
|
||||
SPOTIFY_VOLUMEUP = 655360,
|
||||
SPOTIFY_NEXT = 720896,
|
||||
SPOTIFY_PREV = 786432,
|
||||
SPOTIFY_STOP = 851968,
|
||||
SPOTIFY_PLAYPAUSE = 917504
|
||||
};
|
||||
|
||||
HWND m_Window; // Spotify window
|
||||
bool CheckWindow();
|
||||
|
||||
HWND m_Window;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -22,7 +22,7 @@
|
||||
extern CPlayer* g_WLM;
|
||||
|
||||
// This player emulates the MSN/WLM Messenger 'Listening to' interface, which is
|
||||
// supported by OpenPandora, Last.fm, Media Player Classic, TTPlayer, etc.
|
||||
// supported by OpenPandora, Last.fm, Media Player Classic, TTPlayer, Zune, etc.
|
||||
|
||||
/*
|
||||
** CPlayerWLM
|
||||
@ -64,36 +64,11 @@ CPlayerWLM::CPlayerWLM() : CPlayer(),
|
||||
*/
|
||||
CPlayerWLM::~CPlayerWLM()
|
||||
{
|
||||
g_WLM = NULL;
|
||||
DestroyWindow(m_Window);
|
||||
UnregisterClass(L"MsnMsgrUIManager", GetModuleHandle(NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
** AddInstance
|
||||
**
|
||||
** Called during initialization of each measure.
|
||||
**
|
||||
*/
|
||||
void CPlayerWLM::AddInstance(MEASURETYPE type)
|
||||
{
|
||||
++m_InstanceCount;
|
||||
}
|
||||
|
||||
/*
|
||||
** RemoveInstance
|
||||
**
|
||||
** Called during destruction of each measure.
|
||||
**
|
||||
*/
|
||||
void CPlayerWLM::RemoveInstance()
|
||||
{
|
||||
if (--m_InstanceCount == 0)
|
||||
{
|
||||
g_WLM = NULL;
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK CPlayerWLM::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static CPlayerWLM* player;
|
||||
@ -127,6 +102,7 @@ LRESULT CALLBACK CPlayerWLM::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
|
||||
player->m_State = PLAYER_PLAYING;
|
||||
data.erase(0, 3); // Get rid of the status
|
||||
|
||||
// TODO: Handle invalid
|
||||
len = data.find_first_of(L'\\');
|
||||
len += 2;
|
||||
data.erase(0, len); // Get rid of the format
|
||||
@ -146,7 +122,7 @@ LRESULT CALLBACK CPlayerWLM::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
|
||||
}
|
||||
else
|
||||
{
|
||||
player->ClearInfo();
|
||||
player->ClearData();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -180,12 +156,12 @@ void CPlayerWLM::UpdateData()
|
||||
}
|
||||
|
||||
/*
|
||||
** PlayPause
|
||||
** Play
|
||||
**
|
||||
** Handles the PlayPause bang.
|
||||
** Handles the Play bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerWLM::PlayPause()
|
||||
void CPlayerWLM::Play()
|
||||
{
|
||||
SendKeyInput(VK_MEDIA_PLAY_PAUSE);
|
||||
}
|
||||
|
@ -27,22 +27,19 @@ public:
|
||||
CPlayerWLM();
|
||||
~CPlayerWLM();
|
||||
|
||||
virtual void Pause() { return PlayPause(); }
|
||||
virtual void Play() { return PlayPause(); }
|
||||
virtual void PlayPause();
|
||||
virtual void UpdateData();
|
||||
|
||||
virtual void Pause() { return Play(); }
|
||||
virtual void Play();
|
||||
virtual void Stop();
|
||||
virtual void Next();
|
||||
virtual void Previous();
|
||||
|
||||
virtual void AddInstance(MEASURETYPE type);
|
||||
virtual void RemoveInstance();
|
||||
virtual void UpdateData();
|
||||
|
||||
private:
|
||||
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
void SendKeyInput(WORD key);
|
||||
|
||||
HWND m_Window; // Spotify window
|
||||
HWND m_Window;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -111,7 +111,7 @@ void CPlayerWMP::CRemoteHost::PlayStateChange(long NewState)
|
||||
{
|
||||
case wmppsStopped:
|
||||
case wmppsMediaEnded:
|
||||
m_Player->ClearInfo();
|
||||
m_Player->ClearData();
|
||||
break;
|
||||
|
||||
case wmppsPaused:
|
||||
@ -139,7 +139,7 @@ void CPlayerWMP::CRemoteHost::PlayStateChange(long NewState)
|
||||
*/
|
||||
void CPlayerWMP::CRemoteHost::SwitchedToControl()
|
||||
{
|
||||
m_Player->ClearInfo();
|
||||
m_Player->ClearData();
|
||||
m_Player->Uninitialize();
|
||||
}
|
||||
|
||||
@ -150,8 +150,8 @@ void CPlayerWMP::CRemoteHost::SwitchedToControl()
|
||||
**
|
||||
*/
|
||||
CPlayerWMP::CPlayerWMP() : CPlayer(),
|
||||
m_Initialized(false),
|
||||
m_HasCoverMeasure(false),
|
||||
m_TrackChanged(false),
|
||||
m_Window(),
|
||||
m_ComModule(),
|
||||
m_AxWindow(),
|
||||
m_IPlayer(),
|
||||
@ -170,41 +170,11 @@ CPlayerWMP::CPlayerWMP() : CPlayer(),
|
||||
*/
|
||||
CPlayerWMP::~CPlayerWMP()
|
||||
{
|
||||
g_WMP = NULL;
|
||||
Uninitialize();
|
||||
m_ComModule.Term();
|
||||
}
|
||||
|
||||
/*
|
||||
** AddInstance
|
||||
**
|
||||
** Called during initialization of each measure.
|
||||
**
|
||||
*/
|
||||
void CPlayerWMP::AddInstance(MEASURETYPE type)
|
||||
{
|
||||
++m_InstanceCount;
|
||||
|
||||
if (type == MEASURE_COVER)
|
||||
{
|
||||
m_HasCoverMeasure = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** RemoveInstance
|
||||
**
|
||||
** Called during destruction of each measure.
|
||||
**
|
||||
*/
|
||||
void CPlayerWMP::RemoveInstance()
|
||||
{
|
||||
if (--m_InstanceCount == 0)
|
||||
{
|
||||
g_WMP = NULL;
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize
|
||||
**
|
||||
@ -410,7 +380,9 @@ void CPlayerWMP::UpdateData()
|
||||
|
||||
if (m_TrackChanged)
|
||||
{
|
||||
++m_TrackCount;
|
||||
m_TrackChanged = false;
|
||||
|
||||
CComPtr<IWMPMedia> spMedia;
|
||||
m_IPlayer->get_currentMedia(&spMedia);
|
||||
|
||||
@ -462,7 +434,8 @@ void CPlayerWMP::UpdateData()
|
||||
{
|
||||
m_FilePath = targetPath;
|
||||
|
||||
// TODO: Better solution for this
|
||||
// Find cover if needed
|
||||
// TODO: Fix temp solution
|
||||
if (m_HasCoverMeasure || m_InstanceCount == 0)
|
||||
{
|
||||
spMedia->getItemInfo(CComBSTR("WM/WMCollectionID"), &val);
|
||||
@ -477,37 +450,9 @@ void CPlayerWMP::UpdateData()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetCachedArt())
|
||||
{
|
||||
// Cover is in cache, lets use the that
|
||||
return;
|
||||
}
|
||||
|
||||
TagLib::FileRef fr(url.m_str);
|
||||
if (!fr.isNull() && fr.tag() && GetEmbeddedArt(fr))
|
||||
{
|
||||
// Embedded art found
|
||||
return;
|
||||
}
|
||||
|
||||
// Get rid of the name and extension from filename
|
||||
std::wstring trackFolder = url;
|
||||
std::wstring::size_type pos = trackFolder.find_last_of(L'\\');
|
||||
if (pos == std::wstring::npos) return;
|
||||
trackFolder.resize(++pos);
|
||||
|
||||
if (GetLocalArt(trackFolder, L"cover") || GetLocalArt(trackFolder, L"folder"))
|
||||
{
|
||||
// Local art found
|
||||
return;
|
||||
}
|
||||
|
||||
// Nothing found
|
||||
m_CoverPath.clear();
|
||||
GetCover(m_Artist, m_Title, m_FilePath, m_CoverPath);
|
||||
}
|
||||
}
|
||||
|
||||
ExecuteTrackChangeAction();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -538,10 +483,7 @@ void CPlayerWMP::UpdateData()
|
||||
*/
|
||||
void CPlayerWMP::Pause()
|
||||
{
|
||||
if (m_IPlayer)
|
||||
{
|
||||
m_IControls->pause();
|
||||
}
|
||||
m_IControls->pause();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -552,21 +494,7 @@ void CPlayerWMP::Pause()
|
||||
*/
|
||||
void CPlayerWMP::Play()
|
||||
{
|
||||
if (m_IPlayer)
|
||||
{
|
||||
m_IControls->play();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** PlayPause
|
||||
**
|
||||
** Handles the PlayPause bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerWMP::PlayPause()
|
||||
{
|
||||
(m_State == PLAYER_PLAYING) ? Pause() : Play();
|
||||
m_IControls->play();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -577,11 +505,9 @@ void CPlayerWMP::PlayPause()
|
||||
*/
|
||||
void CPlayerWMP::Stop()
|
||||
{
|
||||
if (m_IPlayer)
|
||||
{
|
||||
m_IControls->stop();
|
||||
m_State = PLAYER_STOPPED;
|
||||
}
|
||||
m_IControls->stop();
|
||||
// TODO: FIXME
|
||||
m_State = PLAYER_STOPPED;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -592,10 +518,7 @@ void CPlayerWMP::Stop()
|
||||
*/
|
||||
void CPlayerWMP::Next()
|
||||
{
|
||||
if (m_IPlayer)
|
||||
{
|
||||
m_IControls->next();
|
||||
}
|
||||
m_IControls->next();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -606,10 +529,7 @@ void CPlayerWMP::Next()
|
||||
*/
|
||||
void CPlayerWMP::Previous()
|
||||
{
|
||||
if (m_IPlayer)
|
||||
{
|
||||
m_IControls->previous();
|
||||
}
|
||||
m_IControls->previous();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -620,10 +540,7 @@ void CPlayerWMP::Previous()
|
||||
*/
|
||||
void CPlayerWMP::SetPosition(int position)
|
||||
{
|
||||
if (m_IPlayer)
|
||||
{
|
||||
m_IControls->put_currentPosition((double)position);
|
||||
}
|
||||
m_IControls->put_currentPosition((double)position);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -634,7 +551,7 @@ void CPlayerWMP::SetPosition(int position)
|
||||
*/
|
||||
void CPlayerWMP::SetRating(int rating)
|
||||
{
|
||||
if (m_IPlayer && (m_State == PLAYER_PLAYING || m_State == PLAYER_PAUSED))
|
||||
if (m_State != PLAYER_STOPPED)
|
||||
{
|
||||
CComPtr<IWMPMedia> spMedia;
|
||||
m_IPlayer->get_currentMedia(&spMedia);
|
||||
@ -683,10 +600,7 @@ void CPlayerWMP::SetRating(int rating)
|
||||
*/
|
||||
void CPlayerWMP::SetVolume(int volume)
|
||||
{
|
||||
if (m_IPlayer)
|
||||
{
|
||||
m_ISettings->put_volume(volume);
|
||||
}
|
||||
m_ISettings->put_volume(volume);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -697,14 +611,11 @@ void CPlayerWMP::SetVolume(int volume)
|
||||
*/
|
||||
void CPlayerWMP::ClosePlayer()
|
||||
{
|
||||
if (m_IPlayer)
|
||||
{
|
||||
HWND wmp = FindWindow(L"WMPlayerApp", NULL);
|
||||
HWND wnd = FindWindow(L"WMPlayerApp", NULL);
|
||||
|
||||
if (wmp)
|
||||
{
|
||||
SendMessage(wmp, WM_CLOSE, 0, 0);
|
||||
}
|
||||
if (wnd)
|
||||
{
|
||||
SendMessage(wnd, WM_CLOSE, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -714,18 +625,7 @@ void CPlayerWMP::ClosePlayer()
|
||||
** Handles the OpenPlayer bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerWMP::OpenPlayer()
|
||||
void CPlayerWMP::OpenPlayer(std::wstring& path)
|
||||
{
|
||||
ShellExecute(NULL, L"open", m_PlayerPath.empty() ? L"wmplayer.exe" : m_PlayerPath.c_str(), NULL, NULL, SW_SHOW);
|
||||
}
|
||||
|
||||
/*
|
||||
** TogglePlayer
|
||||
**
|
||||
** Handles the TogglePlayer bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerWMP::TogglePlayer()
|
||||
{
|
||||
m_IPlayer ? ClosePlayer() : OpenPlayer();
|
||||
ShellExecute(NULL, L"open", path.empty() ? L"wmplayer.exe" : path.c_str(), NULL, NULL, SW_SHOW);
|
||||
}
|
||||
|
@ -37,22 +37,18 @@ public:
|
||||
CPlayerWMP();
|
||||
~CPlayerWMP();
|
||||
|
||||
virtual void UpdateData();
|
||||
|
||||
virtual void Pause();
|
||||
virtual void Play();
|
||||
virtual void PlayPause();
|
||||
virtual void Stop();
|
||||
virtual void Next();
|
||||
virtual void Previous();
|
||||
virtual void SetPosition(int position);
|
||||
virtual void SetRating(int rating);
|
||||
virtual void SetVolume(int volume);
|
||||
virtual void OpenPlayer();
|
||||
virtual void OpenPlayer(std::wstring& path);
|
||||
virtual void ClosePlayer();
|
||||
virtual void TogglePlayer();
|
||||
|
||||
virtual void AddInstance(MEASURETYPE type);
|
||||
virtual void RemoveInstance();
|
||||
virtual void UpdateData();
|
||||
|
||||
private:
|
||||
class CRemoteHost :
|
||||
@ -133,11 +129,10 @@ private:
|
||||
void Initialize();
|
||||
void Uninitialize();
|
||||
|
||||
bool m_Initialized;
|
||||
bool m_HasCoverMeasure;
|
||||
bool m_TrackChanged;
|
||||
HWND m_Window;
|
||||
CComModule m_ComModule;
|
||||
CAxWindow* m_AxWindow;
|
||||
CComModule m_ComModule;
|
||||
CComPtr<IWMPPlayer4> m_IPlayer;
|
||||
CComPtr<IWMPControls> m_IControls;
|
||||
CComPtr<IWMPSettings> m_ISettings;
|
||||
|
@ -34,10 +34,8 @@ extern CPlayer* g_Winamp;
|
||||
CPlayerWinamp::CPlayerWinamp(WINAMPTYPE type) : CPlayer(),
|
||||
m_WinampType(type),
|
||||
m_UseUnicodeAPI(false),
|
||||
m_HasCoverMeasure(false),
|
||||
m_Window()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -48,102 +46,43 @@ CPlayerWinamp::CPlayerWinamp(WINAMPTYPE type) : CPlayer(),
|
||||
*/
|
||||
CPlayerWinamp::~CPlayerWinamp()
|
||||
{
|
||||
g_Winamp = NULL;
|
||||
if (m_WinampHandle) CloseHandle(m_WinampHandle);
|
||||
}
|
||||
|
||||
/*
|
||||
** AddInstance
|
||||
** CheckWindow
|
||||
**
|
||||
** Called during initialization of each measure.
|
||||
** Try to find Winamp periodically.
|
||||
**
|
||||
*/
|
||||
void CPlayerWinamp::AddInstance(MEASURETYPE type)
|
||||
bool CPlayerWinamp::CheckWindow()
|
||||
{
|
||||
++m_InstanceCount;
|
||||
|
||||
if (type == MEASURE_COVER)
|
||||
{
|
||||
m_HasCoverMeasure = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** RemoveInstance
|
||||
**
|
||||
** Called during destruction of each measure.
|
||||
**
|
||||
*/
|
||||
void CPlayerWinamp::RemoveInstance()
|
||||
{
|
||||
if (--m_InstanceCount == 0)
|
||||
{
|
||||
g_Winamp = NULL;
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize
|
||||
**
|
||||
** Get things ready with Winamp.
|
||||
**
|
||||
*/
|
||||
bool CPlayerWinamp::Initialize()
|
||||
{
|
||||
m_Window = FindWindow(L"Winamp v1.x", NULL);
|
||||
|
||||
if (m_Window)
|
||||
{
|
||||
DWORD pID;
|
||||
GetWindowThreadProcessId(m_Window, &pID);
|
||||
m_WinampHandle = OpenProcess(PROCESS_VM_READ, false, pID);
|
||||
|
||||
if (m_WinampHandle)
|
||||
{
|
||||
m_WinampAddress = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_PLAYING_FILENAME);
|
||||
m_UseUnicodeAPI = m_WinampAddress ? true : false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** CheckActive
|
||||
**
|
||||
** Check if Winamp is active.
|
||||
**
|
||||
*/
|
||||
bool CPlayerWinamp::CheckActive()
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
if (!IsWindow(m_Window))
|
||||
{
|
||||
m_Window = NULL;
|
||||
CloseHandle(m_WinampHandle);
|
||||
ClearInfo();
|
||||
|
||||
return false;
|
||||
}
|
||||
static DWORD oldTime = 0;
|
||||
DWORD time = GetTickCount();
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
// Try to find Winamp window every 5 seconds
|
||||
if (time - oldTime > 5000)
|
||||
{
|
||||
static DWORD oldTime = 0;
|
||||
DWORD time = GetTickCount();
|
||||
|
||||
// Try to find Winamp window every 5 seconds
|
||||
if (time - oldTime > 5000)
|
||||
{
|
||||
oldTime = time;
|
||||
return Initialize();
|
||||
}
|
||||
oldTime = time;
|
||||
|
||||
return false;
|
||||
m_Window = FindWindow(L"Winamp v1.x", NULL);
|
||||
if (m_Window)
|
||||
{
|
||||
DWORD pID;
|
||||
GetWindowThreadProcessId(m_Window, &pID);
|
||||
m_WinampHandle = OpenProcess(PROCESS_VM_READ, false, pID);
|
||||
|
||||
if (m_WinampHandle)
|
||||
{
|
||||
m_WinampAddress = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_PLAYING_FILENAME);
|
||||
m_UseUnicodeAPI = m_WinampAddress ? true : false;
|
||||
m_Initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m_Initialized;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -154,181 +93,175 @@ bool CPlayerWinamp::CheckActive()
|
||||
*/
|
||||
void CPlayerWinamp::UpdateData()
|
||||
{
|
||||
if (!CheckActive()) return; // Make sure Winamp is running
|
||||
|
||||
if (m_TrackChanged)
|
||||
if (m_Initialized || CheckWindow())
|
||||
{
|
||||
ExecuteTrackChangeAction();
|
||||
m_TrackChanged = false;
|
||||
}
|
||||
|
||||
int playing = SendMessage(m_Window, WM_WA_IPC, 0, IPC_ISPLAYING);
|
||||
if (playing == 0)
|
||||
{
|
||||
if (!m_FilePath.empty())
|
||||
int playing = SendMessage(m_Window, WM_WA_IPC, 0, IPC_ISPLAYING);
|
||||
if (playing == 0)
|
||||
{
|
||||
ClearInfo();
|
||||
}
|
||||
return; // Don't continue if stopped
|
||||
}
|
||||
else
|
||||
{
|
||||
m_State = (playing == 1) ? PLAYER_PLAYING : PLAYER_PAUSED;
|
||||
m_Position = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETOUTPUTTIME) / 1000; // Returns ms, make seconds
|
||||
// Make sure Winamp is still active
|
||||
if (!IsWindow(m_Window))
|
||||
{
|
||||
m_Initialized = false;
|
||||
if (m_WinampHandle) CloseHandle(m_WinampHandle);
|
||||
}
|
||||
|
||||
float volume = SendMessage(m_Window, WM_WA_IPC, -666, IPC_SETVOLUME);
|
||||
volume /= 2.55f;
|
||||
m_Volume = (UINT)volume;
|
||||
}
|
||||
if (!m_FilePath.empty())
|
||||
{
|
||||
ClearData();
|
||||
}
|
||||
|
||||
BOOL ret;
|
||||
WCHAR wBuffer[MAX_PATH];
|
||||
char cBuffer[MAX_PATH];
|
||||
|
||||
if (m_UseUnicodeAPI)
|
||||
{
|
||||
ret = ReadProcessMemory(m_WinampHandle, m_WinampAddress, &wBuffer, MAX_PATH, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// MediaMonkey doesn't support wide IPC messages
|
||||
int pos = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETLISTPOS);
|
||||
LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, pos, IPC_GETPLAYLISTFILE);
|
||||
ret = ReadProcessMemory(m_WinampHandle, address, &cBuffer, MAX_PATH, NULL);
|
||||
mbstowcs(wBuffer, cBuffer, MAX_PATH);
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: Failed to read Winamp memory (file).");
|
||||
return;
|
||||
}
|
||||
|
||||
if (wcscmp(wBuffer, m_FilePath.c_str()) != 0)
|
||||
{
|
||||
m_TrackChanged = true;
|
||||
m_FilePath = wBuffer;
|
||||
m_Rating = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETRATING);
|
||||
m_Duration = SendMessage(m_Window, WM_WA_IPC, 1, IPC_GETOUTPUTTIME);
|
||||
|
||||
TagLib::FileRef fr(wBuffer);
|
||||
if (!fr.isNull() && fr.tag())
|
||||
{
|
||||
TagLib::Tag* tag = fr.tag();
|
||||
m_Artist = tag->artist().toWString();
|
||||
m_Album = tag->album().toWString();
|
||||
m_Title = tag->title().toWString();
|
||||
// Don't continue if Winamp has quit or is stopped
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TagLib couldn't parse the file, try title instead
|
||||
if (m_UseUnicodeAPI)
|
||||
{
|
||||
LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_PLAYING_TITLE);
|
||||
ret = ReadProcessMemory(m_WinampHandle, address, &wBuffer, MAX_PATH, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
int pos = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETLISTPOS);
|
||||
LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, pos, IPC_GETPLAYLISTTITLE);
|
||||
ReadProcessMemory(m_WinampHandle, m_WinampAddress, &cBuffer, MAX_PATH, NULL);
|
||||
ret = mbstowcs(wBuffer, cBuffer, MAX_PATH);
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: Failed to read Winamp memory (title).");
|
||||
return;
|
||||
}
|
||||
|
||||
std::wstring title = wBuffer;
|
||||
std::wstring::size_type pos = title.find(L". ");
|
||||
|
||||
if (pos != std::wstring::npos && pos < 5)
|
||||
{
|
||||
pos += 2; // Skip ". "
|
||||
title.erase(0, pos);
|
||||
}
|
||||
|
||||
pos = title.find(L" - ");
|
||||
if (pos != std::wstring::npos)
|
||||
{
|
||||
m_Title = title.substr(0, pos);
|
||||
pos += 3; // Skip " - "
|
||||
m_Artist = title.substr(pos);
|
||||
m_Album.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearInfo();
|
||||
return;
|
||||
}
|
||||
m_State = (playing == 1) ? PLAYER_PLAYING : PLAYER_PAUSED;
|
||||
m_Position = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETOUTPUTTIME) / 1000; // ms to secs
|
||||
m_Volume = (SendMessage(m_Window, WM_WA_IPC, -666, IPC_SETVOLUME) * 100) / 255; // 0 - 255 to 0 - 100
|
||||
}
|
||||
|
||||
if (m_HasCoverMeasure)
|
||||
BOOL ret;
|
||||
WCHAR wBuffer[MAX_PATH];
|
||||
char cBuffer[MAX_PATH];
|
||||
|
||||
if (m_UseUnicodeAPI)
|
||||
{
|
||||
if (GetCachedArt() || GetEmbeddedArt(fr))
|
||||
ret = ReadProcessMemory(m_WinampHandle, m_WinampAddress, &wBuffer, MAX_PATH, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// MediaMonkey doesn't support wide IPC messages
|
||||
int pos = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETLISTPOS);
|
||||
LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, pos, IPC_GETPLAYLISTFILE);
|
||||
ret = ReadProcessMemory(m_WinampHandle, address, &cBuffer, MAX_PATH, NULL);
|
||||
mbstowcs(wBuffer, cBuffer, MAX_PATH);
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: Failed to read Winamp memory (file).");
|
||||
return;
|
||||
}
|
||||
|
||||
if (wcscmp(wBuffer, m_FilePath.c_str()) != 0)
|
||||
{
|
||||
++m_TrackCount;
|
||||
m_FilePath = wBuffer;
|
||||
m_Rating = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETRATING);
|
||||
m_Duration = SendMessage(m_Window, WM_WA_IPC, 1, IPC_GETOUTPUTTIME);
|
||||
|
||||
TagLib::FileRef fr(wBuffer);
|
||||
if (!fr.isNull() && fr.tag())
|
||||
{
|
||||
// Art found in cache or embedded in file
|
||||
return;
|
||||
TagLib::Tag* tag = fr.tag();
|
||||
m_Artist = tag->artist().toWString();
|
||||
m_Album = tag->album().toWString();
|
||||
m_Title = tag->title().toWString();
|
||||
}
|
||||
|
||||
// Get rid of the name and extension from filename
|
||||
std::wstring trackFolder = m_FilePath;
|
||||
std::wstring::size_type pos = trackFolder.find_last_of(L'\\');
|
||||
if (pos == std::wstring::npos) return;
|
||||
trackFolder.resize(++pos);
|
||||
|
||||
if (!m_Album.empty())
|
||||
else
|
||||
{
|
||||
std::wstring file = m_Album;
|
||||
std::wstring::size_type end = file.length();
|
||||
for (pos = 0; pos < end; ++pos)
|
||||
// TagLib couldn't parse the file, try title instead
|
||||
if (m_UseUnicodeAPI)
|
||||
{
|
||||
// Replace reserved chars according to Winamp specs
|
||||
switch (file[pos])
|
||||
{
|
||||
case L'?':
|
||||
case L'*':
|
||||
case L'|':
|
||||
file[pos] = L'_';
|
||||
break;
|
||||
|
||||
case L'/':
|
||||
case L'\\':
|
||||
case L':':
|
||||
file[pos] = L'-';
|
||||
break;
|
||||
|
||||
case L'\"':
|
||||
file[pos] = L'\'';
|
||||
break;
|
||||
|
||||
case L'<':
|
||||
file[pos] = L'(';
|
||||
break;
|
||||
|
||||
case L'>':
|
||||
file[pos] = L')';
|
||||
break;
|
||||
}
|
||||
LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_PLAYING_TITLE);
|
||||
ret = ReadProcessMemory(m_WinampHandle, address, &wBuffer, MAX_PATH, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
int pos = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETLISTPOS);
|
||||
LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, pos, IPC_GETPLAYLISTTITLE);
|
||||
ReadProcessMemory(m_WinampHandle, m_WinampAddress, &cBuffer, MAX_PATH, NULL);
|
||||
ret = mbstowcs(wBuffer, cBuffer, MAX_PATH);
|
||||
}
|
||||
|
||||
if (GetLocalArt(trackFolder, file))
|
||||
if (!ret)
|
||||
{
|
||||
// %album% art file found
|
||||
LSLog(LOG_ERROR, L"Rainmeter", L"NowPlayingPlugin: Failed to read Winamp memory (title).");
|
||||
return;
|
||||
}
|
||||
|
||||
std::wstring title = wBuffer;
|
||||
std::wstring::size_type pos = title.find(L". ");
|
||||
|
||||
if (pos != std::wstring::npos && pos < 5)
|
||||
{
|
||||
pos += 2; // Skip ". "
|
||||
title.erase(0, pos);
|
||||
}
|
||||
|
||||
pos = title.find(L" - ");
|
||||
if (pos != std::wstring::npos)
|
||||
{
|
||||
m_Title = title.substr(0, pos);
|
||||
pos += 3; // Skip " - "
|
||||
m_Artist = title.substr(pos);
|
||||
m_Album.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearData();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (GetLocalArt(trackFolder, L"cover") || GetLocalArt(trackFolder, L"folder"))
|
||||
// Find cover if needed
|
||||
if (m_HasCoverMeasure &&
|
||||
!GetCachedCover(m_Artist, m_Title, m_CoverPath) &&
|
||||
!GetEmbeddedCover(fr, m_CoverPath))
|
||||
{
|
||||
// Local art found
|
||||
return;
|
||||
}
|
||||
std::wstring trackFolder = GetFileFolder(m_FilePath);
|
||||
|
||||
// Nothing found
|
||||
m_CoverPath.clear();
|
||||
if (!m_Album.empty())
|
||||
{
|
||||
// Winamp stores covers usually as %album%.jpg
|
||||
std::wstring file = m_Album;
|
||||
std::wstring::size_type end = file.length();
|
||||
for (std::wstring::size_type pos = 0; pos < end; ++pos)
|
||||
{
|
||||
// Replace reserved chars according to Winamp specs
|
||||
switch (file[pos])
|
||||
{
|
||||
case L'?':
|
||||
case L'*':
|
||||
case L'|':
|
||||
file[pos] = L'_';
|
||||
break;
|
||||
|
||||
case L'/':
|
||||
case L'\\':
|
||||
case L':':
|
||||
file[pos] = L'-';
|
||||
break;
|
||||
|
||||
case L'\"':
|
||||
file[pos] = L'\'';
|
||||
break;
|
||||
|
||||
case L'<':
|
||||
file[pos] = L'(';
|
||||
break;
|
||||
|
||||
case L'>':
|
||||
file[pos] = L')';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (GetLocalCover(file, trackFolder, m_CoverPath))
|
||||
{
|
||||
// %album% art file found
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!GetLocalCover(L"cover", trackFolder, m_CoverPath) &&
|
||||
!GetLocalCover(L"folder", trackFolder, m_CoverPath))
|
||||
{
|
||||
// Nothing found
|
||||
m_CoverPath.clear();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -341,10 +274,7 @@ void CPlayerWinamp::UpdateData()
|
||||
*/
|
||||
void CPlayerWinamp::Pause()
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
SendMessage(m_Window, WM_COMMAND, WINAMP_PAUSE, 0);
|
||||
}
|
||||
SendMessage(m_Window, WM_COMMAND, WINAMP_PAUSE, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -355,21 +285,7 @@ void CPlayerWinamp::Pause()
|
||||
*/
|
||||
void CPlayerWinamp::Play()
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
SendMessage(m_Window, WM_COMMAND, WINAMP_PLAY, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** PlayPause
|
||||
**
|
||||
** Handles the PlayPause bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerWinamp::PlayPause()
|
||||
{
|
||||
(m_State == PLAYER_PLAYING) ? Pause() : Play();
|
||||
SendMessage(m_Window, WM_COMMAND, WINAMP_PLAY, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -380,10 +296,7 @@ void CPlayerWinamp::PlayPause()
|
||||
*/
|
||||
void CPlayerWinamp::Stop()
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
SendMessage(m_Window, WM_COMMAND, WINAMP_STOP, 0);
|
||||
}
|
||||
SendMessage(m_Window, WM_COMMAND, WINAMP_STOP, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -394,10 +307,7 @@ void CPlayerWinamp::Stop()
|
||||
*/
|
||||
void CPlayerWinamp::Next()
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
SendMessage(m_Window, WM_COMMAND, WINAMP_FASTFWD, 0);
|
||||
}
|
||||
SendMessage(m_Window, WM_COMMAND, WINAMP_FASTFWD, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -408,10 +318,7 @@ void CPlayerWinamp::Next()
|
||||
*/
|
||||
void CPlayerWinamp::Previous()
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
SendMessage(m_Window, WM_COMMAND, WINAMP_REWIND, 0);
|
||||
}
|
||||
SendMessage(m_Window, WM_COMMAND, WINAMP_REWIND, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -422,11 +329,8 @@ void CPlayerWinamp::Previous()
|
||||
*/
|
||||
void CPlayerWinamp::SetPosition(int position)
|
||||
{
|
||||
if (m_Window)
|
||||
{
|
||||
position *= 1000; // To milliseconds
|
||||
SendMessage(m_Window, WM_WA_IPC, position, IPC_JUMPTOTIME);
|
||||
}
|
||||
position *= 1000; // To milliseconds
|
||||
SendMessage(m_Window, WM_WA_IPC, position, IPC_JUMPTOTIME);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -437,20 +341,17 @@ void CPlayerWinamp::SetPosition(int position)
|
||||
*/
|
||||
void CPlayerWinamp::SetRating(int rating)
|
||||
{
|
||||
if (m_Window && (m_State != PLAYER_STOPPED))
|
||||
if (rating < 0)
|
||||
{
|
||||
if (rating < 0)
|
||||
{
|
||||
rating = 0;
|
||||
}
|
||||
else if (rating > 5)
|
||||
{
|
||||
rating = 5;
|
||||
}
|
||||
|
||||
SendMessage(m_Window, WM_WA_IPC, rating, IPC_SETRATING);
|
||||
m_Rating = rating;
|
||||
rating = 0;
|
||||
}
|
||||
else if (rating > 5)
|
||||
{
|
||||
rating = 5;
|
||||
}
|
||||
|
||||
SendMessage(m_Window, WM_WA_IPC, rating, IPC_SETRATING);
|
||||
m_Rating = rating;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -461,25 +362,20 @@ void CPlayerWinamp::SetRating(int rating)
|
||||
*/
|
||||
void CPlayerWinamp::SetVolume(int volume)
|
||||
{
|
||||
if (m_Window)
|
||||
++volume; // For proper scaling
|
||||
if (volume < 0)
|
||||
{
|
||||
++volume; // For proper scaling
|
||||
if (volume < 0)
|
||||
{
|
||||
volume = 0;
|
||||
}
|
||||
else if (volume > 100)
|
||||
{
|
||||
volume = 100;
|
||||
}
|
||||
|
||||
// Winamp accepts volume in 0 - 255 range
|
||||
float fVolume = (float)volume;
|
||||
fVolume *= 2.55f;
|
||||
volume = (UINT)fVolume;
|
||||
|
||||
SendMessage(m_Window, WM_WA_IPC, volume, IPC_SETVOLUME);
|
||||
volume = 0;
|
||||
}
|
||||
else if (volume > 100)
|
||||
{
|
||||
volume = 100;
|
||||
}
|
||||
|
||||
// Winamp accepts volume in 0 - 255 range
|
||||
volume *= 255;
|
||||
volume /= 100;
|
||||
SendMessage(m_Window, WM_WA_IPC, volume, IPC_SETVOLUME);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -490,19 +386,16 @@ void CPlayerWinamp::SetVolume(int volume)
|
||||
*/
|
||||
void CPlayerWinamp::ClosePlayer()
|
||||
{
|
||||
if (m_Window)
|
||||
if (m_WinampType == WA_WINAMP)
|
||||
{
|
||||
if (m_WinampType == WA_WINAMP)
|
||||
SendMessage(m_Window, WM_CLOSE, 0, 0);
|
||||
}
|
||||
else // if (m_WinampType == WA_MEDIAMONKEY)
|
||||
{
|
||||
HWND wnd = FindWindow(L"TFMainWindow", L"MediaMonkey");
|
||||
if (wnd)
|
||||
{
|
||||
SendMessage(m_Window, WM_CLOSE, 0, 0);
|
||||
}
|
||||
else // if (m_WinampType == WA_MEDIAMONKEY)
|
||||
{
|
||||
HWND wnd = FindWindow(L"TFMainWindow", L"MediaMonkey");
|
||||
if (wnd)
|
||||
{
|
||||
SendMessage(wnd, WM_CLOSE, 0, 0);
|
||||
}
|
||||
SendMessage(wnd, WM_CLOSE, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -513,15 +406,15 @@ void CPlayerWinamp::ClosePlayer()
|
||||
** Handles the OpenPlayer bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerWinamp::OpenPlayer()
|
||||
void CPlayerWinamp::OpenPlayer(std::wstring& path)
|
||||
{
|
||||
if (m_WinampType == WA_WINAMP)
|
||||
{
|
||||
ShellExecute(NULL, L"open", m_PlayerPath.empty() ? L"winamp.exe" : m_PlayerPath.c_str(), NULL, NULL, SW_SHOW);
|
||||
ShellExecute(NULL, L"open", path.empty() ? L"winamp.exe" : path.c_str(), NULL, NULL, SW_SHOW);
|
||||
}
|
||||
else // if (m_WinampType == WA_MEDIAMONKEY)
|
||||
{
|
||||
if (m_PlayerPath.empty())
|
||||
if (path.empty())
|
||||
{
|
||||
// Gotta figure out where Winamp is located at
|
||||
HKEY hKey;
|
||||
@ -545,7 +438,7 @@ void CPlayerWinamp::OpenPlayer()
|
||||
if (type == REG_SZ)
|
||||
{
|
||||
ShellExecute(NULL, L"open", data, NULL, NULL, SW_SHOW);
|
||||
m_PlayerPath = data;
|
||||
path = data;
|
||||
}
|
||||
}
|
||||
|
||||
@ -554,18 +447,7 @@ void CPlayerWinamp::OpenPlayer()
|
||||
}
|
||||
else
|
||||
{
|
||||
ShellExecute(NULL, L"open", m_PlayerPath.c_str(), NULL, NULL, SW_SHOW);
|
||||
ShellExecute(NULL, L"open", path.c_str(), NULL, NULL, SW_SHOW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** TogglePlayer
|
||||
**
|
||||
** Handles the TogglePlayer bang.
|
||||
**
|
||||
*/
|
||||
void CPlayerWinamp::TogglePlayer()
|
||||
{
|
||||
m_Window ? ClosePlayer() : OpenPlayer();
|
||||
}
|
||||
|
@ -33,9 +33,10 @@ public:
|
||||
CPlayerWinamp(WINAMPTYPE type);
|
||||
~CPlayerWinamp();
|
||||
|
||||
virtual void UpdateData();
|
||||
|
||||
virtual void Pause();
|
||||
virtual void Play();
|
||||
virtual void PlayPause();
|
||||
virtual void Stop();
|
||||
virtual void Next();
|
||||
virtual void Previous();
|
||||
@ -43,18 +44,11 @@ public:
|
||||
virtual void SetRating(int rating);
|
||||
virtual void SetVolume(int volume);
|
||||
virtual void ClosePlayer();
|
||||
virtual void OpenPlayer();
|
||||
virtual void TogglePlayer();
|
||||
|
||||
virtual void AddInstance(MEASURETYPE type);
|
||||
virtual void RemoveInstance();
|
||||
virtual void UpdateData();
|
||||
virtual void OpenPlayer(std::wstring& path);
|
||||
|
||||
private:
|
||||
bool Initialize();
|
||||
bool CheckActive();
|
||||
bool CheckWindow();
|
||||
|
||||
bool m_HasCoverMeasure;
|
||||
bool m_UseUnicodeAPI;
|
||||
WINAMPTYPE m_WinampType;
|
||||
HWND m_Window; // Winamp window
|
||||
|
@ -12,7 +12,7 @@
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,1,0,0
|
||||
FILEVERSION 1,1,1,0
|
||||
PRODUCTVERSION PRODUCTVER
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
@ -29,7 +29,7 @@ BEGIN
|
||||
BLOCK "040904E4"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "NowPlaying Plugin for Rainmeter"
|
||||
VALUE "FileVersion", "1.1.0.0"
|
||||
VALUE "FileVersion", "1.1.1.0"
|
||||
VALUE "InternalName", "NowPlaying"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2011 - Birunthan Mohanathas"
|
||||
VALUE "OriginalFilename", "NowPlaying.dll"
|
||||
|
@ -255,6 +255,7 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Cover.cpp" />
|
||||
<ClCompile Include="NowPlaying.cpp" />
|
||||
<ClCompile Include="Player.cpp" />
|
||||
<ClCompile Include="PlayerAIMP.cpp" />
|
||||
@ -342,6 +343,7 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Cover.h" />
|
||||
<ClInclude Include="NowPlaying.h" />
|
||||
<ClInclude Include="Player.h" />
|
||||
<ClInclude Include="PlayerAIMP.h" />
|
||||
|
@ -264,6 +264,9 @@
|
||||
<ClCompile Include="PlayerWLM.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Cover.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="SDKs\AIMP\aimp2_sdk.h">
|
||||
@ -320,6 +323,9 @@
|
||||
<ClInclude Include="PlayerWLM.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Cover.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="PluginNowPlaying.rc">
|
||||
|
@ -109,7 +109,7 @@ enum IPCMESSAGE
|
||||
// uMsg: WM_USER, wParam: 0 or 1, lParam: 128
|
||||
IPC_SET_REPEAT,
|
||||
|
||||
// uMsg: WM_USER, wParam: 0 or 1, lParam: 128 [Sent by/to player]
|
||||
// uMsg: WM_USER, wParam: 0 or 1, lParam: 129 [Sent by/to player]
|
||||
// The player should send this message when it quits.
|
||||
// CAD will also send this message on exit. Upon receival, the player should
|
||||
// disconnect the communication interface and get ready for a IPC_SET_CALLBACK_HWND message.
|
||||
|
Loading…
x
Reference in New Issue
Block a user