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:
Birunthan Mohanathas 2011-06-17 19:07:06 +00:00
parent 67cc4c7c6c
commit 6aa004eb22
26 changed files with 1251 additions and 1714 deletions

View 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;
}

View 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

View File

@ -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
}

View File

@ -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"

View File

@ -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;
}

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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();
}

View File

@ -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
};

View File

@ -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);
}

View File

@ -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;
};

View File

@ -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();
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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();
}

View File

@ -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

View File

@ -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"

View File

@ -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" />

View File

@ -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">

View File

@ -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.