1#import "GSSpeechSynthesizer.h" 2 3static GSSpeechServer *server; 4static int clients; 5 6@interface GSSpeechSynthesizer (Private) 7+ (void)connectionDied: (NSNotification*)aNotification; 8@end 9 10@implementation GSSpeechSynthesizer 11+ (void)initialize 12{ 13 server = [[GSSpeechServer sharedServer] retain]; 14 [[NSNotificationCenter defaultCenter] 15 addObserver: self 16 selector: @selector(connectionDied:) 17 name: NSConnectionDidDieNotification 18 object: nil]; 19} 20 21/** 22 * If the remote end exits before freeing the GSSpeechSynthesizer then we need 23 * to send it a -release message to make sure it dies. 24 */ 25+ (void)connectionDied: (NSNotification*)aNotification 26{ 27 NSEnumerator *e = [[[aNotification object] localObjects] objectEnumerator]; 28 NSObject *o = nil; 29 for (o = [e nextObject] ; nil != o ; o = [e nextObject]) 30 { 31 if ([o isKindOfClass: self]) 32 { 33 [o release]; 34 } 35 } 36} 37 38/** 39 * If no clients have been active for some time, kill the speech server to 40 * conserve resources. 41 */ 42+ (void)exitIfUnneeded: (NSTimer*)sender 43{ 44 if (clients == 0) 45 { 46 exit(0); 47 } 48} 49 50- (id)initWithVoice: (NSString*)aVoice 51{ 52 clients++; 53 if (nil == (self = [super init])) 54 { 55 return nil; 56 } 57 [self setVoice: currentVoice]; 58 return self; 59} 60 61- (id)init 62{ 63 return [self initWithVoice: nil]; 64} 65 66- (NSString*)voice 67{ 68 return currentVoice; 69} 70 71- (id)delegate 72{ 73 return delegate; 74} 75 76- (void)setDelegate: (id)aDelegate 77{ 78 // Either -retain or -release can throw an exception due to DO. 79 NS_DURING 80 aDelegate = [aDelegate retain]; 81 NS_HANDLER 82 NS_ENDHANDLER 83 NS_DURING 84 [delegate release]; 85 NS_HANDLER 86 NS_ENDHANDLER 87 delegate = aDelegate; 88} 89 90- (void)setVoice: (NSString*)aVoice 91{ 92 if (nil == aVoice) 93 { 94 aVoice = [server defaultVoice]; 95 } 96 ASSIGN(currentVoice, aVoice); 97} 98 99- (BOOL)startSpeakingString: (NSString*)aString 100{ 101 [server setVoice: currentVoice]; 102 return [server startSpeakingString: aString notifyWhenDone: self]; 103} 104 105- (void)didFinishSpeaking: (BOOL)didFinish 106{ 107 // Throw the delegate away if it is throwing exceptions during 108 // notification. 109 NS_DURING 110 [delegate speechSynthesizer: self didFinishSpeaking: didFinish]; 111 NS_HANDLER 112 NS_DURING 113 id d = delegate; 114 delegate = nil; 115 [d release]; 116 NS_HANDLER 117 NS_ENDHANDLER 118 NS_ENDHANDLER 119} 120 121- (void)stopSpeaking 122{ 123 [server stopSpeaking]; 124} 125 126- (void)dealloc 127{ 128 clients--; 129 [currentVoice release]; 130 if (clients == 0) 131 { 132 [NSTimer scheduledTimerWithTimeInterval: 600 133 target: object_getClass(self) 134 selector: @selector(exitIfUnneeded:) 135 userInfo: nil 136 repeats: NO]; 137 } 138 [super dealloc]; 139} 140@end 141