PDA

View Full Version : Solution: Get FileName from external app/dll


HeikoSS
20th April 2002, 20:21
It IS possible!
Some guy wrote the pointers aren´t valid, because every process has its own 32bit memory address block.
Thats True, but there are some nice functions which let you access the memory space of another process...

I wrote an example how to get the FileName....in Delphi, but the functions should be the same in C or whatever:


function GetWinampFilename: String;
var Text, tempStr: String;
hwndWinamp, TempHandle : THandle;
dat2: array[0..500] of Char;
TrackPos: Integer;
temp, MPointer: Cardinal;
begin
hwndWinamp:= FindWindow('Winamp v1.x',nil);
TrackPos:= SendMessage(hwndWinamp,WM_USER,0 , 125);
MPointer:= SendMessage(hwndWinamp,WM_USER,TrackPos , 211);
GetWindowThreadProcessId(hwndWinamp,TempHandle);
hwndWinamp:= OpenProcess(PROCESS_ALL_ACCESS,False,TempHandle);
ReadProcessMemory(hwndWinamp, Pointer(MPointer), @dat2,500,temp);
CloseHandle(hwndWinamp);
tempStr:= dat2; // ;-)
Result:= tempStr;
end;


First we get the Winamp handle, as usual.
Then we get the actual played track, as usual.
Then the Pointer to the Filename (MPointer).

This Pointer is not valid in our dll´s process memory.
So we need to Read in Winamp´s process memory.
ReadProcessMemory(); does this.
OpenProcess gives us a new handle, on which we have Read/Write Access.
Otherwise we get an EAccessViolation.
the filename is stored in dat2.

With C there may be some string copy actions necessary.
But this should be no problem...


I hope i helped some of you "I don´t like a winamp plugin" guys ;)
Heiko S.

PS: I wrote a simple example dll for mIRC which puts out the usual stuff on command. (trackname, time, kbps etc..)
Any questions about that are welcome.
And Sorry for neglecting any existing name conventions :)

peter
20th April 2002, 20:29
yeah, nice. which windows OS did you test that in ?

HeikoSS
20th April 2002, 20:31
Windows 2000

So i think for Win95/98/ME/ NT it should work surely.

Windows XP...idk (but i may look...tomorrow..)

Heiko S.

HeikoSS
20th April 2002, 20:41
-deleted

peter
20th April 2002, 21:17
i was only afraid about win2k and similar, but if it works then it's OK.

Gourou
22nd April 2002, 01:38
the probable conversion to vb..... but it doesnt work :cry:

Dim hwndWinamp As Long
Dim TempHandle As Long
Dim dat2 As String * 256
Dim TrackPos As Long
Dim temp As Long
Dim MPointer As Long
Public Const WM_USER = &H400
Public Const PROCESS_VM_READ = &H10
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Public Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByVal lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Public Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" (ByVal lpString1 As String, ByVal lpString2 As String) As Long
Dim pTemp As Long
Dim nTemp As Long

Public Function ShowTitle() As String

hwndWinamp = FindWindow("Winamp v1.x", vbNullString)
TrackPos = SendMessage(hwndWinamp, &H400, 0, 125)
MPointer = SendMessage(hwndWinamp, &H400, TrackPos, 211)
temp = GetWindowThreadProcessId(hwndWinamp, TempHandle)
hwndWinamp = OpenProcess(PROCESS_VM_READ, False, TempHandle)
pTemp = lstrcpy(dat2, dat2)
nTemp = ReadProcessMemory(hwndWinamp, MPointer, pTemp, 256, temp)
temp = CloseHandle(hwndWinamp)
ShowTitle = dat2

End Function


it shows that the read process memory works, that it copies 256, but all that's in my string is null characters, it doesnt change anything, nothing at all. changing anything around gives me some lovely access violations, the worst being where visual studio disappears without a trace..now if only my frozen programs could do that, anyway, that's where I'm at, any help would be most appreciated, thnx in advance.

