Return to Home Page
Greg Santo's Game Programming Portfolio
   
The GMan's Power Hour Plugin


Program Description

A Power Hour is a simple drinking game in which the players take a shot of beer every time a new song starts to play. A new song should start to play every 60 seconds and thus each player takes 60 shots of beer in a single Power Hour. The GMan's Power Hour Plugin cycles through all the songs in Winamp's playlist, playing 60 seconds of each. The user has the option of letting the plugin start each song at the beginning, at a specific time in the song, or at a random position within a range the user specifies. Also, the plugin keeps track of the time the Power Hour was started, how many songs are left, how many songs have been completed, and the amount of time left in the current song.

Programming Challenges

Although this program was created for recreational purposes it proved to be an excellent learning experience for the Win32 API. However, since this plugin requires real-time song changes I was faced with the problem of message queue delays from Winamp's API. When a request from my plugin was sent to Winamp to change the song, for example, Winamp's API returned that the message had been received. However, the message was not always processed. In order to solve this problem I had to pump messages from Winamp's message queue until my message was finally processed.


Features

  • Option to have the plugin start at Winamp startup
  • Option to have each song start at the beginning, a specific time, or at a random time within a range you specify
  • Hide the plugin to the system tray
  • Control the plugin from the system tray
  • Instructions included


Screenshots





The plugin's main window
Options screen
About screen
You can also minimize the plugin to the system tray


Code Sample
The following block of code appears in the WndProc function which processes messages for the Winamp window. This section of code is called whenever there is a song change (i.e. the pluginInfo.state == DECIDING) or when the user clicks the NEXT button. The default return value is stored before any custom code is executed to ensure compatibility.

switch(message)

{

    ...

 

    case WINAMP_NEXT:

 

        // First we process the command

        returnValue = CallWindowProc(lpWndProcOld, hwnd, message, wParam, lParam);

 

        if(pluginInfo.state == DECIDING)

        {

            newTrack = SendMessage(plugin.hwndParent, WM_USER, 0, 125);

 

 

            // If the new current song is still the previous song, we have reached the end of the playlist.

            // Post a restart playlist message.

            if(originalTrack == newTrack)

            {

                // Restart the playlist

                originalTrack = -1;

                newTrack = -1;

                SendMessage(plugin.hwndParent, WM_COMMAND, WINAMP_RESTART_PLAYLIST, 0);

                break;

            }

 

 

            // If we get to this point, the new song is different from the previous one, we now check to see

            // if it is at least 60 seconds

            currentTrackLength = SendMessage(plugin.hwndParent, WM_USER, 1, 105);

 

            if(currentTrackLength >= SONG_DURATION_SECONDS)

            {

                pluginInfo.state = CHANGING_SONG;

                SendMessage(plugin.hwndParent, WM_COMMAND, WINAMP_PLAY, 0);

                break;

            }

            else

            {

                // Since the new song is not usable, we must find a new one

 

                // This new song becomes our new "previous" track

                originalTrack = newTrack;

 

                // We post another "Next" message

                if(++skippedTracks >= MAX_SKIPPED_TRACKS)

                {

                    if(MessageBox(g_hPlugin, "It appears that either your playlist is empty or you have too many songs in your\nplaylist that are shorter than 60 seconds long.\n\nIf you would like the plugin to continue to search for a \"usable\" file, make any\nnecessary changes to your playlist and select YES.\n\nIf you would like the plugin to stop searching and terminate select NO.", "Keep Searching?",

                       MB_ICONQUESTION | MB_YESNO) == IDNO)

                    {

                        pluginInfo.b_SkipCloseMsg = TRUE;

                        SendMessage(g_hPlugin, WM_CLOSE, 0, 0);

                        pluginInfo.state = DISABLED;

                        return returnValue;

                    }

                    else

                    {

                        // Just in case someone pushed play

                        SendMessage(plugin.hwndParent, WM_COMMAND, WINAMP_STOP, 0);

                        skippedTracks = 0;

                    }

                }

                SendMessage(plugin.hwndParent, WM_COMMAND, WINAMP_NEXT, 0);

            }

        }

 

        // Return the return value of our window procedure

        return returnValue;

        break;

 

    ...

}


Downloads

The GMan's Power Hour Plugin.exe - The windows installer for The GMan's Power Hour Plugin Version 1.1
   
Copyright © 2006 Greg Santo