Click here to Skip to main content
15,868,016 members
Articles / Web Development / ASP.NET
Article

Web Based Winamp Controller

Rate me:
Please Sign up or sign in to vote.
4.94/5 (14 votes)
18 Dec 20023 min read 194.7K   2.9K   66   31
Web based WinAmp server

WinAmp controller

Introduction

This article shows a method of controlling WinAmp via a web browser.

Background

Sometime ago I was working at a place where all the developers worked in the same area away from other people. It didn't take long before our main development server began to fill up with quite a collection of MP3's. Once this happened the server then got connected to the phone system and to a decent set of speakers. The only thing left to do was remotely control the playlist. That's where this article comes in.

Using the code

WinAmp can be controlled using the Windows Messaging system. First you need to get a handle to WinAmp, this is done using the FindWindow API. It turns out that all of the WomAmp versions have the same class name: "Winamp v1.x".

Messages are sent in the form of:

int returnVal = SendMessage(hwndWinamp, WM_USER ,data, id);

In order for a Windows service to obtain the handle of the running WinAmp it needs to be able to interact with the desktop. This is done by editing the service properties and checking the 'Allow service to interact with desktop' button.

The web application communicates with the windows service via remoting. The class winampcontroller is remoted between the web application and the windows service. In fact you could do without the Windows service if you wanted to allow IIS to interact with the desktop, but we didn't want to modify the properties of IIS to do this because of security fears.

Since the application is written using the .NET framework, interop is used to call the native Windows API, the following code snippet shows how to send simple commands to WinAmp.

C#
public class winampcontroller : MarshalByRefObject
{
    [DllImport("user32.dll", CharSet=CharSet.Auto)]
    public static extern IntPtr FindWindow(
        [MarshalAs(UnmanagedType.LPTStr)] string lpClassName,
        [MarshalAs(UnmanagedType.LPTStr)] string lpWindowName);
    
    [StructLayout(LayoutKind.Sequential)]
    struct COPYDATASTRUCT
    {
        public IntPtr dwData;
        public int cbData;
        [MarshalAs(UnmanagedType.LPStr)] public string lpData;
    }
    [DllImport("user32.dll", CharSet=CharSet.Auto)]
    static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam,
        [In()] ref COPYDATASTRUCT lParam);
    
    [DllImport("user32.dll", CharSet=CharSet.Auto)]
    static extern int SendMessageA(IntPtr hwnd, int wMsg, int wParam,
        int lParam);
    
    //see table below for descriptions
    const int WM_COMMAND = 0x111;
    const int WM_USER = 1024;//0x4A;
    const int WA_PLAY = 40045;
    const int WA_STOP = 40047;
    const int WA_PAUSE = 40046;
    const int WA_PREVTRACK = 40044;
    const int WA_NEXTTRACK = 40048;
    const int WA_GETSTATUS = 104;
    const int WA_PLAYLISTLEN = 124;
    const int WA_SETVOLUME = 122;
    const int WA_SETPLAYLISTPOS = 121;
    const int WA_WRITEPLAYLIST  = 120;
    const int WA_VOLUMEUP = 40058;                    
    const int WA_VOLUMEDOWN = 40059;
    const int WA_CLEARPLAYLIST = 101;
    const int WA_NOTHING = 0;
    const int WA_RESTART = 135;
    const int WA_REFRESHPLCACHE = 247;
        
    public const int STOPPED = 0;
    public const int PLAYING = 1;
    public const int PAUSED = 3;
    protected string m_windowName;
    public winampcontroller()
    {
        try
        {
            m_windowName = ConfigurationSettings.AppSettings["WindowClassName"];
        }
        catch(NullReferenceException)
        {
            m_windowName = "Winamp v1.x";
        }
    }
    public void Stop()
    {
        IntPtr hwnd = FindWindow(m_windowName, null);            
        SendMessageA(hwnd, WM_COMMAND, WA_STOP, WA_NOTHING);
    }
    public void Play()  
    {            
        IntPtr hwnd = FindWindow(m_windowName, null);            
        SendMessageA(hwnd, WM_COMMAND, WA_PLAY, WA_NOTHING);
    }
    public void Pause()
    {
        IntPtr hwnd = FindWindow(m_windowName, null);            
        SendMessageA(hwnd, WM_COMMAND, WA_PAUSE, WA_NOTHING);
    }
}

WinAmp has pre-defined responses to different values of data, some of these are:

0 Retrieves the version of Winamp running. Version will be 0x20yx for 2.yx.
100 Starts playback.
101 Clears Winamp's playlist.
102 Plays selected track.
104 Returns the status of playback. If 'returnVal' is 1, Winamp is playing. If 'returnVal' is 3, Winamp is paused. Otherwise, playback is stopped.
121 Sets the playlist position to the position specified in tracks in 'data'.
122 Sets the volume to 'data', which can be between 0 (silent) and 255 (maximum).
124 Returns length of the current playlist, in tracks.
125 Returns the position in the current playlist, in tracks (requires Winamp 2.05+).
129 Adds the specified file
135 Restarts Winamp

