Program Description
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
