I've been trying to create an archive plugin for a custom music format (RWD). I've got to the point where the uncompressed music is in a memory buffer, so now all I need to do is create a reader_mem on the buffer. This process works and I can successfully use the reader to read the memory. However, the archive factory cannot seem to use it.
Whenever I add this archive to the playlist, I correctly get a list of all the tracks in the archive, but none of them get parsed, and all the playlist entries appear with "?" marks. In the file properties dialog box, only the packed path string appears. Nothing else is present (no meta info, no tech info, no song length, no file size). It seems as though Foobar2000 cannot use my reader.
How can I create a reader_mem that Foobar2000 can use to read archives?
CODE
reader *archive_rwd::get_reader(const char *path)
{
/* Error handling removed for clarity. */
string8 archive, file;
RWDInfo rwd_data;
this->parse_unpack_path(path, archive, file);
reader *r_file = file::g_open_read(archive);
/* RWD::ReadTrack fills rwd_data with useful metadata such as buffer sizes */
RWD::ReadTrack(r_file, file, rwd_data);
mem_block_t<char> out_buffer (rwd_data.fileLength);
RWD::DecompressData(r_file, out_buffer);
r->reader_release();
reader_mem *rActual = new service_impl_p2_t<reader_mem, void *, int>
(out_buffer, out_buffer.get_size());
/* rActual is fine here. It now holds ownership of out_buffer. */
return rActual; /* But Foobar2000 cannot use it */
}
I've tried making out_buffer and rActual global variables: that didn't help. I've tried using both new and malloc instead of mem_block_t, that made things worse. I've also tried reader_limited.
Edit:
The problem appears to be a bug with reader_mem itself. Right after calling get_reader for my archive plugin, Foobar2000 attempts to reader::open the path, and this is where the bug is.
The open method for reader_mem is a stub, and when Foobar2000 attempts to use the reader, it returns failure. That's why my playlist is coming up empty. To correct the bug:
CODE
// In "../SDK/reader_mem.h" line 68:
class reader_mem : public reader_mem_base
{
virtual bool open(const char *filename, MODE mode)
{
return 0; /* <-- should be "return true;" */
// return true; /* Use this line instead. */
}//dummy
public:
reader_mem(void * p_data,int p_size)
{
free_on_exit = true;
mem_init(p_data,p_size);
}
};
(The same code is used with reader_limited, which explains why it fails too) If I change the line in open(), then everything works fine. I suppose instead of hacking the headers, I could override the method in a derived class.
But won't it be considered a hack if I try to override this behaviour (whether through header hacking or derived class overrides)?