HeikoSS
22nd April 2002, 06:59
Hi again,
I don´t know much about VB...
But here are some things i found:

First I changed my code to equal your VB Code.
Old:
var dat2: array[0..500] of Char;

New:
var dat2: PChar; //Pointer to char


Now I initialized dat2 in two different way´s.

dat2:= PChar('Just a 256 byte long String to hold the Filename..........');

PChar() returns a Pointer to a String;
If it´s intialized this way, ReadProcessMemory fails. The output is the original "Just a long enough......"


Now I used AllocMem(X: Cardinal), which returns a pointer to X Bytes of Memory.

dat:=AllocMem(256);

If its done this way, ReadProcessMemory succeeds.

Maybe there´s a function like AllocMem in VB?

Heiko S.

Gourou
23rd April 2002, 00:34
Bows down to Heiko

Dim hwndWinamp As Long
Dim TempHandle As Long
Dim dat2 As String
Dim TrackPos As Long
Dim temp As Long
Dim MPointer As Long
Public Const WM_USER = &H400
Public Const PROCESS_VM_READ = &H10
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Public Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByVal lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Public Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" (ByVal lpString1 As String, ByVal lpString2 As String) As Long
Dim pTemp As Long
Dim nTemp As Long

Public Function ShowTitle() As String

hwndWinamp = FindWindow("Winamp v1.x", vbNullString)
TrackPos = SendMessage(hwndWinamp, &H400, 0, 125)
MPointer = SendMessage(hwndWinamp, &H400, TrackPos, 211)
temp = GetWindowThreadProcessId(hwndWinamp, TempHandle)
hwndWinamp = OpenProcess(PROCESS_VM_READ, False, TempHandle)
For xn = 1 To 256
dat2 = dat2 & " "
Next xn
nTemp = ReadProcessMemory(hwndWinamp, MPointer, dat2, 256, temp)
temp = CloseHandle(hwndWinamp)
ShowTitle = dat2

I was on the right track, I just didnt know it, you see, I was filling it with null characters by making it fixes length, so it would get to the first null and think that was the end of the string, go figure, so I filled it with spaces, the code works, works like a charm, thank you again Heiko. *bows down to you*
If anyone remembers the vb command to fill a string with a character, then use that instead of my loop.

bananskib
23rd April 2002, 08:39
The answer is no - documented in frontend.h :

#define IPC_GETPLAYLISTFILE 211

/* (requires Winamp 2.04+, only usable from plug-ins (not external apps))
** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTFILE);
**
** IPC_GETPLAYLISTFILE gets the filename of the playlist entry [index].
** returns a pointer to it. returns NULL on error.
*/

notice "not external apps" - sorry

bananskib

HeikoSS
23rd April 2002, 09:56
LOL?

Did you actually read the post´s above?


It IS possible!


^^ This is no question ;)

These Functions ARE the solution, they work...
Ok, I write one for C...
*sighs* ;)

Perhaps someone updates the frontend.h?
Or the FAQ Page?
I´m sure the other "only usable from within winamp´plugin´s" API SendMessages are also usable from external app´s since we are able to freely read/write in winamp´s process memory from an external app too.

Anyone who got how OpenProcess, ReadProcessMemory and WriteProcessMemory work, should be able to port it to the
other IPC_´s .


Heiko S.

HeikoSS
23rd April 2002, 12:45
I´m not very used to C too, but this Code works.


char *GetWinampFilename()
{
HWND hwndWinamp = FindWindowA("Winamp v1.x",NULL);
LPDWORD TempHandle, temp;
TempHandle = new(DWORD);
temp = new(DWORD);
int index = SendMessage(hwndWinamp, WM_USER, 0, 125); //returns the playlist position
LPCVOID lpFileName=(LPCVOID)SendMessage(hwndWinamp, WM_USER, index, 211);
GetWindowThreadProcessId(hwndWinamp, TempHandle);
HANDLE hWinamp = OpenProcess(PROCESS_ALL_ACCESS,false,*TempHandle);
char *dat = (char*) malloc(256);
ReadProcessMemory(hWinamp, lpFileName, dat,256,temp);
CloseHandle(hWinamp);
free(TempHandle);
free(temp);
return dat;
}