The windows service consists of a few lines of code outside of the code generated by Visual Studio:

C#
protected override void OnStart(string[] args)
{
    int tcpChannelVal = 0;
    try
    {
        tcpChannelVal = int.Parse(ConfigurationSettings.AppSettings["ChannelNum"]);
    }
    catch(Exception){
        tcpChannelVal = 1096;
    }

    m_channel = new TcpChannel(tcpChannelVal);
    ChannelServices.RegisterChannel(m_channel);
    RemotingConfiguration.ApplicationName = "WinampController";
    RemotingConfiguration.RegisterWellKnownServiceType(typeof(winampcontroller),
                               "WinampController",WellKnownObjectMode.Singleton);

}

protected override void OnStop()
{
    ChannelServices.UnregisterChannel(m_channel);
}

To install the windows service, you need to use the InstallUtil program that comes with the .NET Framework SDK or Visual Studio .NET

The web application's web.config files need to be changed to point to a directory that contains MP3's

The whole application was put together in a few hours, us being programmers and not designers means that the front end is not very pretty, but since it's only HTML it's easy to change. In terms of features, this example controls a playlist of files in a directory. More functionality and better error handling was destined for this project, but as usual not enough time has meant that it will have to stay this way.

If anyone wants to create a better front end or add more features you are more than welcome too, I would of course update the article with your name and contributions.

Points of Interest

When this code was originally written WinAmp was at version 2. Currently WinAmp is at version 3, which does not provide the same methods for manipulating the player; however, I did find this plugin which replicates the desired functions:

Winamp 2.x Plugin Manager for Winamp 3

History

10/12/2002 - Article Created

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
Web Developer
Australia Australia
I've been programming for a few years now. I blog regularly at httpcode.

Comments and Discussions

 
GeneralGiving IIS access to desktop Pin
p10005-Mar-07 15:00
p10005-Mar-07 15:00 
GeneralRe: Giving IIS access to desktop Pin
lepipele30-Aug-08 5:29
lepipele30-Aug-08 5:29 
Newsreading the winamp playlist (here is the code for it) Pin
fs_Death31-Jan-07 10:43
fs_Death31-Jan-07 10:43 
GeneralGreat Demo Pin
mkeysaer20-Oct-06 19:59
mkeysaer20-Oct-06 19:59 
GeneralGetting this damn thing to work Pin
Abeasp20-Dec-05 9:37
Abeasp20-Dec-05 9:37 
GeneralRe: Getting this damn thing to work Pin
mkeysaer20-Oct-06 19:55
mkeysaer20-Oct-06 19:55 
Generalsending a stream to winamp. Pin
drewdaman2-Nov-04 10:00
drewdaman2-Nov-04 10:00 
GeneralGetting the file name... Pin
DittoACE13-May-04 10:56
DittoACE13-May-04 10:56 
QuestionAnyone got this working in VB? Pin
Doggystyle10-Sep-03 16:18
Doggystyle10-Sep-03 16:18 
AnswerRe: Anyone got this working in VB? Pin
Niels Penneman3-Jan-04 8:11
Niels Penneman3-Jan-04 8:11 
AnswerRe: Anyone got this working in VB? Pin
Niels Penneman3-Jan-04 8:13
Niels Penneman3-Jan-04 8:13 
GeneralRejecting connection. Pin
zeuszeus8-Sep-03 0:10
zeuszeus8-Sep-03 0:10 
Generallittle problems... Pin
Anonymous16-Jun-03 10:11
Anonymous16-Jun-03 10:11 
GeneralIt's not working Pin
Jesse364714-Mar-03 19:02
Jesse364714-Mar-03 19:02 
GeneralRe: It's not working Pin
leppie14-Mar-03 21:25
leppie14-Mar-03 21:25 
GeneralRe: It's not working Pin
bspann28-Apr-03 5:04
bspann28-Apr-03 5:04 
QuestionWorking VB.NET Version? Pin
calcock13-Mar-03 13:02
calcock13-Mar-03 13:02 
AnswerRe: Working VB.NET Version? Pin
Member 140986726-Apr-05 9:16
Member 140986726-Apr-05 9:16 
GeneralNo connection at all... Pin
Jan R Hansen1-Jan-03 12:43
Jan R Hansen1-Jan-03 12:43 
GeneralRe: No connection at all... Pin
Jan R Hansen7-Feb-03 7:49
Jan R Hansen7-Feb-03 7:49 
GeneralRe: No connection at all... Pin
ogiDogi14-Mar-03 7:38
ogiDogi14-Mar-03 7:38 
GeneralRe: No connection at all... Pin
coderDeamon23-Mar-05 0:28
coderDeamon23-Mar-05 0:28 
GeneralAbout your windows service Pin
Mazdak19-Dec-02 22:17
Mazdak19-Dec-02 22:17 
GeneralRe: About your windows service Pin
Dan_P19-Dec-02 22:21
Dan_P19-Dec-02 22:21 
GeneralRe: About your windows service Pin
xcashx2-Apr-03 23:36
xcashx2-Apr-03 23:36 

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.