Click here to Skip to main content
15,881,719 members
Articles / Programming Languages / Visual Basic
Article

Retrieve the Winamp song title with .NET

Rate me:
Please Sign up or sign in to vote.
4.40/5 (17 votes)
5 Jan 20042 min read 118.7K   495   39   12
An article on Winamp and Windows API

Introduction

Ever needed the current Winamp song title? This article describes how to get it using some simple Windows API functions. For example, you could use this code in a nick name changer for an IM program. This code is only tested with Winamp 5, but should also be compatible with all other Winamp versions.

Using the code

First, you need to find the handle of the Winamp window using FindWindow, which is defined in the API reference as follows:

HWND FindWindow(
      LPCTSTR lpClassName,
      LPCTSTR lpWindowName
);

In C# .NET this function is referenced as follows:

C#
[System.Runtime.InteropServices.DllImport("user32.dll", 
    CharSet=System.Runtime.InteropServices.CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName, 
    string lpWindowName);

And in VB .NET:

VB
Private Declare Auto Function FindWindow Lib "user32" ( _
    ByVal lpClassName As String, _
    ByVal lpWindowName As String) As IntPtr

It is known that the Winamp class name is "Winamp v1.x". It is not required to specify a window name, so we pass vbNullString (VB) or null (C#) in the function call. If a Winamp windows is found, the return value is its handle, else, the function returns NULL (.NET: IntPtr.Null). Once you have found the window handle, you can retrieve the window's text using GetWindowText:

int GetWindowText(
      HWND hWnd,
      LPTSTR lpString,
      int nMaxCount
);
C#
[System.Runtime.InteropServices.DllImport("user32.dll", 
    CharSet=System.Runtime.InteropServices.CharSet.Auto)]
public static extern int GetWindowText(IntPtr hwnd, 
    string lpString, int cch);
VB
Private Declare Auto Function GetWindowText Lib "user32" ( _
    ByVal hwnd As IntPtr, _
    ByVal lpString As String, _
    ByVal cch As Integer) As Integer

The return value of this function is the length of the window text. If the function succeeds, we have the window text containing the song title. The text consists of the track number (in the current playlist), followed by a dot and a space, then the track title and finally the text " - Winamp". When Winamp is paused or stopped, it may end with " - Winamp [Paused]" or " - Winamp [Stopped]". In this case we want the function to return only the state ("Paused" or "Stopped"). In the other case, we remove " - Winamp" from the end of the string and the track number at the beginning. Finally we remove all spaces from the beginning and the end of the resulting string and find the song title!

Complete C# .NET source code

C#
[System.Runtime.InteropServices.DllImport("user32.dll", 
  CharSet=System.Runtime.InteropServices.CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName, 
  string lpWindowName);
 
[System.Runtime.InteropServices.DllImport("user32.dll", 
  CharSet=System.Runtime.InteropServices.CharSet.Auto)]
public static extern int GetWindowText(IntPtr hwnd,
  string lpString, int cch);
 
const string lpClassName = "Winamp v1.x";
const string strTtlEnd = " - Winamp";
 
static string GetSongTitle() 
{
      IntPtr hwnd = FindWindow(lpClassName, null);
      if (hwnd.Equals(IntPtr.Zero)) return "Not running";
 
      string lpText = new string((char) 0, 100);
      int intLength = GetWindowText(hwnd, lpText, lpText.Length);
            
      if ((intLength <= 0) || (intLength > lpText.Length)) 
        return "unknown";
 
      string strTitle = lpText.Substring(0, intLength);
      int intName = strTitle.IndexOf(strTtlEnd);
      int intLeft = strTitle.IndexOf("[");
      int intRight = strTitle.IndexOf("]");
 
      if ((intName >= 0) && (intLeft >= 0) && (intName < intLeft) &&
          (intRight >= 0) && (intLeft + 1 < intRight))
            return strTitle.Substring(intLeft + 1, intRight - intLeft - 1);
 
      if ((strTitle.EndsWith(strTtlEnd)) && 
            (strTitle.Length > strTtlEnd.Length))
            strTitle = strTitle.Substring(0, 
                strTitle.Length - strTtlEnd.Length);
 
      int intDot = strTitle.IndexOf(".");
      if ((intDot > 0) && IsNumeric(strTitle.Substring(0, intDot)))
            strTitle = strTitle.Remove(0, intDot + 1);
 
      return strTitle.Trim();
}
 
static bool IsNumeric(string Value)
{
      try 
      {
            double.Parse(Value);
            return true;
      }
      catch
      {
            return false;
      }
}

Complete VB .NET source code

VB
Private Declare Auto Function FindWindow Lib "user32" ( _
  ByVal lpClassName As String, _
  ByVal lpWindowName As String) As IntPtr
Private Declare Auto Function GetWindowText Lib "user32" ( _
   ByVal hwnd As IntPtr, _
   ByVal lpString As String, _
   ByVal cch As Integer) As Integer
 
Private Const lpClassName = "Winamp v1.x"
Private Const strTtlEnd = " - Winamp"
 
Private Function GetWinampSong() As String
    Dim hwnd As IntPtr = FindWindow(lpClassName, vbNullString)
 
    Dim lpText As String
 
    If hwnd.Equals(IntPtr.Zero) Then Return "Not running"
 
    lpText = New String(Chr(0), 100)
    Dim intLength As Integer = GetWindowText(hwnd, lpText, _
      lpText.Length)
 
    If (intLength <= 0) OrElse (intLength > lpText.Length) _
             Then Return "Unknown"
 
    Dim strTitle As String = lpText.Substring(0, intLength)
    Dim intName As Integer = strTitle.IndexOf(strTtlEnd)
    Dim intLeft As Integer = strTitle.IndexOf("[")
    Dim intRight As Integer = strTitle.IndexOf("]")
 
    If (intName >= 0) AndAlso (intLeft >= 0) AndAlso _
            (intName < intLeft) AndAlso _
       (intRight >= 0) AndAlso (intLeft + 1 < intRight) Then _
        Return strTitle.Substring(intLeft + 1, intRight - intLeft - 1)
 
    If (strTitle.EndsWith(strTtlEnd)) AndAlso _
        (strTitle.Length > strTtlEnd.Length) Then _
        strTitle = strTitle.Substring(0, _
          strTitle.Length - strTtlEnd.Length)
 
    Dim intDot As Integer = strTitle.IndexOf(".")
    If (intDot > 0) AndAlso (IsNumeric( _
           strTitle.Substring(0, intDot))) Then _
        strTitle = strTitle.Remove(0, intDot + 1)
 
    Return strTitle.Trim
End Function

Points of Interest

When I first wrote my code I used MarshallAs attributes. I made a mistake by specifying a wrong, but valid argument and spent about one hour looking for the bug. The function GetWindowText always returned 0. In this case, this attribute is not required, so don't use it.

History

  • Original code. Jan 6 2004.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Belgium Belgium
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralFind window Not Working Pin
Anubhava Dimri23-Oct-09 19:02
Anubhava Dimri23-Oct-09 19:02 
GeneralRe: Find window Not Working Pin
Niels Penneman24-Oct-09 0:27
Niels Penneman24-Oct-09 0:27 
GeneralFindWindow + API Pin
avmgan_314817-Sep-06 19:28
avmgan_314817-Sep-06 19:28 
GeneralRe: FindWindow + API Pin
Kristian Sixhøj15-Sep-07 9:35
Kristian Sixhøj15-Sep-07 9:35 
Questionbook????? Pin
mohit narang20-Jul-06 0:20
mohit narang20-Jul-06 0:20 
AnswerRe: book????? Pin
Niels Penneman20-Jul-06 4:18
Niels Penneman20-Jul-06 4:18 
Generalproblem Pin
mohit narang18-Jul-06 22:47
mohit narang18-Jul-06 22:47 
GeneralRe: problem Pin
Niels Penneman19-Jul-06 5:36
Niels Penneman19-Jul-06 5:36 
Generalnewbies Pin
mohit narang18-Jul-06 21:48
mohit narang18-Jul-06 21:48 
GeneralRe: newbies Pin
Colin Angus Mackay18-Jul-06 22:30
Colin Angus Mackay18-Jul-06 22:30 
GeneralRe: newbies Pin
Niels Penneman19-Jul-06 5:34
Niels Penneman19-Jul-06 5:34 
Questionsime improvements? Pin
fredjeboy1-Dec-05 9:07
fredjeboy1-Dec-05 9:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.