Author | Message | Time |
---|---|---|
Moonshine | I was bored so I decided to make a class in C++ that handles the various Winamp API functions that one would expect to find in a bot's winamp controls. I looked around on this forum and found only messy / non-classed code on it, so here it is: http://thedragonmaster.net/fatal-error/MoonShine/WinampManager.zip I included a test prog (main.cpp) so you can see how everything works. This was done in MSVS 2003 .NET, btw -- So if the spacing is all off, I apologize. You can use this code however you want, blah blah blah.. just give me credit please. Hope this helps save some peoples' time, later. | February 23, 2004, 2:32 AM |
DarkMinion | You spent way too much time on that...NullSoft provides a header file with all the constants & you only need to use SendMessage to manipulate it. | February 23, 2004, 4:57 AM |
DarkMinion | But it is neat, I'll give you that :) | February 23, 2004, 5:00 AM |
Yoni | You're using GetWindowText to get the song title - that's not a good idea, since people may do silly things, like make the title scroll in the taskbar and then you'd be getting eww. Here is my code for getting the song title: [code]// The following 2 lines are taken from Nullsoft's header file #define WM_WA_IPC WM_USER #define IPC_GETLISTPOS 125 #define IPC_GETPLAYLISTTITLE 212 // The following are mine #define GetWinampWindow() \ ((HWND)(FindWindow("Winamp v1.x", NULL))) // Winamp 2.05+ #define GetWinampListPos(Winamp) \ ((DWORD)(SendMessage(((HWND)(Winamp)), WM_WA_IPC, 0, IPC_GETLISTPOS))) // Winamp 2.04+, pointer is in Winamp address space #define GetWinampSongTitleRemote(Winamp, Index) \ ((char *)(SendMessage(((HWND)(Winamp)), WM_WA_IPC, ((WPARAM)(Index)), IPC_GETPLAYLISTTITLE))) char *GetWinampSongTitleLocal(HWND Winamp, DWORD Index) // Winamp 2.04+, pointer is in local address space { static char SongTitle[1024]; DWORD WinampProcessID; HANDLE WinampProcess; char *SongTitleRemote; char *Ret = NULL; // Return value // Get process ID GetWindowThreadProcessId(Winamp, &WinampProcessID); // Open process if(WinampProcess = OpenProcess(PROCESS_VM_READ, FALSE, WinampProcessID)) { // Get pointer if(SongTitleRemote = GetWinampSongTitleRemote(Winamp, Index)) // Try to read it if(ReadProcessMemory(WinampProcess, SongTitleRemote, SongTitle, sizeof(SongTitle), NULL)) // Success Ret = SongTitle; CloseHandle(WinampProcess); } return Ret; }[/code] Note it uses a static buffer, so use with care or modify as needed. Example for getting the current song's title: [code]HWND Winamp = GetWinampWindow(); Temp = GetWinampSongTitleLocal(Winamp, GetWinampListPos(Winamp)); if(Temp) strcpy(CurrentSongTitle, Temp);[/code] Edit: Added a few missing definitions. | February 23, 2004, 6:05 AM |
Moonshine | Heh, I also figured it would be a bad idea to use GetWindowText as well, but believe it or not I got the code from winamp's development site itself. However I agree your way is more "Idiot proof," so I'll add that to my code (I'll leave it up to people to change the zip's version if they feel the need, the getwindowtext way should work in theory, since it's preached by nullsoft themselves). | February 23, 2004, 4:53 PM |
Stealth | Here's a port to VB. Enjoy. :) [code]'// Original code by Yoni[vL], thanks to NSDN [Nullsoft] '// Ported to Visual Basic 6 by Stealth (stealth@stealthbot.net) '// Thanks to Skywing[vL], Kp and thuscelackpiss who helped me straighten out ReadProcessMemory '// modWinampTitle.bas Option Explicit '// Constants Private Const WM_USER& = &H400 Private Const WM_WA_IPC = WM_USER Private Const IPC_GETLISTPOS& = 125 Private Const IPC_GETPLAYLISTTITLE& = 212 Private Const PROCESS_VM_READ = (&H10) '// API declarations Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _ ByVal blnheritHandle As Long, _ ByVal dwAppProcessId As Long) As Long Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, _ ByVal lpBaseAddress As Long, _ ByVal lpBuffer As String, ByVal nSize As Long, _ ByRef lpNumberOfBytesWritten As Long) As Long Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, _ ByRef lpdwProcessId As Long) As Long Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long Private 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 '// The following are mine (Yoni's ;) Private Function GetWinampWindow() As Long GetWinampWindow = (FindWindow("Winamp v1.x", vbNullString)) End Function '// Winamp 2.05+ Private Function GetWinampListPos(ByVal hWndWinamp As Long) As Long GetWinampListPos = SendMessage(hWndWinamp, WM_WA_IPC, 0&, IPC_GETLISTPOS) End Function '// Winamp 2.04+, pointer is in Winamp address space Private Function GetWinampSongTitleRemote(ByVal hWndWinamp As Long, ByVal Index As Long) As Long GetWinampSongTitleRemote = SendMessage(hWndWinamp, WM_WA_IPC, Index, IPC_GETPLAYLISTTITLE) End Function Private Function GetWinampSongTitleLocal(ByVal hWndWinamp As Long, ByVal Index As Long) As String '// Winamp 2.04+, pointer is in local address space Dim SongTitle As String Dim WinampProcessID As Long Dim WinampProcessHandle As Long Dim ProcessHandle As Long Dim SongTitleRemote As Long Dim Ret As String SongTitle = String(1024, vbNullChar) '// Get process ID Call GetWindowThreadProcessId(hWndWinamp, WinampProcessID) '// Open process ProcessHandle = OpenProcess(PROCESS_VM_READ, False, WinampProcessID) If (ProcessHandle > 0) Then '// Get pointer SongTitleRemote = GetWinampSongTitleRemote(hWndWinamp, Index) If (SongTitleRemote > 0) Then '// Try to read it If (ReadProcessMemory(ProcessHandle, SongTitleRemote, SongTitle, ByVal Len(SongTitle), 0&) > 0) Then '// Success Ret = Left$(SongTitle, InStr(1, SongTitle, Chr(0)) - 1) End If End If Call CloseHandle(ProcessHandle) End If GetWinampSongTitleLocal = Ret End Function Public Function GetCurrentSongTitle(Optional ShowTrackNumber As Boolean = False) As String Dim hWnd As Long Dim sBuf As String hWnd = GetWinampWindow() sBuf = GetWinampSongTitleLocal(hWnd, GetWinampListPos(hWnd)) If ShowTrackNumber Then sBuf = (GetWinampListPos(hWnd) + 1) & ": " & sBuf End If GetCurrentSongTitle = sBuf End Function [/code] Usage: [code] sWinampSong = GetCurrentSongTitle() 'no track number sWinampSong = GetCurrentSongTitle(True) 'track number [/code] [Edit: When prepending the track number it needs to be +1.] | February 24, 2004, 12:00 AM |