// // NJRVoicePopUpButton.m // Pester // // Created by Nicholas Riley on Sat Oct 26 2002. // Copyright (c) 2002 Nicholas Riley. All rights reserved. // #import "NJRVoicePopUpButton.h" @implementation NJRVoicePopUpButton - (void)_refreshVoiceList; { NSMenu *menu; NSMenuItem *item; NSArray *voiceNames = [SUSpeaker voiceNames]; [self removeAllItems]; menu = [self menu]; [menu setAutoenablesItems: NO]; // XXX would be more elegant with surrogate support like my font popup menu item = [menu addItemWithTitle: @"ÇunknownÈ" action: nil keyEquivalent: @""]; [item setEnabled: NO]; [menu addItem: [NSMenuItem separatorItem]]; if (voiceNames == nil || [voiceNames count] == 0) { item = [menu addItemWithTitle: NSLocalizedString(@"Can't locate voices", "Voice popup menu item surrogate for voice list if no voices are found") action: nil keyEquivalent: @""]; [item setEnabled: NO]; } else { NSEnumerator *e = [voiceNames objectEnumerator]; NSString *voiceName; while ( (voiceName = [e nextObject]) != nil) { item = [menu addItemWithTitle: voiceName action: @selector(_previewVoice) keyEquivalent: @""]; [item setTarget: self]; } } if (_speaker == nil) [self selectItemWithTitle: [SUSpeaker defaultVoice]]; } - (id)initWithFrame:(NSRect)frame; { if ( (self = [super initWithFrame: frame]) != nil) { [self _refreshVoiceList]; } return self; } - (id)initWithCoder:(NSCoder *)coder; { if ( (self = [super initWithCoder: coder]) != nil) { [self _refreshVoiceList]; } return self; } - (SUSpeaker *)_speaker; { if (_speaker == nil) _speaker = [[SUSpeaker alloc] init]; return _speaker; } - (void)_invalidateVoiceSelection; { [self _refreshVoiceList]; [self selectItemAtIndex: 0]; } - (void)setVoice:(NSString *)voice; { int voiceIdx = [self indexOfItemWithTitle: voice]; if (voiceIdx == -1) { [self _invalidateVoiceSelection]; } else { [self selectItemAtIndex: voiceIdx]; } } - (void)_previewVoice; { NSString *voiceName = [self titleOfSelectedItem]; NSString *previewString = nil; VoiceSpec voice; OSStatus err = noErr; VoiceDescription info; short voiceIndex = [[SUSpeaker voiceNames] indexOfObject: voiceName] + 1; [_speaker stopSpeaking]; if ( (err = GetIndVoice(voiceIndex, &voice)) != noErr) { NSBeginAlertSheet(@"Voice not available", nil, nil, nil, [self window], nil, nil, nil, nil, NSLocalizedString(@"The voice '%@' you selected could not be used. An error of type %ld occurred while attempting to retrieve voice information.", "Message displayed in alert sheet when GetIndVoice returns an error"), voiceName, err); [self _invalidateVoiceSelection]; return; } if (_delegate != nil && [_delegate respondsToSelector: @selector(voicePopUpButton:previewStringForVoice:)]) { previewString = [_delegate voicePopUpButton: self previewStringForVoice: voiceName]; } if (previewString == nil) { err = GetVoiceDescription(&voice, &info, sizeof(info)); if (err != noErr || info.comment[0] == 0) previewString = voiceName; else { previewString = (NSString *)CFStringCreateWithPascalString(NULL, info.comment, kCFStringEncodingMacRoman); [previewString autorelease]; } } [[self _speaker] setVoice: voiceIndex]; [_speaker speakText: previewString]; } - (void)dealloc; { [_speaker release]; [super dealloc]; } - (IBAction)stopVoicePreview:(id)sender; { [_speaker stopSpeaking]; } - (void)setEnabled:(BOOL)flag; { [super setEnabled: flag]; if (flag) ; // XXX [self stopVoicePreview: self]; // need to prohibit at startup else [self stopVoicePreview: self]; } - (void)setDelegate:(id)delegate; { _delegate = delegate; } - (id)delegate; { return _delegate; } @end