diff --git a/Plugins/PluginNowPlaying/Cover.cpp b/Plugins/PluginNowPlaying/Cover.cpp new file mode 100644 index 00000000..46cea44c --- /dev/null +++ b/Plugins/PluginNowPlaying/Cover.cpp @@ -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(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(fr.file())) + { + if (file->tag()) + { + found = ExtractMP4(file, target); + } + } + else if (TagLib::FLAC::File* file = dynamic_cast(fr.file())) + { + found = ExtractFLAC(file, target); + + if (!found && file->ID3v2Tag()) + { + found = ExtractID3(file->ID3v2Tag(), target); + } + } + else if (TagLib::ASF::File* file = dynamic_cast(fr.file())) + { + found = ExtractASF(file, target); + } + else if (TagLib::APE::File* file = dynamic_cast(fr.file())) + { + if (file->APETag()) + { + found = ExtractAPE(file->APETag(), target); + } + } + else if (TagLib::MPC::File* file = dynamic_cast(fr.file())) + { + if (file->APETag()) + { + found = ExtractAPE(file->APETag(), target); + } + } + else if (TagLib::WavPack::File* file = dynamic_cast(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(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& 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; +} diff --git a/Plugins/PluginNowPlaying/Cover.h b/Plugins/PluginNowPlaying/Cover.h new file mode 100644 index 00000000..7f5da634 --- /dev/null +++ b/Plugins/PluginNowPlaying/Cover.h @@ -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 \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/NowPlaying.cpp b/Plugins/PluginNowPlaying/NowPlaying.cpp index e94fb22e..ccc79a4b 100644 --- a/Plugins/PluginNowPlaying/NowPlaying.cpp +++ b/Plugins/PluginNowPlaying/NowPlaying.cpp @@ -37,31 +37,11 @@ CPlayer* g_Winamp = NULL; CPlayer* g_WLM = NULL; CPlayer* g_WMP = NULL; -static MeasureMap g_Values; +static std::map 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::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::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::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::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::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 +} diff --git a/Plugins/PluginNowPlaying/NowPlaying.h b/Plugins/PluginNowPlaying/NowPlaying.h index 60fa9f8f..e0eff26f 100644 --- a/Plugins/PluginNowPlaying/NowPlaying.h +++ b/Plugins/PluginNowPlaying/NowPlaying.h @@ -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 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" diff --git a/Plugins/PluginNowPlaying/Player.cpp b/Plugins/PluginNowPlaying/Player.cpp index 266ca12f..22c088c9 100644 --- a/Plugins/PluginNowPlaying/Player.cpp +++ b/Plugins/PluginNowPlaying/Player.cpp @@ -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(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(fr.file())) - { - if (file->tag()) - { - found = GetArtMP4(file); - } - } - else if (TagLib::FLAC::File* file = dynamic_cast(fr.file())) - { - found = GetArtFLAC(file); - - if (!found && file->ID3v2Tag()) - { - found = GetArtID3(file->ID3v2Tag()); - } - } - else if (TagLib::ASF::File* file = dynamic_cast(fr.file())) - { - found = GetArtASF(file); - } - else if (TagLib::APE::File* file = dynamic_cast(fr.file())) - { - if (file->APETag()) - { - found = GetArtAPE(file->APETag()); - } - } - else if (TagLib::MPC::File* file = dynamic_cast(fr.file())) - { - if (file->APETag()) - { - found = GetArtAPE(file->APETag()); - } - } - else if (TagLib::WavPack::File* file = dynamic_cast(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(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& 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; -} diff --git a/Plugins/PluginNowPlaying/Player.h b/Plugins/PluginNowPlaying/Player.h index 63d22394..bf3e95ff 100644 --- a/Plugins/PluginNowPlaying/Player.h +++ b/Plugins/PluginNowPlaying/Player.h @@ -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 \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/PlayerAIMP.cpp b/Plugins/PluginNowPlaying/PlayerAIMP.cpp index 25312af0..3cd148f9 100644 --- a/Plugins/PluginNowPlaying/PlayerAIMP.cpp +++ b/Plugins/PluginNowPlaying/PlayerAIMP.cpp @@ -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(); -} diff --git a/Plugins/PluginNowPlaying/PlayerAIMP.h b/Plugins/PluginNowPlaying/PlayerAIMP.h index 369a0438..84ad6c0c 100644 --- a/Plugins/PluginNowPlaying/PlayerAIMP.h +++ b/Plugins/PluginNowPlaying/PlayerAIMP.h @@ -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 diff --git a/Plugins/PluginNowPlaying/PlayerCAD.cpp b/Plugins/PluginNowPlaying/PlayerCAD.cpp index ac9da884..290716b9 100644 --- a/Plugins/PluginNowPlaying/PlayerCAD.cpp +++ b/Plugins/PluginNowPlaying/PlayerCAD.cpp @@ -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(); -} diff --git a/Plugins/PluginNowPlaying/PlayerCAD.h b/Plugins/PluginNowPlaying/PlayerCAD.h index a29052e1..202ba198 100644 --- a/Plugins/PluginNowPlaying/PlayerCAD.h +++ b/Plugins/PluginNowPlaying/PlayerCAD.h @@ -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 diff --git a/Plugins/PluginNowPlaying/PlayerFoobar.cpp b/Plugins/PluginNowPlaying/PlayerFoobar.cpp index 05d776a1..91969a87 100644 --- a/Plugins/PluginNowPlaying/PlayerFoobar.cpp +++ b/Plugins/PluginNowPlaying/PlayerFoobar.cpp @@ -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(); -} diff --git a/Plugins/PluginNowPlaying/PlayerFoobar.h b/Plugins/PluginNowPlaying/PlayerFoobar.h index 3a4c8315..5abb717d 100644 --- a/Plugins/PluginNowPlaying/PlayerFoobar.h +++ b/Plugins/PluginNowPlaying/PlayerFoobar.h @@ -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 }; diff --git a/Plugins/PluginNowPlaying/PlayerITunes.cpp b/Plugins/PluginNowPlaying/PlayerITunes.cpp index 1cf65a0e..24a31043 100644 --- a/Plugins/PluginNowPlaying/PlayerITunes.cpp +++ b/Plugins/PluginNowPlaying/PlayerITunes.cpp @@ -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); } diff --git a/Plugins/PluginNowPlaying/PlayerITunes.h b/Plugins/PluginNowPlaying/PlayerITunes.h index 517dbd44..62259342 100644 --- a/Plugins/PluginNowPlaying/PlayerITunes.h +++ b/Plugins/PluginNowPlaying/PlayerITunes.h @@ -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; }; diff --git a/Plugins/PluginNowPlaying/PlayerSpotify.cpp b/Plugins/PluginNowPlaying/PlayerSpotify.cpp index a02545ed..1acabc44 100644 --- a/Plugins/PluginNowPlaying/PlayerSpotify.cpp +++ b/Plugins/PluginNowPlaying/PlayerSpotify.cpp @@ -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(); -} diff --git a/Plugins/PluginNowPlaying/PlayerSpotify.h b/Plugins/PluginNowPlaying/PlayerSpotify.h index ec0ded29..ee03125d 100644 --- a/Plugins/PluginNowPlaying/PlayerSpotify.h +++ b/Plugins/PluginNowPlaying/PlayerSpotify.h @@ -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 diff --git a/Plugins/PluginNowPlaying/PlayerWLM.cpp b/Plugins/PluginNowPlaying/PlayerWLM.cpp index 53c4b5df..edcc272c 100644 --- a/Plugins/PluginNowPlaying/PlayerWLM.cpp +++ b/Plugins/PluginNowPlaying/PlayerWLM.cpp @@ -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); } diff --git a/Plugins/PluginNowPlaying/PlayerWLM.h b/Plugins/PluginNowPlaying/PlayerWLM.h index dc86ae4e..5f797513 100644 --- a/Plugins/PluginNowPlaying/PlayerWLM.h +++ b/Plugins/PluginNowPlaying/PlayerWLM.h @@ -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 diff --git a/Plugins/PluginNowPlaying/PlayerWMP.cpp b/Plugins/PluginNowPlaying/PlayerWMP.cpp index e3a6336a..9e22643d 100644 --- a/Plugins/PluginNowPlaying/PlayerWMP.cpp +++ b/Plugins/PluginNowPlaying/PlayerWMP.cpp @@ -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 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 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); } diff --git a/Plugins/PluginNowPlaying/PlayerWMP.h b/Plugins/PluginNowPlaying/PlayerWMP.h index 38d0c220..e1c1d565 100644 --- a/Plugins/PluginNowPlaying/PlayerWMP.h +++ b/Plugins/PluginNowPlaying/PlayerWMP.h @@ -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 m_IPlayer; CComPtr m_IControls; CComPtr m_ISettings; diff --git a/Plugins/PluginNowPlaying/PlayerWinamp.cpp b/Plugins/PluginNowPlaying/PlayerWinamp.cpp index 9246b278..2d85ff07 100644 --- a/Plugins/PluginNowPlaying/PlayerWinamp.cpp +++ b/Plugins/PluginNowPlaying/PlayerWinamp.cpp @@ -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(); -} diff --git a/Plugins/PluginNowPlaying/PlayerWinamp.h b/Plugins/PluginNowPlaying/PlayerWinamp.h index 3f00ee43..003661d7 100644 --- a/Plugins/PluginNowPlaying/PlayerWinamp.h +++ b/Plugins/PluginNowPlaying/PlayerWinamp.h @@ -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 diff --git a/Plugins/PluginNowPlaying/PluginNowPlaying.rc b/Plugins/PluginNowPlaying/PluginNowPlaying.rc index afb75a8b..faa00aec 100644 --- a/Plugins/PluginNowPlaying/PluginNowPlaying.rc +++ b/Plugins/PluginNowPlaying/PluginNowPlaying.rc @@ -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" diff --git a/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj b/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj index 7793ee5b..06bfe18f 100644 --- a/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj +++ b/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj @@ -255,6 +255,7 @@ + @@ -342,6 +343,7 @@ + diff --git a/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters b/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters index 529e97ed..aa1ee991 100644 --- a/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters +++ b/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters @@ -264,6 +264,9 @@ Source Files + + Source Files + @@ -320,6 +323,9 @@ Header Files + + Header Files + diff --git a/Plugins/PluginNowPlaying/SDKs/CAD/cad_sdk.h b/Plugins/PluginNowPlaying/SDKs/CAD/cad_sdk.h index e1d39097..eb9097f3 100644 --- a/Plugins/PluginNowPlaying/SDKs/CAD/cad_sdk.h +++ b/Plugins/PluginNowPlaying/SDKs/CAD/cad_sdk.h @@ -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.