Maybe someone wants to rewrite it, to make it look nicer ;)


Heiko S.

salva
27th April 2002, 09:22
Hello Gourou, will you post some project sample with your code ?

Tks

Gourou
27th April 2002, 14:11
sure, hell, why not, gimme a min to get a sample cobbled together..

Gourou
27th April 2002, 14:19
here, it works fine for me, if it doesnt work correctly for you, then message me

Gourou
28th April 2002, 12:10
bloody hell, cant edit my own upload, that sux, so here's an update, I fixed a bug, it wasnt noticeable, but it was an error, and I dont like errors, even if they get passed by ok. BTW, this is just source code, I didnt bother to compile it

deep_burn
2nd July 2002, 23:58
I know I shouldn't be replying to a post that's 3 months old, but I can't help it. This is an excellent example of being able to pull the current song title/filename from WinAmp, which is exactly what I wanted to do. Even better, it's native VB.
*praise to the NSDN*

HeikoSS
3rd July 2002, 14:27
/me wonders how many vb coders are out there =)

np

Gourou
4th July 2002, 02:32
more than you think...

NegativeFactor
10th July 2002, 07:55
This thread has made my life 100% better, since now i can get the song names!! No more sleepless nights, yeah!!

I'm a VB coder 2!

;)

quentin
12th January 2003, 20:00
vbcoder :D
i'm going to reactivate this post since i have a problem

i surely get the right title returned but when i want to return some more text afterwards it doesn't work. i guess that's because of the Space(256)

does anyone have a clue how to just return a normal string instead of this special string? or how to terminate the string so that i can add normal text after it?

heres my code:
[quote]Public Function ShowFile() As String
On Error Resume Next
hWndWinamp = FindWindow("Winamp v1.x", vbNullString)
TrackPos = SendMessage(hWndWinamp, WM_USER, 0, 125)
MPointer = SendMessage(hWndWinamp, WM_USER, TrackPos, 211) '212 is Title
temp = GetWindowThreadProcessId(hWndWinamp, TempHandle)
hwndWinampP = OpenProcess(PROCESS_VM_READ, False, TempHandle)
Data = Space(256)
nTemp = ReadProcessMemory(hwndWinampP, MPointer, Data, 256, temp)
pTemp = CloseHandle(hwndWinampP)
ShowFile = Trim(Data)
End Function[/code]

thanks!

HeikoSS
12th January 2003, 22:17
Sorry, other question:

Is there any WinampAPI in Winamp3 ?

I wanted to port this to 3...but didn´t find anything...

Heiko S.

Lion King
14th January 2003, 07:33
http://forums.winamp.com/showthread.php?threadid=106344

daydee
18th February 2003, 16:38
Originally posted by quentin
vbcoder :D
i'm going to reactivate this post since i have a problem

i surely get the right title returned but when i want to return some more text afterwards it doesn't work. i guess that's because of the Space(256)

does anyone have a clue how to just return a normal string instead of this special string? or how to terminate the string so that i can add normal text after it?

heres my code:
[quote]Public Function ShowFile() As String
On Error Resume Next
hWndWinamp = FindWindow("Winamp v1.x", vbNullString)
TrackPos = SendMessage(hWndWinamp, WM_USER, 0, 125)
MPointer = SendMessage(hWndWinamp, WM_USER, TrackPos, 211) '212 is Title
temp = GetWindowThreadProcessId(hWndWinamp, TempHandle)
hwndWinampP = OpenProcess(PROCESS_VM_READ, False, TempHandle)
Data = Space(256)
nTemp = ReadProcessMemory(hwndWinampP, MPointer, Data, 256, temp)
pTemp = CloseHandle(hwndWinampP)
ShowFile = Trim(Data)
End Function[/code]

