Home › Forums › TWAIN Mac/OSX › twain event loop for mac OS X
- This topic has 6 replies, 3 voices, and was last updated 6 years, 7 months ago by Johnwick88.
- AuthorPosts
I’m trying to write a twain client that supports Mac OS X 10.7 and later. I have implemented a callback function which is Twain 2.x compliant and it appears to work with some Twain devices on the Mac, however, as I understand it Mac only supports up to Twain 1.9, which doesn’t use a callback function (it uses an event loop).
The Twain 1.9 spec gives sample code for the Carbon API, but not for Cocoa. As Carbon is now deprecated, is there any sample code for Cocoa so that I can see how to do an event loop that would be Twain 1.9 compliant?
Mac OS X supports all versions of TWAIN, including the newly released 2.3. What it doesn’t currently have is an updated Data Source manager.
Fortunately, that version of the DSM does support DAT_CALLBACK. The main difference is that Mac OS X requires a driver to use DG_CONTROL / DAT_CALLBACK / MSG_INVOKE_CALLBACK to trigger a callback. The experience on the Application side is the same. Use DG_CONTROL / DAT_CALLBACK / MSG_REGISTER_CALLBACK to register for the callback.
We recommend using the TWAIN 2.3 TWAIN.H file (found on twain.org), rather than the older TWAIN.H file found in /System/Library/Frameworks/TWAIN.framework/Headers. It’s compatible with all drivers and applications on Mac OS X…
Thanks for the reply!
I have Mac drivers for other Epson scanners that install fine but don’t appear to work with the callback, so I was figuring that I needed to support the old Twain 1.9 event loop for those scanners. This is where it appeared that I needed to use the deprecated Carbon framework to send Carbon events to the datasource.
Just to be perfectly clear, are you saying that I simply don’t need to support the old-style Mac event loop at all, even for older scanners?
I wish I could be that confident. With the new open source DSM (which hasn’t been ported to the Mac yet) it doesn’t matter how the driver triggers an event, the DSM will report it through the appropriate mechanism to the application.
If Apple implemented it correctly, this should be the behavior for the Mac DSM, so if a driver uses DG_CONTROL / DAT_NULL to send a message to the DSM, then if a callback is registered, it should be invoked. Unfortunately, I can’t be sure Apple did that, and the use of a special MSG_INVOKE_CALLBACK hints that they may not have done it right.
So, sadly, the only way to know is to try it…
Thanks Mark, I really appreciate your help on this.
Hi Mark,
I tried the following code with no luck. I never receive any cocoa events of any kind. I also tried GetNextEvent and it also returns no events.
My code is part of a pluginprocess for the Safari Browser, so I’m wondering if I can even get any events.
// This method will look for a Mac event to dispatch to the DS.
S32 TwainSessionMac::ProcessMacEvent()
{
NSAutoreleasePool *outerpool = [[NSAutoreleasePool alloc] init];
NSEvent *cocoaEvent =
[NSApp
nextEventMatchingMask:NSAnyEventMask
untilDate:nil
inMode:NSDefaultRunLoopMode
dequeue:YES];if (cocoaEvent)
{
// Convert to a carbon event
EventRecord carbonEvent;
if (!([cocoaEvent eventRef] && ConvertEventRefToEventRecord((EventRef)[cocoaEvent eventRef], &carbonEvent)))
{
NSPoint where = cocoaEvent window] convertBaseToScreen:[cocoaEvent locationInWindow;carbonEvent.what = nullEvent;
carbonEvent.message = 0;
carbonEvent.when = (UInt32)([cocoaEvent timestamp] * 60); // seconds to ticks
carbonEvent.where.h = (short)where.x;
carbonEvent.where.v = (short)(NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]) – where.y);
carbonEvent.modifiers = 0; //[self modifiersForEvent:cocoaEvent];
}// send to data source
TW_EVENT twEvent;
twEvent.pEvent = (TW_MEMREF)&carbonEvent;
twEvent.TWMessage = MSG_NULL;
S32 rc = m_twBase.TWAIN_DS(&CurrentDS(), DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT, (TW_MEMREF)&twEvent);
if( rc < 0 )
{
WIC_WARN(g_sessnMacLog, “DataSource operation failed:%d”, rc);
SetErrorCode(rc);
return TWRC_FAILURE;
}
else if( rc == TWRC_FAILURE )
{
TW_UINT16 cc = m_twBase.TWAIN_ConditionCode();
WIC_WARN(g_sessnMacLog, “DS operation returns error: %d/%d”, rc, cc);
SetErrorCode(TWSSNEW_FAILURE, cc);
return TWRC_FAILURE;
}ClearErrorCode();
if( rc == TWRC_DSEVENT )
{
WIC_TRACE(g_sessnMacLog, “DataSource consumes the message”);
return m_twProc.TwainProc(twEvent.TWMessage);
}[NSApp sendEvent:cocoaEvent];
[NSApp updateWindows];
}[outerpool release];
return TWRC_SUCCESS;
}Thanks Mark.
royal1688
- AuthorPosts