Old 15th January 2011, 01:01   #1
Ravenhearty
Junior Member
 
Join Date: Jan 2011
Posts: 1
C# Get playing title

Greetings fellow developers, I'm making a small C# lib that queries Winamp for the currently playing song. So far I've written methods to get SampleRate, Bitrate, Channels, Position and Length of the playing song.

My problem is I cannot seem to make the IPC_GET_PLAYING_TITLE message to work.

My PInvoke of SendMessage:
code:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);



And this is how I send the data and decode the result:
code:
public static string GetTitle()
{
IntPtr result = SendMessage(GetWinampHandle(), WM_WA_IPC, IntPtr.Zero, IPC_GET_PLAYING_TITLE);
string title = Marshal.PtrToStringUni(result);
return title;
}



The resulting string is always empty ( "" ). The SDK doesn't say if this message can be sent from external apps, its located in a section that says it can only be used by plugins, but a few other messages in the same section just above the IPC_GET_PLAYING_TITLE explicitly say that they can be used outside of Winamp.

Any help, thought or comments are welcomed thank you.
Ravenhearty is offline   Reply With Quote
Old 15th January 2011, 08:29   #2
DrO
 
Join Date: Sep 2003
Posts: 27,873
it won't work as you're trying to access a string from a different process space which doesn't map to the same address in your C# app and so you just get a blank string (or an exception in some cases).

if you can do c/c++ then https://sourceforge.net/projects/winampminimagic/ may help (need to find the time to release a pre-compiled version of that code) which would allow what you're trying to do.

-daz
DrO is offline   Reply With Quote
Old 9th February 2011, 12:36   #3
akpsvnit
Junior Member
 
Join Date: Feb 2011
Posts: 1
First of all,
for Winamp title, you need to enable "Show winamp in taskbar" in preferences -> General preferences.
Now you need to get correct handle for winamp to get title.
For that import few dll functions.
-------------------------------------------------------
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow([MarshalAs(UnmanagedType.LPTStr)] string lpClassName, [MarshalAs(UnmanagedType.LPTStr)] string lpWindowName);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetWindowText(IntPtr hwnd, string lpString, int cch);
-------------------------------------------------------

& create a function
-------------------------------------------------------
public static string GetTitle()
{
IntPtr hwnd = FindWindow("Winamp v1.x",null);
if (hwnd.Equals(IntPtr.Zero))
return "N/A";
string lpText = new string((char) 0, 100);
int intLength = GetWindowText(hwnd, lpText, lpText.Length);
if ((intLength <= 0) || (intLength > lpText.Length))
return "N/A";
string strTitle = lpText.Substring(0, intLength);
return (strTitle);
}
-------------------------------------------------------

This will return the whole title visible in taskbar.
Then you can crop the winamp name at the end in order to get current track.
akpsvnit is offline   Reply With Quote
Old 9th February 2011, 12:43   #4
DrO
 
Join Date: Sep 2003
Posts: 27,873
you can do it that way but what i've linked to is the more complete way of doing it as people can and will change their taskbar text (either directly or by changing the ATF formatting in Winamp) which means some of your assumptions will not be correct.

-daz
DrO is offline   Reply With Quote
Old 11th February 2011, 06:56   #5
Shatonapples
Junior Member
 
Join Date: Feb 2011
Posts: 5
I am baffled as to why there isn't an easy solution for this. I've been looking around for hours. It seems that the issue is that the memory address that WinAmp gives to us is relative to its "process space," and unless we get read access to that "process space," then we can't get access to the data that it tried to give us.

I'm not sure where to go from here, but if you find anything out, post it here!
Shatonapples is offline   Reply With Quote
Old 11th February 2011, 08:44   #6
DrO
 
Join Date: Sep 2003
Posts: 27,873
that's how it is with any program, process spaces are mapped at different locations so trying to 'share' those memory addresses between different processes will never be gauranteed to map to the same place. just compile the code from the sourceforge site i've posted above as a c/c++ dll and then use that (until i can sort out a release for it).

-daz
DrO is offline   Reply With Quote
Old 12th February 2011, 06:43   #7
Shatonapples
Junior Member
 
Join Date: Feb 2011
Posts: 5
I have a C# project, and when I tried to incorporate the dll in my project, it said it wasn't accessible via COM and something else. When I tried to build it as part of my project (VS 2010 lets you use multiple languages in a single solution), it just says "A reference to "WinampMiniMagic" could not be added."

Any other ideas of how to utilize the WMM in my application? It definitely would serve my needs.
Shatonapples is offline   Reply With Quote
Old 12th February 2011, 08:57   #8
DrO
 
Join Date: Sep 2003
Posts: 27,873
all i've ever done is use it as an external dll and load it as per the C# example in the example folder.

-daz
DrO is offline   Reply With Quote
Old 12th February 2011, 19:50   #9
Shatonapples
Junior Member
 
Join Date: Feb 2011
Posts: 5
A reference to 'Path\WinampMiniMagic.dll' could not be added. Please make sure that file is accessible, and that is a valid assembly or COM component.

Path holds the correct path to the folder, I just didn't feel like typing it. Is there a way to build a C++ project like this in a COM accessible manner?
Shatonapples is offline   Reply With Quote
Old 13th February 2011, 08:06   #10
Shatonapples
Junior Member
 
Join Date: Feb 2011
Posts: 5
It looks like if I try to do it like you have done it in your Example.cpp, it sort of works. This code is a bit too cryptic for me to understand how to get the filename in C#.

A couple lines I can't figure out how to translate:
HMODULE minilib = LoadLibraryW(L"WinampMiniMagic.dll");
wprintf(L"Title: %s\n", GetMetaDataFromFile(curPath, L"Title", buffer, 2048));
// Granted, I don't need the wprintf, but I'm still confused about the L and some other things.
(GETCURRENTPLAYLISTFILE)GetProcAddress(minilib, "GetCurrentPlaylistFile");
(GETCURRENTPLAYLISTTITLE)GetProcAddress(minilib, "GetCurrentPlaylistTitle");

// Tbh, I don't really need much other than the line:
(GETCURRENTPLAYLISTFILE)GetProcAddress(minilib, "GetCurrentPlaylistFile");
// And whatever prereqs it takes to get there.
// I can do the rest of the file info gathering through C#, I just want the filename.
// All the other aspects of manipulating WinAmp that I was looking for, I have found through SendMessage.
Shatonapples is offline   Reply With Quote
Old 13th February 2011, 18:53   #11
Shatonapples
Junior Member
 
Join Date: Feb 2011
Posts: 5
I think I just need to figure out:

HMODULE minilib = LoadLibraryW(L"WinampMiniMagic.dll");
(GETCURRENTPLAYLISTFILE)GetProcAddress(minilib, "GetCurrentPlaylistFile");
typedef wchar_t *(*GETCURRENTPLAYLISTFILE)(void);

But that's where I get stuck. I'm not really sure what to do with them.
Shatonapples is offline   Reply With Quote
Reply
Go Back   Winamp & Shoutcast Forums > Developer Center > Winamp Development

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump