NowPlayingPlugin: Improved MusicBee & MediaMonkey support and fixed that the ClosePlayer bang with iTunes does not always work.

This commit is contained in:
Birunthan Mohanathas 2011-05-28 07:50:33 +00:00
parent 9a19d8808e
commit 3268c774d2
10 changed files with 256 additions and 63 deletions

View File

@ -140,6 +140,14 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
}
data->player = g_iTunes;
}
else if (_wcsicmp(L"MediaMonkey", str) == 0)
{
if (!g_Winamp)
{
g_Winamp = new CPlayerWinamp(WA_MEDIAMONKEY);
}
data->player = g_Winamp;
}
else if (_wcsicmp(L"MusicBee", str) == 0)
{
if (!g_CAD)
@ -156,11 +164,11 @@ UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id)
}
data->player = g_Spotify;
}
else if (_wcsicmp(L"WinAmp", str) == 0 || _wcsicmp(L"MediaMonkey", str) == 0)
else if (_wcsicmp(L"WinAmp", str) == 0)
{
if (!g_Winamp)
{
g_Winamp = new CPlayerWinamp();
g_Winamp = new CPlayerWinamp(WA_WINAMP);
}
data->player = g_Winamp;
}

View File

@ -18,6 +18,7 @@
#include "StdAfx.h"
#include "PlayerCAD.h"
#include "CAD/cad_sdk.h"
// This player emulates the CD Art Display IPC API. For now, only MusicBee
// is supported, but this can easily be extended.
@ -121,6 +122,7 @@ void CPlayerCAD::Initialize()
m_PlayerWindow = wnd;
SendMessage(m_PlayerWindow, WM_USER, (WPARAM)m_Window, IPC_SET_CALLBACK_HWND);
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_CURRENT_TRACK);
m_State = (PLAYERSTATE)SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_PLAYER_STATE);
}
else
{
@ -141,7 +143,6 @@ void CPlayerCAD::Uninitialize()
UnregisterClass(L"NowPlayingCADClass", GetModuleHandle(NULL));
}
/*
** WndProc
**
@ -180,6 +181,7 @@ LRESULT CALLBACK CPlayerCAD::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
case IPC_SHUTDOWN_NOTIFICATION:
p->m_PlayerWindow = NULL;
p->ClearInfo();
break;
}
return 0;
@ -376,7 +378,6 @@ void CPlayerCAD::SetVolume(int volume)
{
if (m_PlayerWindow)
{
volume += m_Volume;
if (volume < 0)
{
volume = 0;
@ -410,6 +411,8 @@ void CPlayerCAD::ChangeVolume(int volume)
void CPlayerCAD::ClosePlayer()
{
SendMessage(m_PlayerWindow, WM_USER, 0, IPC_CLOSE_PLAYER);
m_PlayerWindow = NULL;
ClearInfo();
}
/*

View File

@ -44,49 +44,6 @@ public:
virtual void UpdateData();
private:
enum IPCMESSAGE
{
IPC_PLAY = 100,
IPC_PLAYPAUSE,
IPC_FORCEPAUSE,
IPC_STOP,
IPC_NEXT,
IPC_PREVIOUS,
IPC_SET_VOLUME = 108,
IPC_GET_VOLUME,
IPC_GET_CURRENT_TRACK,
IPC_GET_DURATION = 113,
IPC_SET_POSITION,
IPC_IS_PLAYING,
IPC_IS_PAUSED,
IPC_GET_LIST_LENGTH,
IPC_SET_LIST_POS,
IPC_GET_LIST_ITEM,
IPC_SET_CALLBACK_HWND, // Recieved by player. wParam is handle to CAD window.
IPC_GET_LIST_POS,
IPC_GET_POSITION,
IPC_TRACK_CHANGED_NOTIFICATION, // Sent by player.
IPC_SHOW_PLAYER_WINDOW,
IPC_GET_PLAYER_STATE,
IPC_PLAYER_STATE_CHANGED_NOTIFICATION, // Sent by player.
IPC_AUTOENQUEUE_OPTIONS, // Ignored.
IPC_SET_REPEAT,
IPC_SHUTDOWN_NOTIFICATION, // Sent by/to player on exit. Player should NULL the CAD window handle.
IPC_GET_REPEAT,
IPC_CLOSE_PLAYER, // Player should exit upon receival.
IPC_GET_SHUFFLE = 140,
IPC_SET_SHUFFLE,
IPC_RATING_CHANGED_NOTIFICATION = 639, // Sent by/to player.
IPC_REGISTER_PLAYER = 700, // Sent by player to CAD on startup.
IPC_CURRENT_TRACK_INFO,
IPC_SEND_LYRICS,
IPC_SEND_NEW_LYRICS,
IPC_NEW_COVER_NOTIFICATION = 800, // Sent by player (ignored).
IPC_GET_CURRENT_LYRICS,
IPC_ADDFILE_PLAY_PLAYLIST,
IPC_ADDFILE_QUEUE_PLAYLIST
};
void Initialize();
void Uninitialize();
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

View File

@ -29,15 +29,8 @@ extern CPlayer* g_iTunes;
*/
CPlayerITunes::CEventHandler::CEventHandler(CPlayerITunes* player) :
m_iTunes(player),
m_TypeInfo(),
m_RefCount()
{
ITypeLib* pITypeLib = NULL;
HRESULT hr = LoadRegTypeLib(LIBID_iTunesLib, 1, 5, 0x00, &pITypeLib);
// Get type information for the interface of the object.
hr = pITypeLib->GetTypeInfoOfGuid(DIID__IiTunesEvents, &m_TypeInfo);
pITypeLib->Release();
}
/*
@ -64,13 +57,13 @@ HRESULT STDMETHODCALLTYPE CPlayerITunes::CEventHandler::QueryInterface(REFIID ii
ULONG STDMETHODCALLTYPE CPlayerITunes::CEventHandler::AddRef()
{
InterlockedIncrement(&m_RefCount);
++m_RefCount;
return m_RefCount;
}
ULONG STDMETHODCALLTYPE CPlayerITunes::CEventHandler::Release()
{
InterlockedDecrement(&m_RefCount);
--m_RefCount;
if (m_RefCount == 0)
{
delete this;
@ -568,9 +561,9 @@ void CPlayerITunes::ClosePlayer()
{
if (m_Initialized)
{
m_Initialized = false;
m_UserQuitPrompt = true;
m_iTunes->Quit();
ClearInfo();
Uninitialize();
}
}

View File

@ -74,7 +74,6 @@ private:
private:
ULONG m_RefCount;
ITypeInfo* m_TypeInfo; // Pointer to type information
CPlayerITunes* m_iTunes;
};

View File

@ -21,6 +21,8 @@
#include "Winamp/wa_ipc.h"
#include "Winamp/wa_cmd.h"
// This player retrieves data through the Winamp IPC API.
extern CPlayer* g_Winamp;
/*
@ -29,7 +31,8 @@ extern CPlayer* g_Winamp;
** Constructor.
**
*/
CPlayerWinamp::CPlayerWinamp() : CPlayer(),
CPlayerWinamp::CPlayerWinamp(WINAMPTYPE type) : CPlayer(),
m_WinampType(type),
m_UseUnicodeAPI(false),
m_HasCoverMeasure(false),
m_Window()
@ -475,7 +478,18 @@ void CPlayerWinamp::ClosePlayer()
{
if (m_Window)
{
SendMessage(m_Window, WM_CLOSE, 0, 0);
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(wnd, WM_CLOSE, 0, 0);
}
}
}
}
@ -487,7 +501,48 @@ void CPlayerWinamp::ClosePlayer()
*/
void CPlayerWinamp::OpenPlayer()
{
ShellExecute(NULL, L"open", m_PlayerPath.empty() ? L"winamp.exe" : m_PlayerPath.c_str(), NULL, NULL, SW_SHOW);
if (m_WinampType == WA_WINAMP)
{
ShellExecute(NULL, L"open", m_PlayerPath.empty() ? L"winamp.exe" : m_PlayerPath.c_str(), NULL, NULL, SW_SHOW);
}
else // if (m_WinampType == WA_MEDIAMONKEY)
{
if (m_PlayerPath.empty())
{
// Gotta figure out where Winamp is located at
HKEY hKey;
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Clients\\Media\\MediaMonkey\\shell\\open\\command",
0,
KEY_QUERY_VALUE,
&hKey);
DWORD size = 512;
WCHAR* data = new WCHAR[size];
DWORD type = 0;
if (RegQueryValueEx(hKey,
NULL,
NULL,
(LPDWORD)&type,
(LPBYTE)data,
(LPDWORD)&size) == ERROR_SUCCESS)
{
if (type == REG_SZ)
{
ShellExecute(NULL, L"open", data, NULL, NULL, SW_SHOW);
m_PlayerPath = data;
}
}
delete [] data;
RegCloseKey(hKey);
}
else
{
ShellExecute(NULL, L"open", m_PlayerPath.c_str(), NULL, NULL, SW_SHOW);
}
}
}
/*

View File

@ -21,10 +21,16 @@
#include "Player.h"
enum WINAMPTYPE
{
WA_WINAMP,
WA_MEDIAMONKEY
};
class CPlayerWinamp : public CPlayer
{
public:
CPlayerWinamp();
CPlayerWinamp(WINAMPTYPE type);
~CPlayerWinamp();
virtual void Play();
@ -49,6 +55,7 @@ private:
bool m_HasCoverMeasure;
bool m_UseUnicodeAPI;
WINAMPTYPE m_WinampType;
HWND m_Window; // Winamp window
HANDLE m_WinampHandle; // Handle to Winamp process
LPCVOID m_WinampAddress;

View File

@ -353,6 +353,7 @@
<ClInclude Include="PlayerWinamp.h" />
<ClInclude Include="PlayerWMP.h" />
<ClInclude Include="SDKs\AIMP\aimp2_sdk.h" />
<ClInclude Include="SDKs\CAD\cad_sdk.h" />
<ClInclude Include="SDKs\iTunes\iTunesCOMInterface.h" />
<ClInclude Include="SDKs\Winamp\wa_cmd.h" />
<ClInclude Include="SDKs\Winamp\wa_dlg.h" />

View File

@ -22,6 +22,9 @@
<Filter Include="Players">
<UniqueIdentifier>{8be2f033-c29f-41d2-affd-c7721f0df88b}</UniqueIdentifier>
</Filter>
<Filter Include="SDKs\CD Art Display">
<UniqueIdentifier>{9e4422be-972a-442d-95f1-f238ef237a7b}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="SDKs\iTunes\iTunesCOMInterface_i.c">
@ -312,6 +315,9 @@
<ClInclude Include="PlayerCAD.h">
<Filter>Players</Filter>
</ClInclude>
<ClInclude Include="SDKs\CAD\cad_sdk.h">
<Filter>SDKs\CD Art Display</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="PluginNowPlaying.rc" />

View File

@ -0,0 +1,164 @@
/*
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 __CADSDK_H__
#define __CADSDK_H__
enum IPCMESSAGE
{
/*
Most of these messages are sent to the player. Messages that the player
should send back to CAD are noted by '[Sent by player]'
Based on information available in cad-sdk-2.1.pdf and in foo_cdartdisplay source.
*/
// uMsg: WM_USER, wParam: 0, lParam: 100
IPC_PLAY = 100,
// uMsg: WM_USER, wParam: 0, lParam: 101
IPC_PLAYPAUSE,
// uMsg: WM_USER, wParam: 0, lParam: 102
IPC_FORCEPAUSE,
// uMsg: WM_USER, wParam: 0, lParam: 103
IPC_STOP,
// uMsg: WM_USER, wParam: 0, lParam: 104
IPC_NEXT,
// uMsg: WM_USER, wParam: 0, lParam: 105
IPC_PREVIOUS,
// uMsg: WM_USER, wParam: volume (0 - 100), lParam: 108
IPC_SET_VOLUME = 108,
// uMsg: WM_USER, wParam: 0, lParam: 109, result: 0 to 100
IPC_GET_VOLUME,
// uMsg: WM_USER, wParam: 0, lParam: 110
// When the player recieves this message, it should send
// the IPC_CURRENT_TRACK message back to CAD
IPC_GET_CURRENT_TRACK,
// uMsg: WM_USER, wParam: 0, lParam: 113
IPC_GET_DURATION = 113,
// uMsg: WM_USER, wParam: position (seconds), lParam: 114
IPC_SET_POSITION,
// uMsg: WM_USER, wParam: 0, lParam: 115, result: 1 if playing
IPC_IS_PLAYING,
// uMsg: WM_USER, wParam: 0, lParam: 116, result: 1 if paused
IPC_IS_PAUSED,
// uMsg: WM_USER, wParam: 0, lParam: 117
IPC_GET_LIST_LENGTH,
// uMsg: WM_USER, wParam: position, lParam: 118
IPC_SET_LIST_POS,
// uMsg: WM_USER, wParam: 0, lParam: 119
IPC_GET_LIST_ITEM,
// uMsg: WM_USER, wParam: hwnd, lParam: 120
// CAD sends this mesage to the player on startup. The player
// should then send all future WM_COPYDATA messages to this window.
IPC_SET_CALLBACK_HWND,
// uMsg: WM_USER, wParam: 0, lParam: 121
IPC_GET_LIST_POS,
// uMsg: WM_USER, wParam: 0, lParam: 122, result: position (in seconds)
IPC_GET_POSITION,
// uMsg: WM_USER, wParam: 0, lParam: 123 [Sent by player]
// The player should send this message when the track changes.
IPC_TRACK_CHANGED_NOTIFICATION,
// uMsg: WM_USER, wParam: 0, lParam: 124
IPC_SHOW_PLAYER_WINDOW,
// uMsg: WM_USER, wParam: 0, lParam: 125, result: 0 (stopped), 1 (playing), or 2 (paused)
IPC_GET_PLAYER_STATE,
// uMsg: WM_USER, wParam: 0, lParam: 126 [Sent by player]
// The player should send this notification when the play state changes.
IPC_PLAYER_STATE_CHANGED_NOTIFICATION,
// uMsg: WM_USER, wParam: 0, lParam: 127 [Not implemented in CAD yet]
IPC_AUTOENQUEUE_OPTIONS,
// 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]
// 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.
IPC_SHUTDOWN_NOTIFICATION,
// uMsg: WM_USER, wParam: 0, lParam: 130, result: 1 if shuffle is active
IPC_GET_REPEAT,
// uMsg: WM_USER, wParam: 0, lParam: 131
// The player should quit completely upon receival.
IPC_CLOSE_PLAYER,
// uMsg: WM_USER, wParam: 0, lParam: 140, result: 1 if shuffle is active
IPC_GET_SHUFFLE = 140,
// uMsg: WM_USER, wParam: 0 or 1, lParam: 141
IPC_SET_SHUFFLE,
// uMsg: WM_USER, wParam: rating (0 - 10), lParam: 141 [Sent by/to player]
// CAD sends this message to the player with the new rating (0 - 10). The
// player sends this message when the rating changes.
IPC_RATING_CHANGED_NOTIFICATION = 639,
// uMsg: WM_COPYDATA, wParam: 700, lParam: COPYDATASTRUCT [Sent by player]
// The player sends this message on start up. Refer to the SDK manual for detailed info.
IPC_REGISTER_PLAYER = 700, // Sent by player to CAD on startup.
// uMsg: WM_COPYDATA, wParam: 701, lParam: COPYDATASTRUCT [Sent by player]
// The player sends this when it receives the IPC_GET_CURRENT_TRACK message.
IPC_CURRENT_TRACK_INFO,
// uMsg: WM_COPYDATA, wParam: 702, lParam: COPYDATASTRUCT [Sent by player]
// The player sends this when it receives the IPC_GET_CURRENT_LYRICS message.
IPC_CURRENT_LYRICS,
// uMsg: WM_COPYDATA, wParam: 703, lParam: COPYDATASTRUCT [Sent by player]
// The player sends this when, for example, new lyrics have been retrieved.
IPC_NEW_LYRICS,
// uMsg: WM_COPYDATA, wParam: 800, lParam: COPYDATASTRUCT [Sent by player]
// The player sends this when a new cover is available for playing track.
IPC_NEW_COVER = 800,
// uMsg: WM_USER, wParam: 0, lParam: 801
IPC_GET_CURRENT_LYRICS,
IPC_ADDFILE_PLAY_PLAYLIST,
IPC_ADDFILE_QUEUE_PLAYLIST
};
#endif