thanks! Add the TrimNulls function below and give it a try. Hope this helps...

Public Function ShowFile() As String
On Error Resume Next
hWndWinamp = FindWindow("Winamp v1.x", vbNullString)
TrackPos = SendMessage(hWndWinamp, WM_USER, 0, 125)
MPointer = SendMessage(hWndWinamp, WM_USER, TrackPos, 211) '212 is Title
temp = GetWindowThreadProcessId(hWndWinamp, TempHandle)
hwndWinampP = OpenProcess(PROCESS_VM_READ, False, TempHandle)
Data = Space(256)
nTemp = ReadProcessMemory(hwndWinampP, MPointer, Data, 256, temp)
pTemp = CloseHandle(hwndWinampP)
ShowFile = TrimNulls(Data)
End Function

Private Function TrimNulls(strString As String) As String
Dim l As Long
l = InStr(1, strString, Chr(0))
TrimNulls = Left$(strString, l - 1)
strString = TrimNulls
End Function

quentin
18th February 2003, 19:22
Add the TrimNulls function below and give it a try. Hope this helps...

Private Function TrimNulls(strString As String) As String
Dim l As Long
l = InStr(1, strString, Chr(0))
TrimNulls = Left$(strString, l - 1)
strString = TrimNulls
End Function


:) :) i love you :) :)

yeah that worked fine :)

thanks for your help! :)

daydee
20th February 2003, 03:07
:D your welcome!
You could also use it if your populating a listbox...
This was originally a function which I grabbed from Gourou's project but I made it into a sub with a variable for a Listbox.
I'm using this in my latest app which works great. My thanks to Gourou for coming up with this neat stuff.
I was able to reduce my initial code considerably because of it. :up:
Happy coding! :)

Public Sub ShowFileList(ByVal LstBox As ListBox)
Dim tempStr As String
On Error Resume Next
LstBox.Clear
hwndWinamp = FindWindow("Winamp v1.x", vbNullString)
pLength = SendMessage(hwndWinamp, WM_USER, 0, 124)

For xn = 1 To pLength
MPointer = SendMessage(hwndWinamp, WM_USER, xn - 1, 211) '212 is Title
temp = GetWindowThreadProcessId(hwndWinamp, TempHandle)
hwndWinampP = OpenProcess(PROCESS_VM_READ, False, TempHandle)
Data = Space(256)
nTemp = ReadProcessMemory(hwndWinampP, MPointer, Data, 256, temp)
pTemp = CloseHandle(hwndWinampP)
tempStr = TrimNulls(Data)
'do your string manipulation here,
'like remove file extension etc...
LstBox.AddItem tempStr
Next xn

End Sub

deep_burn
21st February 2003, 17:23
You people are beautiful. The DAY I come back to working with the API for VB, you resurrect this post.

Currently, I'm working on a special project that I'll talk about when it's done. It's a stand-alone VB app that communicates with WinAMP (of course)... but it takes a whole new twist. I hope it's well received.

daydee
22nd February 2003, 06:14
Originally posted by deep_burn
You people are beautiful. The DAY I come back to working with the API for VB, you resurrect this post.

Currently, I'm working on a special project that I'll talk about when it's done. It's a stand-alone VB app that communicates with WinAMP (of course)... but it takes a whole new twist. I hope it's well received. Hi there deep_burn, wonder if that new twist your mentioning is something simmilar to what I've done? I don't want to turn this into a chit chat but I got so p..... o.. at trying to find a decent visual front end for winamp 2 that I decided to learn VB 2 years ago and make it myself. I think I've maxed out just about every functions you can get out of winamp on this one. Well maybe not but pretty close... :)
My web counter is surely proof that that there was a need for such a thing.
Funny but of all people I would have thought Nullsoft would have come out with something like this long ago. I mean a front end that you could easily use with your full album folders. Sure there are a few plugins out there that'll let you see the album covers while listening to your tunes but I think most people want a little more interaction than this no? I did... Anyway I'm sure with the huge hard drives coming out on the market nowadays a whole bunch of people are going to start realizing that it's wwwwway more efficient to keep your music collection on your pc than all over the place.

