Zune Now Playing support for Digsby and Winamp-compatible nowplaying software.

July 17, 2010 by Dave
 

The Zune media player delivers Now Playing information to Windows Live Messenger, but other software isn’t able to pick up these messages.  Quite a few users have asked for Zune Now Playing support in Digsby, so I put together this little app that lets this work.  The application itself is generic, converting Zune now playing messages into the more widely implemented Winamp now playing method.

Download the executable and source (C++).

Code Listing:

#include "stdafx.h"
#include "ZuneNowPlaying.h"
#include "LimitSingleInstance.h" // KB243953
#include <regex>
 
const std::tr1::wregex pattern(L".*?\\\\0Music\\\\0.*?\\\\0.*?\\\\0(.*?)\\\\0(.*?)\\\\0");
 
CLimitSingleInstance g_SingleInstanceObj(L"{24F3CD83-9FFE-4DE6-951D-63958942F834}");
 
HWND hWndWinamp;
HWND hWndWindowsLiveMessenger;
 
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_COPYDATA:
			{
				COPYDATASTRUCT *cds = (COPYDATASTRUCT*)lParam;
				wchar_t *str = (wchar_t*)cds-&gt;lpData;
 
				std::tr1::wcmatch result;
				if(std::tr1::regex_search(str, result, pattern))
				{
					std::wstring ret = result[2].str() + L" - " + result[1].str();
					SetWindowText(hWndWinamp, ret.c_str());
				}
				else
				{
					SetWindowText(hWndWinamp, L"");
				}
				break;
			}
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		case WM_USER:
			if (lParam == 104)
			{
				return 1; // Winamp=Playing (always)
			}
	}
	return DefWindowProc(hWnd, message, wParam, lParam);
}
 
void RegisterClasses(HINSTANCE hInstance)
{
	WNDCLASSEX wcex = WNDCLASSEX();
	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.lpfnWndProc	= WndProc;
	wcex.hInstance		= hInstance;
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszClassName	= L"MsnMsgrUIManager";
	RegisterClassEx(&amp;wcex);
 
	wcex.lpszClassName	= L"Winamp v1.x";
	RegisterClassEx(&amp;wcex);
}
 
bool CreateWindows(HINSTANCE hInstance)
{
	// Pretend to be Windows Live Messenger, so WM_COPYDATA messages are sent to us.
	hWndWindowsLiveMessenger = CreateWindow(L"MsnMsgrUIManager", L"", WS_DISABLED,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
	// Pretend to be Winamp (any version), so apps will pick us up for Now Playing.
	hWndWinamp = CreateWindow(L"Winamp v1.x", L"", WS_DISABLED,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
 
	return hWndWinamp &amp;&amp; hWndWindowsLiveMessenger;
}
 
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpCmdLine*/, int /*nCmdShow*/)
{
	MSG msg = MSG();
	if (!g_SingleInstanceObj.IsAnotherInstanceRunning())
	{
		RegisterClasses(hInstance);
 
		if (CreateWindows(hInstance))
		{
			while (GetMessage(&amp;msg, NULL, 0, 0))
			{
				TranslateMessage(&amp;msg);
				DispatchMessage(&amp;msg);
			}
		}
	}
	return (int)msg.wParam;
}</regex>

How it works:

It’s pretty simple, Zune software sends a WM_COPYDATA message to a window with class name MsnMsgrUIManager, the message contains a pointer to a unicode string, that looks something like this:

ZUNE\0Music\01\0{0} - {1}\0TRACK_TITLE\0TRACK_ARTIST\0TRACK_ALBUM\0zune:ZUNE_GUID\0
 
// TRACK_TITLE: Title
// TRACK_ARTIST: Artist
// TRACK_ALBUM: Album
// ZUNE_GUID:  A GUID that may refer to the Zune device, Zune account, or Zune software itself.
 
// Note:  {0} - {1} is the format of how the string should be displayed in WLM - I ignore this entirely.
// Note2:  This method is used by other software, so I don't gate on ZUNE for the sake of maximum flexibility.  
// Note3:  The "1" after Music specifies the playing state.  0=Stopped, 1=Playing.  I ignore this and instead just use whether or not the other fields exist.

Note:  The \0’s in the above string are literally \ and 0, not NULL characters.

Using a regular expression to match the fields, The artist and title are extracted from the string, and set as the window caption for a window with class name Winamp v1.x. Software (like Digsby, or other now playing apps) may use FindWindow to locate the fake Winamp player, and read the caption with GetWindowText.

You may need to install the Microsoft Visual C++ 2010 Redistributable Package (x86).

Comments

4 Comments on Zune Now Playing support for Digsby and Winamp-compatible nowplaying software.

  1. Navarr on Sat, 17th Jul 2010 3:43 pm
  2. Unfortunately it doesn’t seem to be a launch and go on Windows 7.

    “MSVCP100.dll is missing from your computer”

  3. Dave on Sat, 17th Jul 2010 4:14 pm
  4. I’ve updated with links to the VC++ Redist.

  5. Navarr on Sat, 17th Jul 2010 9:59 pm
  6. I already have that dave, i ran the 64-bit and it asked to repair, i repaired got the same error messages.

    You didn’t accidentally release the debug version, did you?

  7. Navarr on Sun, 18th Jul 2010 6:00 am
  8. Hey Dave, after some rabid googling, I managed to figure out that you HAVE to have the x86 runtime to use it, otherwise you’ll get the errors I got.