Code:
/// <summary>
/// A .NET wrapper for common winamp controls.
/// </summary>
public class Winamp
{
#region DLL Imports
[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 SendMessageA(IntPtr hwnd, int wMsg, int wParam, uint lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetWindowText(IntPtr hwnd, string lpString, int cch);
[DllImport("user32")]
public static extern int GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
[DllImport("Kernel32.dll")]
public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, UInt32 nSize,
ref UInt32 lpNumberOfBytesRead);
[DllImport("Kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, bool bInheritHandle, UInt32 dwProcessId);
[DllImport("KERNEL32.DLL")]
public static extern int CloseHandle(int handle);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, uint lParam);
#endregion
#region Winamp-specific Constants
// We have to define the Winamp class name
private const string m_windowName = "Winamp v1.x";
// Useful for GetSongTitle() Method
private const string strTtlEnd = " - Winamp";
#endregion
private static int eqPosition;
public static IntPtr hWnd = FindWindow("Winamp v1.x", null);
public static Process WinAmpProcess = Process.GetProcessesByName("Winamp")[0];
#region Other useful Winamp Methods
/// <summary>
/// Gets the current song title.
/// </summary>
/// <returns></returns>
public static string GetCurrentSongTitle()
{
IntPtr hwnd = FindWindow(m_windowName, 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.Replace(strTtlEnd, string.Empty).Trim();
}
#endregion
#region WM_COMMAND Type Methods
/// <summary>
/// Stops winamp.
/// </summary>
public static void Stop()
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmCommand, (int) Command.StopSong,
(uint) Command.Nothing);
}
/// <summary>
/// Plays winamp.
/// </summary>
public static void Play()
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmCommand, (int) Command.PlaySong,
(uint) Command.Nothing);
}
/// <summary>
/// Pauses winamp.
/// </summary>
public static void Pause()
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmCommand, (int) Command.PauseUnpause,
(uint) Command.Nothing);
}
/// <summary>
/// Moves winamp to the previous track.
/// </summary>
public static void PrevTrack()
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmCommand, (int) Command.PreviousTrack,
(uint) Command.Nothing);
}
/// <summary>
/// Moves winamp to the next track.
/// </summary>
public static void NextTrack()
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmCommand, (int) Command.NextTrack,
(uint) Command.Nothing);
}
/// <summary>
/// Turns winamp's volume up.
/// </summary>
public static void VolumeUp()
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmCommand, (int) Command.VolumeUp,
(uint) Command.Nothing);
}
/// <summary>
/// Turns winamp's volume down.
/// </summary>
public static void VolumeDown()
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmCommand, (int) Command.VolumeDown,
(uint) Command.Nothing);
}
/// <summary>
/// Fast forwards 5 seconds.
/// </summary>
public static void Forward5Sec()
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmCommand, (int) Command.FastForwardFive,
(uint) Command.Nothing);
}
/// <summary>
/// Rewinds 5 seconds.
/// </summary>
public static void Rewind5Sec()
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmCommand, (int) Command.RewindFive,
(uint) Command.Nothing);
}
#endregion
#region WM_USER (WM_WA_IPC) Type Methods
/// <summary>
/// Gets the playback status.
/// </summary>
/// <value>The playback status.</value>
public static int PlaybackStatus
{
get
{
IntPtr hwnd = FindWindow(m_windowName, null);
return SendMessageA(hwnd, (int) Command.WmWaIpc, (int) Command.Nothing, isPlaying);
}
}
/// <summary>
/// Gets the winamp version.
/// </summary>
/// <value>The winamp version.</value>
public static int WinampVersion
{
get
{
IntPtr hwnd = FindWindow(m_windowName, null);
return SendMessageA(hwnd, (int) Command.WmWaIpc, (int) Command.Nothing,
getVersion);
}
}
/// <summary>
/// Gets or sets the playlist position.
/// </summary>
/// <value>The playlist position.</value>
public static int PlaylistPosition
{
get
{
IntPtr hwnd = FindWindow(m_windowName, null);
return SendMessageA(hwnd, (int) Command.WmWaIpc, (int) Command.Nothing,
getPlaylistPosition);
}
set
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmWaIpc, value, setPlaylistPos);
}
}
/// <summary>
/// Gets the track position. (In milliseconds)
/// </summary>
/// <value>The track position.</value>
public static int TrackPosition
{
get
{
IntPtr hwnd = FindWindow(m_windowName, null);
return SendMessageA(hwnd, (int) Command.WmWaIpc, (int) Command.Nothing,
getOutputTime);
}
}
/// <summary>
/// Gets the track count of the playlist
/// </summary>
/// <value>The track count.</value>
public static int TrackCount
{
get
{
IntPtr hwnd = FindWindow(m_windowName, null);
return SendMessageA(hwnd, (int) Command.WmWaIpc, (int) Command.Nothing,
getPlaylistLength);
}
}
/// <summary>
/// Deletes the current playlist.
/// </summary>
public static void DeleteCurrentPlaylist()
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmWaIpc, (int) Command.Nothing, clearPlaylist);
}
/// <summary>
/// Saves the playlist.
/// </summary>
public static void SavePlaylist()
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmWaIpc, (int) Command.Nothing, writePlaylist);
}
/// <summary>
/// Jumps to a position (in milliseconds) on the current track.
/// </summary>
/// <param name="position">The position.</param>
public static void JumpToTrackPosition(int position)
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmWaIpc, position, jumpToTime);
}
/// <summary>
/// Sets the volume. (0 - 255)
/// </summary>
/// <param name="position">The position.</param>
public static void SetVolume(int position)
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmWaIpc, position, setVolume);
}
/// <summary>
/// Sets the panning. (0 (left) - 255 (right))
/// </summary>
/// <param name="position">The position.</param>
public static void SetPanning(int position)
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmWaIpc, position, setPanning);
}
/// <summary>
/// Returns info about the current playing song. (KB rate, etc)
/// </summary>
/// <param name="mode">The mode.</param>
public static void GetTrackInfo(int mode)
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmWaIpc, mode, getCurrentTrackInfo);
}
public static void GetEqData(int position)
{
IntPtr hwnd = FindWindow(m_windowName, null);
eqPosition = SendMessageA(hwnd, (int) Command.WmWaIpc, position, getEquilizerData);
}
public static int SetEqData()
{
IntPtr hwnd = FindWindow(m_windowName, null);
SendMessageA(hwnd, (int) Command.WmWaIpc, eqPosition, setEquilizerData);
return eqPosition;
}
#endregion
private static string readStringFromWinampMemory(int winampMemoryAddress)
{
string str = "";
IntPtr handle = OpenProcess(0x0010, false, (uint) WinAmpProcess.Id);
byte[] buff = new byte[500];
uint ret = new UInt32();
IntPtr pos = new IntPtr(winampMemoryAddress);
int stringLength = 500; // Max length, if the buffer doesn't contain 0x00
if (ReadProcessMemory(handle, pos, buff, 500, ref ret))
{
for (int i = 0; i < stringLength; i++)
{
if (buff[i] != 0x00)
{
continue;
}
stringLength = i; // Store length
break;
}
Encoding encoding = Encoding.Default;
str = encoding.GetString(buff, 0, stringLength); // Encode from start to 0x00
}
return str;
}
public static string[] GetPlaylist()
{
int len = SendMessage(hWnd, (int) WA_IPC.WM_WA_IPC, 0, (uint) WA_IPC.IPC_GETLISTLENGTH);
string[] listNames = new string[len];
for (int i = 0; i < len; i++)
{
listNames[i] =
readStringFromWinampMemory(SendMessage(hWnd, (int) WA_IPC.WM_WA_IPC, i,
(uint) WA_IPC.IPC_GETPLAYLISTTITLE));
}
return listNames;
}
#region Nested type: Command
/// <summary>
/// Enum of constants used for Winamp commands
/// </summary>
private enum Command
{
/// <summary>
///
/// </summary>
Nothing = 0,
/// <summary>
/// To tell Winamp that we are sending it a WM_COMMAND, it needs this value.
/// </summary>
WmCommand = 0x111,
/// <summary>
/// To tell Winamp that we are sending it a WM_USER (WM_WA_IPC) it needs this value.
/// </summary>
WmWaIpc = 0x0400,
/// <summary>
/// Opens the Preferences menu
/// </summary>
TogglePreferencesMenu = 40012,
/// <summary>
/// Toggles the Always On Top option
/// </summary>
ToggleAlwaysOnTop = 40019,
/// <summary>
/// Opens the Load File(s) menu
/// </summary>
ToggleLoadFileMenu = 40029,
/// <summary>
/// Opens the EQ menu.
/// </summary>
ToggleEquilizerMenu = 40036,
/// <summary>
/// Opens the playlist menu
/// </summary>
TogglePlaylistMenu = 40040,
/// <summary>
/// Opens the About box
/// </summary>
OpenAboutBox = 40041,
/// <summary>
/// Plays the previous track
/// </summary>
PreviousTrack = 40044,
/// <summary>
/// Plays the selected track
/// </summary>
PlaySong = 40045,
/// <summary>
/// Pauses/unpauses the current track
/// </summary>
PauseUnpause = 40046,
/// <summary>
/// Stops playing the current track
/// </summary>
StopSong = 40047,
/// <summary>
/// Plays the next track
/// </summary>
NextTrack = 40048,
/// <summary>
/// Turns the volume up
/// </summary>
VolumeUp = 40058,
/// <summary>
/// Turns the volume down
/// </summary>
VolumeDown = 40059,
/// <summary>
/// Fast forwards 5 seconds
/// </summary>
FastForwardFive = 40060,
/// <summary>
/// Rewinds 5 seconds
/// </summary>
RewindFive = 40061,
/// <summary>
/// Fast-rewind 5 seconds
/// </summary>
RewindFastFive = 40144,
Button2Shift = 40145,
Button3Shift = 40146,
/// <summary>
/// Stop after current track
/// </summary>
StopAfterCurrent = 40147,
/// <summary>
/// Fast forward 5 seconds
/// </summary>
FastForwardFive2 = 40148,
/// <summary>
/// Go to the start of the playlist
/// </summary>
GoToStartOfPlaylist = 40154,
/// <summary>
/// Open URL dialog
/// </summary>
ToggleURLDialog = 40155,
Button3Ctrl = 40156,
/// <summary>
/// Fadeout and stop
/// </summary>
FadeoutAndStop = 40157,
/// <summary>
/// Go to the end of the playlist
/// </summary>
GoToEndOfPlaylist = 40158,
/// <summary>
/// Opens the load directory box
/// </summary>
ToggleLoadDirectoryMenu = 40187,
/// <summary>
/// Starts playing the audio CD in the first CD reader
/// </summary>
PlayFirstCDDrive = 40323,
/// <summary>
/// Starts playing the audio CD in the second CD reader
/// </summary>
PlaySecondCDDrive = 40323,
/// <summary>
/// Starts playing the audio CD in the third CD reader
/// </summary>
PlayThirdCDDrive = 40323,
/// <summary>
/// Starts playing the audio CD in the fourth CD reader
/// </summary>
PlayFourthCDDrive = 40323
}
#endregion
#region Nested type: WA_IPC
private enum WA_IPC
{
WM_WA_IPC = 1024,
IPC_GETLISTLENGTH = 124,
IPC_SETPLAYLISTPOS = 121,
IPC_GETLISTPOS = 125,
IPC_GETPLAYLISTFILE = 211,
IPC_GETPLAYLISTTITLE = 212
}
#endregion
#region WM_USER (WM_WA_IPC) Type Constants
// typically (but not always) use 0x1zyx for 1.zx versions
/// <summary>
/// Clears Winamp's playlist.
/// </summary>
private const int clearPlaylist = 101;
/// <summary>
/// Returns info about the current playing song (about Kb rate)
/// </summary>
private const int getCurrentTrackInfo = 126;
/// <summary>
/// Queries the status of the EQ. The value it returns depends on what 'position' is set to.
/// </summary>
private const int getEquilizerData = 127;
/// <summary>
/// Returns the position in milliseconds of the current track
/// </summary>
private const int getOutputTime = 105;
/// <summary>
/// Returns the length of the current playlist in tracks
/// </summary>
private const int getPlaylistLength = 124;
/// <summary>
/// Returns the playlist position.
/// </summary>
private const int getPlaylistPosition = 125;
/// <summary>
/// Returns Winamp version (0x20yx for winamp 2.yx)
/// </summary>
private const int getVersion = 0;
/// <summary>
/// Returns status of playback. Returns: 1 = playing, 3 = paused, 0 = not playing) current song (mode = 0),
/// or the song length, in seconds (mode = 1).
/// It returns: -1 if not playing or if there is an error.
/// </summary>
private const int isPlaying = 104;
/// <summary>
/// Sets the appoximate position in milliseconds of the current song
/// </summary>
private const int jumpToTime = 106;
/// <summary>
/// Sets the value of the last position retrieved by IPC_GETEQDATA (integer eqPosition)
/// </summary>
private const int setEquilizerData = 128;
/// <summary>
/// Sets the panning of Winamp (from 0 (left) to 255 (right))
/// </summary>
private const int setPanning = 123;
/// <summary>
/// Sets the playlist position
/// </summary>
private const int setPlaylistPos = 121;
/// <summary>
/// Sets the volume of Winamp (from 0-255)
/// </summary>
private const int setVolume = 122;
/// <summary>
/// Writes the current playlist to <winampdir>Winamp.m3u
/// </summary>
private const int writePlaylist = 120;
#endregion
}
Phew, that's alot of code.