I've got over 550 CD'S neatly stored on two separate HD and would never ever go back to listening to my cd's the old way.
I don't really feel comfortable about mentioning this here but anyway if you want to try it out here's the link. It's free btw... unless you use it commercially of course ;)
http://pages.globetrotter.net/bakerywizard/partyTime_jukebox.htm

If you wanta share ideas you can write me at bakerywizard@globetrotter.net

Cheers and thanks again to all the forum gurus for not abandoning us... Winamp 2 lovers that is! :D
:)

deep_burn
23rd February 2003, 16:12
That's an excellent idea. Although, it's nowhere close to what I'm doing.

I've decided not to release my app. I would, but I've gotten a second wind on things I can do with it, and unfortunatly, it's becomming more multi-purpose than just WinAMP.

When I reach version 2.0, that's when I'll release it as a plugin.

Yeah, WinAMP 2 still rocks! I'll never replace it. It'll be one of those things that you've had on your computer for like 11 years... like Temple of Abshai.

syph424
16th July 2003, 16:52
Looks like it's been a few months since anyone's dug this one up from the dead... it's about time to do it again, eh?

I'm working on a class to interact with WinAmp 2.x in VB.NET. I haven't run into any problems so far, so I figured it was about time to tackle the current file issue.

Using Gourou's code, I can get the title in VB6 without any issues. However, I'm having a hell of a time rolling it up to .NET. The current issue (I'm sure there's more to follow) is with the OpenProcess API call. Up until that call, I've got VB6 and VB.NET on the same page. However, I can't get the .NET code to return the same value as the VB6 code.

I've got the API registered as "Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Integer, ByVal dwProcessId As Integer) As Integer". I attempted using GetProcessById in the System.Diagnostics.Process class too, no dice.

Any ideas? Anyone tried this yet? ;)

Thanks for any assistance...

syph

orlandocurioso
27th November 2003, 21:43
Big Thank You for HeikoSS & Gourou!
A nice VB wrapper for using your methods & a hack to use restricted
stringbuffers,can be found at
http://forums.winamp.com/showthread.php?s=&threadid=157836

ScoBra7
18th March 2004, 12:31
...frontend.h
In SDK v 5.02 (I think it is in wa_icp.h)

Here is my C code, using MFC, I used a dialog box just to test:

void CWinampTestDlg::OnOK()
{
CString Text, tempStr;
HWND hwndWinamp;
HANDLE hWinamp;
unsigned long TempHandle;
char * dat2 = new char[500];
memset(dat2,0,500);
int TrackPos;
int * MPointer;
unsigned long temp;

hwndWinamp = ::FindWindow("Winamp v1.x",0);
if(hwndWinamp == NULL)
{
AfxMessageBox("Please be so kind as to start Winamp.");
return;
}
TrackPos = ::SendMessage(hwndWinamp,WM_USER,0 , 125);
MPointer = (int*)::SendMessage(hwndWinamp,WM_USER,TrackPos , 211);
GetWindowThreadProcessId(hwndWinamp,&TempHandle);
hWinamp = ::OpenProcess(PROCESS_ALL_ACCESS,FALSE,TempHandle);
ReadProcessMemory(hWinamp, MPointer, dat2,500,&temp);
CloseHandle(hWinamp);
tempStr = dat2; // ;-)
CString str;
str.Format("Now playing\n%d\t%s",TrackPos,tempStr);
AfxMessageBox(str);
delete dat2;
}

cutter2004
31st March 2004, 07:24
Urgent!!! How to get filename in fullpath.
Thank.

