So, the short of it is, Winamp is stupid. It does not particularly allow you to "queue up" (in the playlist) multiple songs that are stored within a single file. The playlist is literally architected to reference physical files on disk; Winamp supports absolutely nothing else. I will describe this in detail for RSN below, but here's what you need to know:
Think about what now has to happen with NSFE: you have to quite literally split the NSFE file up into N separate NSF files, write them all to disk, and then build the playlist with IPC_ENQUEUEFILE. This is pretty ugly/terrible: think about those NSFEs that have hundreds of songs. You now get to extract hundreds of files to disk, which means lots of disk I/O and wasted disk space just to play what is essentially a single file, and you risk causing Winamp to block/stall (i.e. could report "Not responding") while the plugin does this, depending on all sorts of variables. If the source file is on a CIFS/SMB share, or a USB stick, or whatever else, it means tons of network I/O or silly writes to the USB media. Additionally -- and this is a HUGE one -- if Winamp crashes, which I have had happen with NSFPlay on rare occasion (I still can't pinpoint what I'm doing that causes it),
nothing is going to clean up all those files on disk so you now have junk laying around somewhere. I imagine all of this is partially what's been plaguing rainwarrior for some time now and why he has to think long and hard about how (or if) he wants to try and solve it.
The RAR loading/extraction routines for RSN are compiled/built into the plugin itself, using
unrar.dll from the official RAR owner/maintainer. Winamp does not do archive decompression or management natively in any way. SNESAmp hooks into the DLL by loading it at runtime and then using
GetProcAddress to find the locations of the functions it cares about --
RAROpenArchive (using RAR_OM_EXTRACT) and
RARProcessFile are the two relevant ones.
RARProcessFile, when given a valid open archive, will extract the relevant file from the archive into a directory of your choice -- but if you pass NULL as the parameter, which SNESAmp does via
rar.ProcessFile(rh, RAR_TEST, NULL, NULL);, it extracts the file into the current working directory, then tells Winamp "here's the path to the extracted file" + adding it to the playlist. So, in other words: it does things exactly like how I just described in my above paragraph. RAR is a somewhat "touchy" format licensing-wise as well, but whatever. Here's the terrible code (which is compatible with Winamp 2.x, so you won't see IPC_ENQUEUEFILE mentioned -- it instead does things the old/hard way):
Code:
case(ID6_UNK): //File was unknown, it could be a RAR file
if (!xpl || !rar.GetDllVersion || parsing) return ID6_UNK;
parsing = 1; //RAR file is being parsed
//Open RSN file ------------------------
memset(&ropen, 0, sizeof(RAROpenArchiveData));
ropen.ArcName = fn;
ropen.OpenMode = RAR_OM_EXTRACT;//LIST;
rh = rar.OpenArchive(&ropen);
if (!rh) goto Error;
rf.pData = NULL;
rf.alloc = 0;
rf.size = -1;
rar.SetCallback(rh, RARCallback, (s32)&rf);
//Get pointer to internal filename -----
strcpy(str, fn);
s = ::StrEnd(str);
*s++ = '\\';
setCur = 0; //Initial file hasn't been found yet
cds.dwData = IPC_PLAYFILE;
cds.lpData = str;
while(!rar.ReadHeader(rh, &rhdr))
{
if ((rhdr.Flags & 0xE0) != 0xE0)
{
if (!strcmpi(ScanStrR(rhdr.FileName, '.'), "spc"))
{
strcpy(s, rhdr.FileName);
//Extract file -------------
rf.size = 0;
rar.ProcessFile(rh, RAR_TEST, NULL, NULL);
lastType = lastID6.LoadTag(rf.pData, rf.size);
strcpy(lastID6.file, str);
lastRAR = 1;
if (lastType == ID6_SPC || lastType == ID6_EXT)
memcpy(lastFile, rf.pData, 0x10200);
else
lastType = ID6_UNK;
rf.size = -1;
//Add file to playlist -----
if (!setCur) //If this is the first SPC, change current PL file
{
SendMessage(inMod.hMainWindow, WM_WA_IPC, (WPARAM)str, IPC_CHANGECURRENTFILE);
setCur = 1;
}
else //Otherwise add the file to the play list
{
cds.cbData = strlen(str) + 1;
SendMessage(inMod.hMainWindow, WM_COPYDATA, (WPARAM)0, (LPARAM)&cds);
}
continue;
}
}
if (rar.ProcessFile(rh, RAR_SKIP, NULL, NULL)) break;
}
if (rf.pData) free(rf.pData);
rar.CloseArchive(rh);
You can read a "general" comprehension of how unrar.dll functions behave here (ignore the fact this is for Python, it doesn't matter):
https://python-unrar.readthedocs.io/en/ ... manual.txtYou can get the SNESAmp source here (does not include unrar.dll -- that is included with the SNESAmp installer, and the DLL ends up in your Winamp plugins dir (yes really)):
https://www.alpha-ii.com/Source/index.htmlCircling back:
You can blame Winamp for all of this nonsense. It was never, ever intended to be able to "play multiple songs from a single file", and .m3u/m3u8 won't work either (that is just a on-disk playlist of filenames also on the disk). Winamp, in every way/shape/form, expects physical files on the disk for its playlist. It was designed to be an MP3 player. I think sometimes people forget that. So, any plugin you see that supports a file format with multiple songs within a single file has to extract the files to disk somewhere for the Winamp playlist to be able to work with it. What's going on under the hood is hidden from you, but this is what's going on.
Now I hope you understand how/why NSFPlug/NSFPlay works the way it does with its native plugin song UI/dialog selector. Yes, I too would love for it to work in the playlist, but once I saw how it has to be done, I learned to not complain and just use it.
I think with NSFPlay (not NSFPlug!) it will be 100% possible to have a kind of "song playlist" natively within the program. But with Winamp, nope, not gonna happen.
Finally: I should add that music formats, *ESPECIALLY* those with compression wrappers, have been under extreme scrutiny in the past several years for security-related problems: such as allowing someone to inject a malicious file into the archive and due to bugs in the decompressor, running code when the file is loaded (song is played). I really have to suggest not going this route if it can be avoided. The one format that's been generally pretty good over the years is VGZ (multiple VGMs in a zlib/gzip archive), but again, the process is the same as I just described.