Re: Accessing user interface from ioProc
Re: Accessing user interface from ioProc
- Subject: Re: Accessing user interface from ioProc
- From: Michael Thornburgh <email@hidden>
- Date: Thu, 20 Nov 2003 00:05:02 -0800
there are a few different problems going on here.
the first, related to the error message you got: almost all interesting
Cocoa methods, especially those in the AppKit, require an
NSAutoreleasePool to be active for memory management. the thread in
which the IOProc executes has no NSAutoreleasePool automatically in
place for you. if you wanted a pool in place in your IOProc (which you
don't, see below), you'd do something like
OSStatus myIOProc (80 gazillion parameters...)
{
NSAutoreleasePool * pool = [NSAutoreleasePool new];
// do all your work, send messages to Cocoa objects, etc
[pool release];
return noErr;
}
second: memory allocation (and therefore, object creation) is not
recommended in your IOProc. the time available to do the work in your
IOProc is constrained, and malloc and its buddies can cause swapping,
paging, and waiting on very busy locks, which can cause unpredictable
and long pauses, possibly causing your IOProc to overload (glitch).
since you got a warning message about no NSAutoreleasePool being in
place, that means an object was getting created and was trying to be
autoreleased. creating an NSAutoreleasePool would create yet another
object at IOProc time. not having one in place is even worse, though
-- the NSCFNumber being created isn't being released at all, which is a
memory leak. eventually you'll run out of memory.
second-and-a-half: updating cocoa view objects on the screen can also
take super long, and shouldn't be done in the IOProc.
third: almost none of the interesting AppKit objects are inherently
thread-safe, and in particular, UI objects should only be updated in
the main thread. updating those objects from threads other than the
main one can (and probably will) result in drawing glitches and
inconsistencies. from your IOProc, you can queue up something to
happen in the main thread to actually do your UI updating, see
-[NSObject performSelectorOnMainThread:withObject:waitUntilDone:] for
more information (and you _don't_ want to waitUntilDone, of course!).
-mike
On Nov 19, 2003, at 8:09 PM, Michael Bonnice wrote:
In my application, I listen to the input device and calculate an FFT
all within my ioProc. This works, and I can print the results using
fprintf(stderr, ...) from my ioProc. Now I'm ready to put the results
into my user interface.
This is an Objective-C program, and I'm new to Objective-C and Cocoa.
Naturally, before I've even got the grip of the object hierarchy and
the flow of control, I need to send a message to an object while in an
ioProc, and I don't know what scope the ioProc is in (or if this is
even a meaningful concept?)
There is a text field in my interface window that should display the
result. I stored a reference to that field, calculate the result, then
send the field the message to display the result. It does display it,
but I get an error message in the console each time I send the message:
2003-11-19 21:05:44.854 Tuner[466] *** _NSAutoreleaseNoPool(): Object
0x36b3d0 of class NSCFNumber autoreleased with no pool in place - just
leaking
Any ideas how to fix this?
Mike
Code fragments:
@interface TunerController : NSObject
{
...
IBOutlet id freqField; // the user interface item, a text field
...
}
...
@end
@implementation TunerController
- (void)awakeFromNib
{
[tuner setup]; // this will initialize our CoreAudio data
...
[tuner setLeftFreqField: freqField]; // tell the tuner where to
show the left frequency
}
..
@end
@interface Tuner : NSObject
{
...
IBOutlet id leftFreqField; // field showing the
frequency of the left channel
}
...
- (void)setLeftFreqField:(id)field;
@end
// define a C struct from the Obj-C object so audio callback can access
data
typedef struct {
@defs(Tuner);
} tunerdef;
// this is the audio processing callback
OSStatus inappIOProc (AudioDeviceID inDevice, const AudioTimeStamp*
inNow, const AudioBufferList* inInputData,
const AudioTimeStamp* inInputTime,
AudioBufferList* outOutputData, const AudioTimeStamp* inOutputTime,
void* defptr)
{
tunerdef* def = defptr; // get access to Tuner's data
float leftFreq;
// do the FFT math here, the answer is in leftFreq
..
[def->leftFreqField setDoubleValue: leftFreq]; // display
the result !!!!!!!!!!!!!! problem here !!!!!!!!!!
}
@implementation Tuner
- (void)setLeftFreqField:(id)field
{
leftFreqField = field; // store the field id in a place where
the
ioProc can get it
}
@end
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.