ScoBra7
1st April 2004, 05:41
In wa_ipc.h you'll find#define IPC_GETPLAYLISTFILE 211
/* (requires Winamp 2.04+, only usable from plug-ins (not external apps))
** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTFILE);
** IPC_GETPLAYLISTFILE gets the filename of the playlist entry [index].
** returns a pointer to it. returns NULL on error.
*/


#define IPC_GETPLAYLISTTITLE 212
/* (requires Winamp 2.04+, only usable from plug-ins (not external apps))
** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTTITLE);
**
** IPC_GETPLAYLISTTITLE gets the title of the playlist entry [index].
** returns a pointer to it. returns NULL on error.
*/

But "(not external apps)" is not true my app can get it.

Thus for the fullpath useMPointer = (int*)::SendMessage(hwndWinamp,WM_USER,TrackPos , IPC_GETPLAYLISTFILE);

in the above code.

Davman99
4th April 2004, 22:24
Ok, now im gonna have to reveal my n00bness here, and while i doubt i will get an answer, im gonna ask anyway...

Im looking for a DLL for use with mIRC (must follow this format)

int __stdcall procname(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause)

that will allow me to control winamp's volume, along with play and stop.

I take it this is possible (everything is), but not being a C coder, im not sure how.

If anyone has any ideas, or can point me in the direction of code samples that i may understand (are nicely commented), it would be great....

ScoBra7
5th April 2004, 05:26
If I understand you correctly, the DLL "plugs-in" to mIRC?

If so, you use the same code listed above in your DLL.

If you want a DLL that already does this, I think you have to write one. Which doesn't answer your question :(

Search this forum, you'll find clues on how to do it.

fdeshayes
16th January 2007, 19:47
hi!

i'm trying to get the filename of the current playing song in winamp from an external application written in C# (.NET 2.0)

I'm doing the same things that are your C or Vb code but it doesn't work. The openProcess method alway return me zero, so i can't read in winamp memory.

Anybody have a sample code in C# ? i can post my code here if somebody can help...

Tardymo
17th January 2007, 11:27
Can you post a DllImport you are using for openProcess?

fdeshayes
17th January 2007, 18:13
i've seen your WACC lib and download it. It work fine :-)
but why use a bind method with path of winamp ?
can we get this path from registry ?
is bind necessary for all winamp interaction or only for some (which used command line to control winamp?) ?

