I hate to admit it, but I have been trying to debug one single, annoying bug in my TWAIN plugin for the last week (well, almost). And the worst part about it: it wasn’t even my code that was the root cause! I’m going to go on a bit of a rant, so forgive me if I’m a bit rough with my words, but I am quite displeased at this entire situation.
TWAIN, for those who don’t know, is an interface that allows all kinds of image and audio capture devices to communicate with applications in a standardized way. For developers, this is great because application developers only need to implement one protocol to provide for a wide array of devices, and device manufacturers that provide TWAIN data sources (drivers) automatically support a wide array of applications. Win/win.
There’s a few problems, though. The technical expertise needed to leverage TWAIN is fairly high compared to other popular APIs. Also, the documentation, while mostly correct in the information it provides, does have some typographical and formatting issues that really make it difficult to use. But that’s not what has been causing me so much grief. Oh, no. This problem is much more insidious.
So after figuring out how TWAIN actually works, like how to pass messages and whatnot, I ported the TWAIN header file to pure REALbasic code and proceeded to cook up an example that would show the scanner’s interface dialog. I had been reading through the documentation, and they had mentioned there was a way to receive messages back through a callback, which was optional on Windows, but required for Macs. I quickly decided this would be a good idea, as it would keep most of my code cross-platform, and soft-linked to TWAINDSM.DLL instead of TWAIN_32.DLL.
This process went relatively fast, as there’s only a handful of messages that need to be sent to initialize TWAIN to the point of being useful. I set up the aforementioned callback to beep when it received a useful event. However, when I ran my debug builds, every time the data source’s dialog box would show up just fine and seem mostly functional, but would never fire the callback. And when this callback is responsible for handling closing off the data source dialog, and to start the scanning procedure, you should be able to see how this may be somewhat of a problem.
Because I did notice some problems with how the controls were working, I decided to explore the possibility that I was not handling some sort of event correctly, or REALbasic was causing some issues by not dispatching messages to the window at all. I ended up setting up a GetMsgProc hook (which sees EVERYTHING that passes through the GetMessage() and PeekMessage() functions), but lacking an easy to navigate table of Windows messages, this was like picking a needle out of a haystack. I downloaded Winspector (which is a pretty useful program) to assist in this endeavour, but it did not solve my problem; I was just not seeing the messages I should have seen being sent and received.
So why wasn’t I seeing those messages? Because they weren’t actually being sent and received? Yeah, that should have been a tip-off right there, and saved me two days in debugging time. But no. Because I was using hooks to intercept messages from RB and pass them off to TWAIN, I figured RB might be doing the same thing, and killing any of the events it didn’t recognize before I got a chance to look at them. As a result, I squished my code into a REALbasic plugin and tried to work some wizardry there, but it was to no avail. The messages just weren’t coming or going.
At this point, five days had gone by with this one miserable dialog box misbehaving. And then it dawned on me. The messages weren’t coming or going, period. And the only remaining reason I could think of was because the library I was using was defective. Thankfully I still had the GetMsgProc filter set up, so switching from TWAINDSM.DLL back to TWAIN_32.DLL was no hardship at all. Once I made the switch, everything worked great.
With that nasty bug out of the way, let’s hope my plugin development goes a bit smoother.
In theory, I could just develop the TWAIN stuff in pure RB, but I think I’ll hold off on it for now, as the TWAIN_32.DLL library does not export any of its symbols, which in turn makes it hard for RB to load. Not impossible, but more typing than I’m really up for considering the plugin is working just fine at the moment.
If you have any tales of miserable bugs to share, feel free to do so; I’d like to think I’m not the only one that has them, even if they only appear once in a blue moon.