source: trunk/Cocoa/Pester/Source/NJRVoicePopUpButton.m@ 578

Last change on this file since 578 was 364, checked in by Nicholas Riley, 17 years ago

English.lproj/Alarms.nib: Specify alternating row coloring in the nib,
now we're 10.4+.

English.lproj/InfoPlist.strings: Updated for 1.1b6.

English.lproj/Localizable.strings: Quote alarm message in pretty
description (used in tooltip). Change voice error now it no longer
incorporates OSStatus.

English.lproj/MainMenu.nib: Add speech prefs again; turn repetitions
field into a NJRValidatingField and hook up its delegate.

Info-Pester.plist: Updated for 1.1b6.

NJRHotKey.m: Switch to new Objective-C exception style.

NJRIntervalField.[hm]: Now a subclass of NJRValidatingField.

NJRTableDelegate.m: Get rid of our own tooltip support as NSTableView
now supports them (though with a minor visual glitch on the first
tooltip).

NJRTableView.[hm]: Remove tooltip support. Remove alternating row
coloring support.

NJRValidatingField.[hm]: Contains validation sheet stuff from
NJRIntervalField.

NJRVoicePopUpButton.[hm]: Switch to NSSpeechSynthesizer.

PSAlarm.m: Quote alarm message in pretty description (used in
tooltip). Fix repeating alarms not restoring as repeating if they
didn't expire while Pester was not running. No longer set timer on
Pester 1.0 alarm import, to help make importing atomic.

PSAlarmSetController.[hm]: Use NJRValidatingField for repetitions
field. Switch to new Objective-C exception style. Fix validation
issues on in/at changing. Temporary changes to restore speech support
and allow the sound popup to be removed entirely from the nib (rather
than being dragged out of the visible area, as it was in 1.1b5).
Changes for NSSpeechSynthesizer, which uses different voice names.

PSAlarms.m: Switch to new Objective-C exception style. Fix
duplication and error handling in Pester 1.0 alarm import, making
atomic.

PSAlarmsController.m: Use new tooltip support (since it's implemented
in the delegate rather than the data source, we have to proxy it).

PSAlerts.m: Wrap initialization in exception block so we don't leak.

PSApplication.m: Switch to new Objective-C exception style.

PSMediaAlert.m: Clamp repetitions at 1..99 so the user can't type an
invalid value, then quit and have it saved.

PSSpeechAlert.[hm]: Switch to NSSpeechSynthesizer. Throw an
intelligible exception if the voice is unavailable.

PSTimer.m: Switch to new Objective-C exception style.

Pester.xcodeproj: Remove VERSION generation; rename targets to be more
understandable.

Read Me.rtfd: Updated for 1.1b6.

SUSpeaker.[hm]: Gone in switch to NSSpeechSynthesizer.

VERSION: Gone - we use agvtool for everything now.

Updates/release-notes.html: Updated for 1.1b6.

Updates/updates.xml: Updated for 1.1b6.

package-Pester.sh: Use agvtool to get version. Atomically update
file on Web server to avoid partial downloads.