by the way, when i get songpath from your WACC lib, i use it with taglib dll (http://developer.novell.com/wiki/index.php/TagLib_Sharp) to read all ID3 stuff (and other tag format for vorbis / ape...)

If i put the songpath in hard code (like String songPath ="c:\\mp3\\toto.mp3" all is ok, i can read the id3 tags. But if i use your WACC lib to get the current winamp song played (the same toto.mp3), the taglib constructor return null. I've compared the two string (the hard coded and the one return from your lib), all is the same (after a substring to kill \0 at end of string return by WACC). So what's wrong with String return by your WACC?

here is my getCurrentSongPath method
public String getCurrentSongPath() {
String songPath = "";
findAndSetHandle();

if (handle != IntPtr.Zero) {
clsWACC cWinamp = new clsWACC();
bool bind = cWinamp.Bind("c:\\Program Files\\Winamp\\Winamp.exe");
if (bind) {
int currPos = cWinamp.Playlist.Position;
songPath = cWinamp.Playlist.GetItemPath(currPos);
songPath = songPath.Substring(0, songPath.IndexOf('\0'));
songPath = songPath.Trim();
}
}
return songPath;
}


here is how i get tag with taglib

String musicPath = sensorWinamp.multimediaPlayer.getCurrentSongPath();
String musicPath2 = "E:\\MP3\\Albums\\Thunderstone\\2004 - The Burning\\06. Sea of Sorrow.mp3";
Console.WriteLine(musicPath.CompareTo(musicPath2)); // return zero
currentSong = TagLib.File.Create(musicPath); // return null !?!?
currentSong = TagLib.File.Create(musicPath2); // all is ok

Tardymo
18th January 2007, 20:37
but why use a bind method with path of winamp ?
can we get this path from registry ?
Sure we can. In fact, I will add this functionality in the next release.


is bind necessary for all winamp interaction or only for some (which used command line to control winamp?) ?

It is needed for all interactions. Bind method gets a handle to winamp's main window to which most of the commands are sent. This handle is a global instance member of a class.


If i put the songpath in hard code (like String songPath ="c:\\mp3\\toto.mp3" all is ok, i can read the id3 tags. But if i use your WACC lib to get the current winamp song played (the same toto.mp3), the taglib constructor return null. I've compared the two string (the hard coded and the one return from your lib), all is the same (after a substring to kill \0 at end of string return by WACC). So what's wrong with String return by your WACC?

A bug actually :rolleyes:
A string returned by GetItemPath (and all other strings that are read from the winamp's memory space) is not terminated properly. I have fixed the problem so you have to wait for the next release planned in this weekend. You will not have to use the following line anymore and taglib will work as expected.

songPath = songPath.Substring(0, songPath.IndexOf('\0'));


If you don't want to wait, you can fix the library yourself. Just replace this line:
Dim RetStr As String = Marshal.PtrToStringAnsi(returnVal, MaxStrLen)
with this one:
Dim RetStr As String = Marshal.PtrToStringAnsi(returnVal)
It's in clsWacc.vb in ReadRemoteString function.

By the way. Next version will be able to read information from tags, so stay tuned.

fdeshayes
19th January 2007, 18:00
thanks for this explication.

For your bind, maybe you can use system method FindWindow with the classname of winamp : "Winamp v1.x". This classname doesn't change, contrary to the path of winamp.exe

here is an exemple in C#. I've not VB.

// find a process windows by classname or windows name
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

// call like this
IntPtr winampHandle = FindWindow("Winamp v1.x", null);

i've not VB so i must wait until next released. Can you said approximatly when will be the next released or maybe can you send me only the fresh .dll (even in beta, i only use cWinamp.Playlist.Position and cWinamp.Playlist.GetItemPath()) ?

thanks for your work!

Tardymo
19th January 2007, 22:09
FindWindow is used internally in Bind method. Path is optional parameter. But I guess C# doesn't have optional parameters so you can simply specify an empty string for a path parameter if Winamp is already running.
First thing Bind method does is it tries to find a winamp window (using FindWindow). If it does not find one, it uses a specified path to lauch Winamp.
New version of WACC will be released in next couple of days.

Sipps
13th December 2008, 16:59
Originally posted by HeikoSS

function GetWinampFilename: String;
var Text, tempStr: String;
hwndWinamp, TempHandle : THandle;
dat2: array[0..500] of Char;
TrackPos: Integer;
temp, MPointer: Cardinal;
begin
hwndWinamp:= FindWindow('Winamp v1.x',nil);
TrackPos:= SendMessage(hwndWinamp,WM_USER,0 , 125);
MPointer:= SendMessage(hwndWinamp,WM_USER,TrackPos , 211);
GetWindowThreadProcessId(hwndWinamp,TempHandle);
hwndWinamp:= OpenProcess(PROCESS_ALL_ACCESS,False,TempHandle);
ReadProcessMemory(hwndWinamp, Pointer(MPointer), @dat2,500,temp);
CloseHandle(hwndWinamp);
tempStr:= dat2; // ;-)
Result:= tempStr;
end;


I thought I was pretty able to convert this to C#, but I can't get it to work. Any C# people that know for a fact they can rewrite this to C#?

fdeshayes
14th December 2008, 08:27
Hi!
i've coded some C# interaction with Winamp and i've used the WACC .NET library.

you can find this lib here :
WACC Library (http://sourceforge.net/project/showfiles.php?group_id=180765)

With that, it's very simple to have path of current playing song in Winamp :

String currentSongPath = cWinamp.Playlist.GetItemPath(cWinamp.Playlist.Position)

hope it can help.

bye!

babazula2
30th December 2009, 18:59
thanks fdeshayes