|
|
1.1 root 1: /*
2: * You may freely copy, distribute and reuse the code in this example.
3: * NeXT disclaims any warranty of any kind, expressed or implied, as to
4: * its fitness for any particular use.
5: */
6:
7:
8: #import "SoundController.h"
9: #import "SaveToController.h"
10: #import "SoundDocument.h"
11: #import <soundkit/soundkit.h>
12: #import <appkit/Application.h>
13: #import <appkit/OpenPanel.h>
14: #import <appkit/Cursor.h>
15: #import <appkit/Button.h>
16: #import <appkit/Panel.h>
17: #import <appkit/publicWraps.h> /* for NXBeep() */
18: #import <sys/param.h> /* for MAXPATHLEN */
19: #import <string.h>
20: #import <objc/NXStringTable.h>
21:
22: static char pathname[1024];
23:
24: static BOOL getOpenPath(char *buf, char const *theType)
25: {
26: static id openPanel = nil;
27: char const *fileTypes[2] = {0,0};
28: int opr;
29:
30: if (!openPanel)
31: openPanel = [OpenPanel new];
32: if (theType && *theType)
33: fileTypes[0] = theType;
34: [NXApp setAutoupdate:NO];
35:
36: if (*buf)
37: opr = [openPanel runModalForDirectory:buf
38: file:NULL types:fileTypes];
39: else
40: opr = [openPanel runModalForDirectory:"/NextLibrary/Sounds"
41: file:"Basso.snd" types:fileTypes];
42: if (opr) {
43: strcpy(buf,[openPanel filename]);
44: [NXApp setAutoupdate:YES];
45: return YES;
46: } else {
47: [NXApp setAutoupdate:YES];
48: return NO;
49: }
50: }
51:
52:
53: static BOOL getSavePath(char *buf, char const *defaultPath, View *accessory)
54: {
55: static id savePanel = nil;
56: BOOL ok;
57: char dirName[1024], fileName[256];
58:
59: if (!savePanel) {
60: const char *const types[2] = {"snd", NULL};
61: savePanel = [SavePanel new];
62: [savePanel setRequiredFileType:types[0]];
63: }
64: [savePanel setAccessoryView:accessory];
65: [NXApp setAutoupdate:NO];
66: if (defaultPath && *defaultPath) {
67: char *p;
68: strcpy(dirName,defaultPath);
69: if (p = rindex(dirName,'/')) {
70: strcpy(fileName, p+1);
71: *p = '\0';
72: } else {
73: strcpy(fileName,defaultPath);
74: fileName[0] = '\0';
75: }
76: ok = [savePanel runModalForDirectory:dirName file:fileName];
77: } else
78: ok = [savePanel runModal];
79: [NXApp setAutoupdate:YES];
80: if (ok) {
81: strcpy(buf,[savePanel filename]);
82: return YES;
83: } else
84: return NO;
85: }
86:
87:
88: @implementation SoundController
89:
90: - init
91: {
92: [super init];
93: [controlPanel removeFromEventMask:(NX_KEYDOWNMASK|NX_KEYUPMASK)];
94: [controlPanel setFloatingPanel:YES];
95: return self;
96: }
97:
98: - appDidInit:sender
99: {
100: [self newSoundDoc:self]; /* User Interface guidelines recommend opening
101: a new document at launch time. We do this in
102: appDidInit: rather than init to make sure that
103: the stringTable has been unarchived */
104: return self;
105: }
106:
107: - info:sender
108: {
109: if (!infoPanel)
110: [NXApp loadNibSection:"InfoPanel.nib" owner:self];
111: [infoPanel orderFront:self];
112: return self;
113: }
114:
115: - newSoundDoc:sender
116: {
117: static char filenamebuf[MAXPATHLEN+1];
118: strcpy(filenamebuf, [[OpenPanel new] directory]);
119: /* doesn't instantiate a new OpenPanel
120: if one already exists */
121: strcat(filenamebuf,[stringTable valueForStringKey:"/UNTITLED"]);
122: [self setDocument:[[SoundDocument alloc] init]];
123: [currentDocument setFileName:filenamebuf];
124: return self;
125: }
126:
127:
128: - setDocument:aDocument
129: {
130: [self stop:nil];
131: currentDocument = aDocument;
132: [recordButton setEnabled:([currentDocument isRecordable]? YES : NO)];
133: [playButton setEnabled:YES];
134: [currentDocument setDelegate:self];
135: return self;
136: }
137:
138: - document
139: {
140: return currentDocument;
141: }
142:
143: - openFile:(char *)fileName
144: {
145: id newDocument;
146: newDocument = [[SoundDocument alloc] init];
147: [newDocument setFileName:fileName];
148: [newDocument load:nil];
149: [self setDocument:newDocument];
150: return self;
151: }
152:
153: - open:sender
154: {
155: if (getOpenPath(pathname,"snd"))
156: [self openFile:pathname];
157: return self;
158: }
159:
160: - saveAs:sender withAccessory:accessory
161: {
162: char pathname[1024];
163: id doc = currentDocument;
164: if (accessory)
165: [saveToController setSound:[doc sound]];
166: if (doc && getSavePath(pathname,[doc fileName],accessory)) {
167: if (accessory)
168: [doc saveToFormat:[saveToController soundTemplate]
169: fileName: pathname];
170: else {
171: [doc setFileName:pathname];
172: [doc save:sender];
173: }
174: }
175: return self;
176: }
177:
178: - saveAs:sender
179: {
180: return [self saveAs:sender withAccessory:nil];
181: }
182:
183: - saveTo:sender
184: {
185: return [self saveAs:sender withAccessory:saveToAccessoryView];
186: }
187:
188: - save:sender
189: {
190: if (currentDocument) {
191: if ([currentDocument fileName]
192: && strcmp(strrchr([currentDocument fileName],'/'),"/UNTITLED"))
193: [currentDocument save:sender];
194: else
195: [self saveAs:sender];
196: }
197: return self;
198: }
199:
200: - revertToSaved:sender
201: {
202: if (currentDocument)
203: [currentDocument revertToSaved:sender];
204: return self;
205: }
206:
207: - play:sender
208: {
209: if (![currentDocument isPlayable]) {
210: NXBeep();
211: return nil;
212: }
213: if (currentDocument) {
214: [playButton setEnabled:NO];
215: [recordButton setEnabled:NO];
216: [stopButton setEnabled:YES];
217: [pauseButton setState:0];
218: [currentDocument play:sender];
219: }
220: return self;
221: }
222:
223: - willPlay:sender
224: {
225: [meter setSound:[sender soundBeingProcessed]];
226: [meter run:self];
227: return self;
228: }
229:
230: - didPlay:sender
231: {
232: [playButton setState:0];
233: [playButton setEnabled:YES];
234: [recordButton setState:0];
235: [recordButton setEnabled:YES];
236: [pauseButton setState:0];
237: [meter stop:self];
238: return self;
239: }
240:
241: - stop:sender
242: {
243: if (currentDocument)
244: [currentDocument stop:sender];
245: [playButton setState:0];
246: [playButton setEnabled:YES];
247: [recordButton setState:0];
248: [recordButton setEnabled:YES];
249: [pauseButton setState:0];
250: return self;
251: }
252:
253: - pause:sender
254: {
255: if (!currentDocument || (![playButton state] && ![recordButton state])) {
256: [pauseButton setState:0];
257: return self;
258: } else if ([pauseButton state])
259: [currentDocument pause:self];
260: else
261: [currentDocument resume:self];
262: return self;
263: }
264:
265: - record:sender
266: {
267: if (currentDocument) {
268: [recordButton setEnabled:NO];
269: [playButton setEnabled:NO];
270: [stopButton setEnabled:YES];
271: [currentDocument record:sender];
272: }
273: return self;
274: }
275:
276: - willRecord:sender
277: {
278: [meter setSound:[sender soundBeingProcessed]];
279: [meter run:self];
280: return self;
281: }
282:
283: - didRecord:sender
284: {
285: [playButton setState:0];
286: [playButton setEnabled:YES];
287: [recordButton setState:0];
288: [recordButton setEnabled:YES];
289: [pauseButton setState:0];
290: [meter stop:self];
291: return self;
292: }
293:
294: - soundDidChange:sender
295: {
296: if (currentDocument)
297: [currentDocument touch];
298: return self;
299: }
300:
301: - hadError:sender
302: {
303: int err = [[sender soundBeingProcessed] processingError];
304:
305: if ([playButton state])
306: NXRunAlertPanel([stringTable valueForStringKey:"Play error"],
307: SNDSoundError(err),
308: [stringTable valueForStringKey:"OK"],
309: NULL,NULL);
310: else if ([recordButton state])
311: NXRunAlertPanel([stringTable valueForStringKey:"Record error"],
312: SNDSoundError(err),
313: [stringTable valueForStringKey:"OK"],
314: NULL,NULL);
315: return [self stop:self];
316: }
317:
318: - appDidHide:sender
319: {
320: [self stop:nil];
321: return self;
322: }
323:
324: - appDidBecomeActive:sender
325: {
326: [controlPanel orderFront:nil];
327: return self;
328: }
329:
330: - stringTable
331: {
332: return stringTable;
333: }
334:
335: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.