File size: 3.6 KB
Line 
1//
2// NJRVoicePopUpButton.m
3// Pester
4//
5// Created by Nicholas Riley on Sat Oct 26 2002.
6// Copyright (c) 2002 Nicholas Riley. All rights reserved.
7//
8
9#import "NJRVoicePopUpButton.h"
10
11@implementation NJRVoicePopUpButton
12
13- (void)_refreshVoiceList;
14{
15 NSMenu *menu;
16 NSMenuItem *item;
17 NSArray *voices = [NSSpeechSynthesizer availableVoices];
18
19 [self removeAllItems];
20 menu = [self menu];
21 [menu setAutoenablesItems: NO];
22 // XXX would be more elegant with surrogate support like my font popup menu
23 item = [menu addItemWithTitle: @"«unknown»" action: nil keyEquivalent: @""];
24 [item setEnabled: NO];
25 [menu addItem: [NSMenuItem separatorItem]];
26 if (voices == nil || [voices count] == 0) {
27 item = [menu addItemWithTitle: NSLocalizedString(@"Can't locate voices", "Voice popup menu item surrogate for voice list if no voices are found") action: nil keyEquivalent: @""];
28 [item setEnabled: NO];
29 } else {
30 NSEnumerator *e = [voices objectEnumerator];
31 NSString *voice;
32 while ( (voice = [e nextObject]) != nil) {
33 item = [menu addItemWithTitle:
34 [[NSSpeechSynthesizer attributesForVoice: voice] objectForKey: NSVoiceName]
35 action: @selector(_previewVoice) keyEquivalent: @""];
36 [item setRepresentedObject: voice];
37 [item setTarget: self];
38 }
39 }
40 if (_speaker == nil)
41 [self selectItemAtIndex: [menu indexOfItemWithRepresentedObject: [NSSpeechSynthesizer defaultVoice]]];
42}
43
44- (id)initWithFrame:(NSRect)frame;
45{
46 if ( (self = [super initWithFrame: frame]) != nil) {
47 [self _refreshVoiceList];
48 }
49 return self;
50}
51
52- (id)initWithCoder:(NSCoder *)coder;
53{
54 if ( (self = [super initWithCoder: coder]) != nil) {
55 [self _refreshVoiceList];
56 }
57 return self;
58}
59
60- (NSSpeechSynthesizer *)_speaker;
61{
62 if (_speaker == nil) _speaker = [[NSSpeechSynthesizer alloc] initWithVoice: nil];
63 return _speaker;
64}
65
66- (void)_invalidateVoiceSelection;
67{
68 [self _refreshVoiceList];
69 [self selectItemAtIndex: 0];
70}
71
72- (void)setVoice:(NSString *)voice;
73{
74 int voiceIdx = [self indexOfItemWithRepresentedObject: voice];
75 if (voiceIdx == -1) {
76 [self _invalidateVoiceSelection];
77 } else {
78 [self selectItemAtIndex: voiceIdx];
79 }
80}
81
82- (void)_previewVoice;
83{
84 NSString *voice = [[self selectedItem] representedObject];
85 NSString *previewString = nil;
86
87 [_speaker stopSpeaking];
88
89 if (![[self _speaker] setVoice: voice]) {
90 // XXX localize title
91 NSBeginAlertSheet(@"Voice not available", nil, nil, nil, [self window], nil, nil, nil, nil, NSLocalizedString(@"The voice '%@' you selected could not be used.", "Message displayed in alert sheet when -[NSSpeechSynthesizer setVoice:] returns an error"), [self titleOfSelectedItem]);
92 [self _invalidateVoiceSelection];
93 return;
94 }
95
96 if (_delegate != nil && [_delegate respondsToSelector: @selector(voicePopUpButton:previewStringForVoice:)]) {
97 previewString = [_delegate voicePopUpButton: self previewStringForVoice: voice];
98 }
99
100 if (previewString == nil)
101 previewString = [[NSSpeechSynthesizer attributesForVoice: voice] objectForKey: NSVoiceDemoText];
102
103 [_speaker startSpeakingString: previewString];
104}
105
106- (void)dealloc;
107{
108 [_speaker release];
109 [super dealloc];
110}
111
112- (IBAction)stopVoicePreview:(id)sender;
113{
114 [_speaker stopSpeaking];
115}
116
117- (void)setEnabled:(BOOL)flag;
118{
119 [super setEnabled: flag];
120 if (flag) ; // XXX [self stopVoicePreview: self]; // need to prohibit at startup
121 else [self stopVoicePreview: self];
122}
123
124- (void)setDelegate:(id)delegate;
125{
126 _delegate = delegate;
127}
128
129- (id)delegate;
130{
131 return _delegate;
132}
133
134@end
Note: See TracBrowser for help on using the repository browser.