Introduction
There are some very useful utilities that extend shell capabilities around MP3 and other media files, such as AudioShell. They integrate media file metadata preview and editing into the Windows shell itself, without the need for any external application. The most notable example of shell extending is a preview of the media file metadata like the title and the artist info.
Following the same idea comes this article. This article presents a shell extension that adds infotip preview of PLS, M3U and M3U8 music playlists. PLS (introduced by Winamp) and M3U are the most wide-spread playlist formats, supported by Winamp, Windows Media Player, and many other players. M3U and PLS don't support Unicode, for which there is M3U8, an UTF8-extended M3U file format.
Vista Shell
There is one crucial difference between XP and Vista infotips. While in XP infotip's character count is not limited, Vista sets a limit on maximum number of displayed characters. Vista infotips are limited to about 900 characters, that is, about 15 rows with 65 chars per row + 5 chars in the 16th line, as seen in this screenshot (taken from a special test that generated a long string for infotip):
It is hard to tell if the line-break characters ('\n') are included in the count, but they probably are.
Therefore, playlist parsing and infotip generation is limited so that infotip can be shown properly on Vista an XP:
I haven't included a screenshot here of a big infotip on XP simply because the infotip can take the whole screen if you make it big enough (I don't know by how much it extends beyond the screen boundaries).
If you don't have Asian or other wide-character language files installed on your system, you might miss some characters if the playlist was originally saved with wide characters (Vista & XP screnshots):
The Code
This code is built on top of a code from an excellent article Windows 2000 UI Innovations by Dino Esposito. It is highly recommended to read it first as it explains many basic details which I won't cover here. For PLS and M3U/M3U8 format see unofficial specifications at Winamp forums. PLS files are parsed using the ConfigFile class by Richard J. Wagner.
The project is built with VC 2005 Express + Platform SDK2003 R2 + WTL 8.0 and probably builds without any changes in VC 2008.
A main playlist parsing framework is found inside PlaylistParser.cpp
. The playlist format is determined by file extension and appropriate parsing function is selected.
PLAYLIST_TYPE C_PlaylistParser::getType(CString fpl)
{
fpl.MakeLower();
if (fpl.IsEmpty()) return NOTPLS;
if (fpl==_T("m3u")) return M3U;
if (fpl==_T("m3u8")) return M3U;
......
return NOTPLS;
}
int C_PlaylistParser::process(CString fpls)
{
playlistFile.Split(fpls);
playlistFile.ext_nodot.MakeLower();
try
{
playlistType=getType(playlistFile.ext_nodot);
switch (playlistType)
{
case M3U:
parseM3U();
break;
case PLS:
parsePLS();
break;
......
default:
break;
}
buildPlaylist();
}
catch (...) {return FALSE;}
return TRUE;
}
Both M3U and M3U8 are processed by passing text lines to MultiByteToWideChar
with CP_UTF8
flag.
Note that PLS specification states that entries are case-sensitive.
buildPlaylist()
transforms info stored in vector into infotip with following layout:
<track#>.<artist, title> <track playtime ##:##>
....
--------------------------------------------
Total playing time: ##:##:##
Size: ######
If playlist processing fails completely, a generic infotip (file type, size) is displayed.
Please note that file size is determined with a GetFileSize
which works correctly only with files smaller than 2GB. While this is not a good practice, it is unlikely that a playlist will be bigger than 2 GB.
Finally, we must not forget to use try/catch
block in CBmpTip::GetBitmapInfo
method to prevent any possible error from crashing the Explorer (eg. pulling out USB drive while in use). In the source package there is a small test project (PLS.sln) to test the parser code, since debugging shell extensions inside Windows Explorer can be very inconvenient.
For some media types like *.ogg, a playlist may omiss the track playtime if the saving application can't determine it. If the file path points to web radio stream, track name displays URL and track playtime is undetermined.
Vista and UAC
In order to make this shell extension play nice with UAC, a DLL must be added to the known DLLs list.
HKLM
{
NoRemove Software
{
NoRemove Microsoft
{
NoRemove Windows
{
NoRemove CurrentVersion
{
NoRemove 'Shell Extensions'
{
NoRemove Approved
{
val {A191B386-C1C7-4fb5-AD9D-6979C21CE44B} = s 'PlsTip Class'
...
Reusing the Code
To extend parsing to other playlist formats (like wpl etc.), you need to put your infotip-generator function inside CBmpTip::GetBitmapInfo
member, add a new file extension to the PLAYLIST_TYPE
enum in PlaylistGlobals.h and inside C_PlaylistParser::getType
, and add a new parsing function to the switch(playlistType)
block.
It is also neccessary to add neccessary registry entries inside BmpTip.rgs and BmpTip.idl files.
To make a completely new infotip extension, put your new infotip generator function inside CBmpTip::GetBitmapInfo
member, and change CLSIDs inside BmpTip.rgs and BmpTip.idl files.
A limited error correction is implemented wherever possible, but it is not error-proof as in normal programs because I don't expect to parse a hand-made playlists (which may contain errors). The code works best with application-generated playlists, as they are unlikely to contain structural errors. The project package comes with some test files so you can conduct you own tests.