Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/Classes/RecordPanelController.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 169 - (show annotations) (download)
Sun Oct 27 01:45:31 2019 UTC (4 years, 5 months ago) by toshinagata1964
File size: 17415 byte(s)
Behavior of the split view of the graphic window is fixed
1 /*
2 Copyright 2010-2012 Toshi Nagata. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 */
13
14 #import "RecordPanelController.h"
15 #import "MyDocument.h"
16 #import "MDHeaders.h"
17 #import "MyMIDISequence.h"
18 #import "MyAppController.h"
19
20 @implementation RecordPanelController
21
22 - (id)initWithDocument: (MyDocument *)document audio: (BOOL)audioFlag
23 {
24 self = [super initWithWindowNibName: (audioFlag ? @"AudioRecordPanel" : @"RecordPanel")];
25 myDocument = [document retain];
26 isAudio = audioFlag;
27 return self;
28 }
29
30 - (void)dealloc
31 {
32 if (calib != NULL)
33 MDCalibratorRelease(calib);
34 [myDocument release];
35 [info release];
36 [[NSNotificationCenter defaultCenter] removeObserver:self];
37 [super dealloc];
38 }
39
40 static id
41 sAllowedExtensionsForTag(int tag)
42 {
43 id obj;
44 if (tag == 1) {
45 obj = [NSArray arrayWithObjects:@"wav", nil];
46 } else if (tag == 0) {
47 obj = [NSArray arrayWithObjects:@"aiff", @"aif", nil];
48 } else {
49 obj = nil;
50 }
51 return obj;
52 }
53
54 - (void)updateDisplay
55 {
56 MyMIDISequence *seq = [myDocument myMIDISequence];
57 NSString *s;
58 int32_t bar, beat, tick;
59 int ival;
60 MDTickType theTick;
61
62 s = [info valueForKey: (isAudio ? MyRecordingInfoSourceAudioDeviceKey : MyRecordingInfoSourceDeviceKey)];
63 if (s == nil) {
64 [sourceDevicePopUp selectItemAtIndex: 0];
65 } else {
66 [sourceDevicePopUp selectItemWithTitle: s];
67 }
68
69 if (!isAudio) {
70 [destinationDevicePopUp selectItemWithTitle: [info valueForKey: MyRecordingInfoDestinationDeviceKey]];
71 ival = [[info valueForKey: MyRecordingInfoTargetTrackKey] intValue];
72 if (ival > 0 && ival < [seq trackCount]) {
73 [destinationTrackPopUp selectItemAtIndex: ival - 1];
74 } else {
75 [destinationTrackPopUp selectItemAtIndex: [destinationTrackPopUp numberOfItems] - 1];
76 }
77 ival = [[info valueForKey: MyRecordingInfoDestinationChannelKey] intValue];
78 [midiChannelPopUp selectItemAtIndex: ival];
79 ival = [[info valueForKey: MyRecordingInfoBarBeatFlagKey] intValue];
80 [barBeatPopUp selectItemAtIndex: (ival ? 0 : 1)];
81 ival = [[info valueForKey: MyRecordingInfoRecordingModeKey] intValue];
82 [modePopUp selectItemAtIndex: ival];
83 if (ival == 0) {
84 [barBeatPopUp setEnabled: YES];
85 [barBeatText setEnabled: YES];
86 } else {
87 [barBeatPopUp setEnabled: NO];
88 [barBeatText setEnabled: NO];
89 }
90 ival = [[info valueForKey: MyRecordingInfoMIDITransposeKey] intValue];
91 [transposeOctavePopUp selectItemAtIndex:8 - ((ival + 48) / 12)];
92 [transposeNotePopUp selectItemAtIndex:((ival + 48) % 12)];
93 }
94
95 theTick = (MDTickType)[[info valueForKey: MyRecordingInfoStartTickKey] doubleValue];
96 if (theTick >= 0 && theTick < kMDMaxTick) {
97 MDCalibratorTickToMeasure(calib, theTick, &bar, &beat, &tick);
98 s = [NSString stringWithFormat: @"%d:%d:%d", (int)bar, (int)beat, (int)tick];
99 } else {
100 s = @"----:--:----";
101 }
102 [startTickText setStringValue: s];
103
104 theTick = (MDTickType)[[info valueForKey: MyRecordingInfoStopTickKey] doubleValue];
105 if (theTick > 0 && theTick < kMDMaxTick) {
106 MDCalibratorTickToMeasure(calib, theTick, &bar, &beat, &tick);
107 s = [NSString stringWithFormat: @"%d:%d:%d", (int)bar, (int)beat, (int)tick];
108 } else {
109 s = @"----:--:----";
110 }
111 [stopTickText setStringValue: s];
112
113 ival = [[info valueForKey: MyRecordingInfoStopFlagKey] intValue];
114 [stopTickCheckbox setState: ival];
115 if (ival) {
116 [stopTickText setEnabled: YES];
117 } else {
118 [stopTickText setEnabled: NO];
119 }
120
121 ival = [[info valueForKey: MyRecordingInfoCountOffNumberKey] intValue];
122 [barBeatText setIntValue: ival];
123
124 ival = [[info valueForKey: MyRecordingInfoReplaceFlagKey] intValue];
125 [overdubRadioMatrix selectCellWithTag: ival];
126
127 if (isAudio) {
128 NSString *locationText, *nameText;
129 [audioSampleRatePopUp selectItemWithTitle: [NSString stringWithFormat: @"%.0f", [[info valueForKey: MyRecordingInfoAudioBitRateKey] floatValue]]];
130 ival = [[info valueForKey: MyRecordingInfoAudioChannelFormatKey] intValue];
131 [audioChannelsPopUp selectItemAtIndex: ival];
132 ival = [[info valueForKey: MyRecordingInfoAudioRecordingFormatKey] intValue];
133 [audioFormatPopUp selectItemAtIndex: ival];
134 locationText = [info valueForKey: MyRecordingInfoFolderNameKey];
135 if (locationText == nil) {
136 locationText = [[[myDocument fileURL] path] stringByDeletingLastPathComponent];
137 if (locationText == nil)
138 locationText = @"~/Music";
139 }
140 nameText = [info valueForKey: MyRecordingInfoFileNameKey];
141 if (nameText == nil)
142 nameText = @"";
143 [audioFileLocationText setStringValue: locationText];
144 [audioFileNameText setStringValue: nameText];
145 if ([locationText length] > 0 && [nameText length] > 0)
146 [startRecordingButton setEnabled: YES];
147 else
148 [startRecordingButton setEnabled: NO];
149 }
150 }
151
152 /*
153 - (void)timerCallback: (NSTimer *)timer
154 {
155 if (isAudio) {
156 float volume, ampLeft, ampRight, peakLeft, peakRight;
157 if (MDAudioGetInputVolumeAndAmplitudes(&volume, &ampLeft, &ampRight, &peakLeft, &peakRight) == kMDNoError) {
158 [audioVolumeSlider setFloatValue: volume * 100.0];
159 [audioLeftLevel setFloatValue: ampLeft * 100.0];
160 [audioRightLevel setFloatValue: ampRight * 100.0];
161 NSLog(@"ampLeft = %f, ampRight = %f", ampLeft, ampRight);
162 }
163 }
164 }
165
166 - (void)stopTimer
167 {
168 if (timer != nil) {
169 [timer invalidate];
170 [timer release];
171 timer = nil;
172 }
173 }
174 */
175
176 - (void)reloadMIDIDeviceInfo
177 {
178 int i, n;
179 NSMenu *menu;
180 NSString *str;
181 char name[64];
182 MyMIDISequence *seq = [myDocument myMIDISequence];
183
184 // Update the device information before starting the dialog
185 // This is unnecessary: device information is always updated whenever
186 // Audio/MIDI setup changes
187 // MDPlayerReloadDeviceInformation();
188
189 // Initialize device popups (set device names and tags)
190 [sourceDevicePopUp removeAllItems];
191 menu = [sourceDevicePopUp menu];
192 [[menu addItemWithTitle: @"Any MIDI device" action: nil keyEquivalent: @""] setTag: 0];
193 n = MDPlayerGetNumberOfSources();
194 for (i = 1; i <= n; i++) {
195 id item;
196 MDPlayerGetSourceName(i - 1, name, sizeof name);
197 item = [menu addItemWithTitle:@"X" action: nil keyEquivalent: @""];
198 str = [NSString stringWithUTF8String:name];
199 [item setTitle:str];
200 [item setTag:i];
201 }
202
203 [destinationDevicePopUp removeAllItems];
204 menu = [destinationDevicePopUp menu];
205 n = MDPlayerGetNumberOfDestinations();
206 for (i = 0; i <= n; i++) {
207 if (i == 0)
208 strcpy(name, "(none)");
209 else
210 MDPlayerGetDestinationName(i - 1, name, sizeof name);
211 [[menu addItemWithTitle: [NSString stringWithUTF8String: name] action: nil keyEquivalent: @""] setTag: i];
212 }
213
214 // Add destinations for existing tracks (which may not be online now)
215 n = [seq trackCount];
216 for (i = 1; i < n; i++) {
217 NSString *s = [seq deviceName: i];
218 if (s == nil || [s isEqualToString: @""])
219 continue;
220 if (s != nil && [destinationDevicePopUp indexOfItemWithTitle: s] < 0)
221 [[menu addItemWithTitle: s action: nil keyEquivalent: @""] setTag: 10000 + i];
222 }
223
224 // Initialize track popup
225 [destinationTrackPopUp removeAllItems];
226 menu = [destinationTrackPopUp menu];
227 n = [[myDocument myMIDISequence] trackCount];
228 for (i = 1; i < n; i++) {
229 [[menu addItemWithTitle: [NSString stringWithFormat: @"%d: %@", i, [[myDocument myMIDISequence] trackName: i]] action: nil keyEquivalent: @""] setTag: i];
230 }
231 [menu addItem: [NSMenuItem separatorItem]];
232 [[menu addItemWithTitle: @"Create new track" action: nil keyEquivalent: @""] setTag: -1];
233 }
234
235 - (void)reloadInfoFromDocument
236 {
237 NSString *str1, *str2;
238 id obj;
239 int tag;
240 MyMIDISequence *seq = [myDocument myMIDISequence];
241
242 // In case window is not yet visible
243 [self window];
244
245 // Current recordingInfo
246 info = [[NSMutableDictionary dictionaryWithDictionary: [seq recordingInfo]] retain];
247
248 if (!isAudio) {
249 [self reloadMIDIDeviceInfo];
250 }
251
252 // Initialize the calibrator
253 {
254 MDSequence *mds = [seq mySequence];
255 MDTrack *track = MDSequenceGetTrack(mds, 0);
256 if (calib != NULL)
257 MDCalibratorRelease(calib);
258 // Tempo is not necessary (only ticks are handled here)
259 calib = MDCalibratorNew(mds, track, kMDEventTimeSignature, -1);
260 }
261
262 [info setValue: [NSNumber numberWithBool: isAudio] forKey: MyRecordingInfoIsAudioKey];
263
264 str1 = [[myDocument fileURL] path];
265 str2 = [info valueForKey: MyRecordingInfoFileNameKey];
266 obj = [info valueForKey:MyRecordingInfoAudioRecordingFormatKey];
267 tag = (obj == nil ? 0 : [obj intValue]);
268 obj = sAllowedExtensionsForTag(tag);
269 if (str2 == nil && str1 != nil) {
270 str2 = [[str1 lastPathComponent] stringByDeletingPathExtension];
271 if (obj != nil)
272 str2 = [str2 stringByAppendingPathExtension:[obj objectAtIndex:0]];
273 [info setValue:str2 forKey:MyRecordingInfoFileNameKey];
274 }
275 str2 = [info valueForKey:MyRecordingInfoFolderNameKey];
276 if (str2 == nil && str1 != nil) {
277 str2 = [str1 stringByDeletingLastPathComponent];
278 [info setValue:str2 forKey:MyRecordingInfoFolderNameKey];
279 }
280
281 [self updateDisplay];
282 }
283
284 - (void)saveInfoToDocument
285 {
286 // NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
287 MyMIDISequence *seq = [myDocument myMIDISequence];
288 [seq setRecordingInfo: info];
289 /* [def setValue:[[metronomeDevicePopUp selectedItem] title] forKey:MyRecordingInfoMetronomeDeviceKey];
290 [def setValue:[NSNumber numberWithInt:[metronomeChannelPopUp indexOfSelectedItem]] forKey:MyRecordingInfoMetronomeChannelKey]; */
291 }
292
293 - (void)midiSetupDidChange:(NSNotification *)aNotification
294 {
295 [self reloadMIDIDeviceInfo];
296 [self updateDisplay];
297 }
298
299 - (void)windowDidLoad
300 {
301 [[NSNotificationCenter defaultCenter]
302 addObserver:self
303 selector:@selector(midiSetupDidChange:)
304 name:MyAppControllerMIDISetupDidChangeNotification
305 object:[NSApp delegate]];
306 }
307
308 //- (void)beginSheetForWindow: (NSWindow *)parentWindow invokeStopModalWhenDone: (BOOL)flag
309 //{
310 // NSWindow *window = [self window];
311 // [self reloadInfo];
312 // [self updateDisplay];
313 // stopModalFlag = flag;
314 // [[NSApplication sharedApplication] beginSheet: window
315 // modalForWindow: parentWindow
316 // modalDelegate: self
317 // didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
318 // contextInfo: nil];
319 //}
320
321 - (IBAction)cancelButtonPressed: (id)sender
322 {
323 editingText = nil;
324 [[NSApplication sharedApplication] endSheet: [self window] returnCode: 0];
325 }
326
327 - (IBAction)myPopUpAction: (id)sender
328 {
329 id item;
330 int tag, ch;
331 int32_t dev;
332 NSString *str;
333 MyMIDISequence *seq = [myDocument myMIDISequence];
334
335 item = [sender selectedItem];
336 if (item == nil)
337 return;
338 tag = (int)[item tag];
339 if (sender == sourceDevicePopUp) {
340 str = [item title];
341 if (isAudio) {
342 // [info setValue: str forKey: MyRecordingInfoSourceAudioDeviceKey];
343 // MDAudioSelectInOutDeviceAtIndices([item tag], -1);
344 } else {
345 [info setValue: (tag == 0 ? nil : str) forKey: MyRecordingInfoSourceDeviceKey];
346 }
347 } else if (sender == destinationDevicePopUp) {
348 str = [item title];
349 if (isAudio) {
350 // [info setValue: str forKey: MyRecordingInfoDestinationAudioDeviceKey];
351 // MDAudioSelectInOutDeviceAtIndices(-1, [item tag]);
352 } else {
353 [info setValue: str forKey: MyRecordingInfoDestinationDeviceKey];
354 dev = MDPlayerGetDestinationNumberFromName([str UTF8String]);
355 ch = 0;
356 if (dev >= 0) {
357 item = [midiChannelPopUp selectedItem];
358 if (item != nil)
359 ch = (int)[item tag] - 1;
360 }
361 MDPlayerSetMIDIThruDeviceAndChannel(dev, ch);
362 }
363 } else if (sender == midiChannelPopUp) {
364 [info setValue: [NSNumber numberWithInt: tag - 1] forKey: MyRecordingInfoDestinationChannelKey];
365 if (!isAudio) {
366 item = [destinationDevicePopUp selectedItem];
367 if (item != nil) {
368 str = [item title];
369 if (str != nil) {
370 dev = MDPlayerGetDestinationNumberFromName([str UTF8String]);
371 if (dev >= 0)
372 MDPlayerSetMIDIThruDeviceAndChannel(dev, tag - 1);
373 }
374 }
375 }
376 } else if (sender == destinationTrackPopUp) {
377
378 [info setValue: [NSNumber numberWithInt: (tag > 0 ? tag : -1)] forKey: MyRecordingInfoTargetTrackKey];
379 // Also modify destination device and channel if necessary
380 if (tag > 0) {
381 str = [seq deviceName: tag];
382 if (str != nil && ![str isEqualToString: @""]) {
383 [info setValue: str forKey: MyRecordingInfoDestinationDeviceKey];
384 }
385 ch = [seq trackChannel: tag];
386 if (ch >= 0 && ch < 16)
387 [info setValue: [NSNumber numberWithInt: ch] forKey: MyRecordingInfoDestinationChannelKey];
388 }
389 } else if (sender == modePopUp) {
390 [info setValue: [NSNumber numberWithInt: tag] forKey: MyRecordingInfoRecordingModeKey];
391 } else if (sender == barBeatPopUp) {
392 [info setValue: [NSNumber numberWithBool: (tag == 0)] forKey: MyRecordingInfoBarBeatFlagKey];
393 } else if (sender == transposeOctavePopUp || sender == transposeNotePopUp) {
394 tag = (4 - (int)[transposeOctavePopUp indexOfSelectedItem]) * 12;
395 tag += [transposeNotePopUp indexOfSelectedItem];
396 [info setValue: [NSNumber numberWithInt: tag] forKey: MyRecordingInfoMIDITransposeKey];
397 MDPlayerSetMIDIThruTranspose(tag);
398 } else if (sender == audioFormatPopUp) {
399 [info setValue: [NSNumber numberWithInt: tag] forKey: MyRecordingInfoAudioRecordingFormatKey];
400 } else if (sender == audioSampleRatePopUp) {
401 float fval = [[sender titleOfSelectedItem] floatValue];
402 [info setValue: [NSNumber numberWithFloat: fval] forKey: MyRecordingInfoAudioBitRateKey];
403 } else if (sender == audioChannelsPopUp) {
404 [info setValue: [NSNumber numberWithInt: tag] forKey: MyRecordingInfoAudioChannelFormatKey];
405 }
406 [self updateDisplay];
407 }
408
409 - (IBAction)startButtonPressed: (id)sender
410 {
411 if (editingText != nil)
412 [editingText sendAction:[editingText action] to:[editingText target]];
413 [[NSApplication sharedApplication] endSheet: [self window] returnCode: 1];
414 }
415
416 - (IBAction)barBeatTextChanged:(id)sender
417 {
418 int val = [sender intValue];
419 [info setValue: [NSNumber numberWithInt: val] forKey: MyRecordingInfoCountOffNumberKey];
420 [self updateDisplay];
421 }
422
423 - (IBAction)overdubRadioChecked:(id)sender
424 {
425 int tag = (int)[[sender selectedCell] tag];
426 [info setValue: [NSNumber numberWithBool: tag] forKey: MyRecordingInfoReplaceFlagKey];
427 [self updateDisplay];
428 }
429
430 - (IBAction)stopCheckboxClicked:(id)sender
431 {
432 int val = ([sender state] != NSOffState);
433 [info setValue: [NSNumber numberWithBool: val] forKey: MyRecordingInfoStopFlagKey];
434 [self updateDisplay];
435 }
436
437 /*
438 - (IBAction)playThruCheckboxClicked: (id)sender
439 {
440 int val = ([sender state] != NSOffState);
441 [info setValue: [NSNumber numberWithBool: val] forKey: MyRecordingInfoAudioPlayThroughKey];
442 MDAudioEnablePlayThru(val);
443 [self updateDisplay];
444 }
445 */
446
447 - (IBAction)tickTextChanged:(id)sender
448 {
449 int32_t bar, beat, tick;
450 MDTickType mdTick;
451 const char *s;
452 s = [[sender stringValue] UTF8String];
453 if (MDEventParseTickString(s, &bar, &beat, &tick) == 3) {
454 mdTick = MDCalibratorMeasureToTick(calib, bar, beat, tick);
455 [info setValue: [NSNumber numberWithDouble: mdTick] forKey: (sender == startTickText ? MyRecordingInfoStartTickKey : MyRecordingInfoStopTickKey)];
456 }
457 [self updateDisplay];
458 }
459
460 - (IBAction)chooseDestinationFile:(id)sender
461 {
462 NSSavePanel *panel = [NSSavePanel savePanel];
463 NSString *filename, *foldername;
464 id obj;
465 int tag;
466 filename = [info valueForKey: MyRecordingInfoFileNameKey];
467 foldername = [info valueForKey: MyRecordingInfoFolderNameKey];
468 obj = [info valueForKey:MyRecordingInfoAudioRecordingFormatKey];
469 tag = (obj == nil ? 0 : [obj intValue]);
470 obj = sAllowedExtensionsForTag(tag);
471 if (obj)
472 [panel setAllowedFileTypes:obj];
473 if (filename == nil) {
474 NSString *ext = (obj != nil ? [obj objectAtIndex:0] : @"");
475 filename = [NSString stringWithFormat: @"untitled.%@", ext];
476 }
477 if (foldername == nil)
478 foldername = @"~/Music";
479
480 [panel setDirectoryURL: [NSURL fileURLWithPath:[foldername stringByExpandingTildeInPath]]];
481 [panel setNameFieldStringValue:filename];
482 if ([panel runModal] == NSFileHandlingPanelOKButton) {
483 foldername = [[[panel directoryURL] path] stringByAbbreviatingWithTildeInPath];
484 filename = [[[panel URL] path] lastPathComponent];
485 [info setValue: foldername forKey: MyRecordingInfoFolderNameKey];
486 [info setValue: filename forKey: MyRecordingInfoFileNameKey];
487 }
488 [self updateDisplay];
489 }
490
491 - (IBAction)destinationTextChanged:(id)sender
492 {
493 NSString *name;
494 name = [sender stringValue];
495 if (sender == audioFileLocationText) {
496 // TODO: check the existence of the directory
497 name = [name stringByAbbreviatingWithTildeInPath];
498 [info setValue: name forKey: MyRecordingInfoFolderNameKey];
499 } else {
500 [info setValue: name forKey: MyRecordingInfoFileNameKey];
501 }
502 [self updateDisplay];
503 }
504
505 - (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor
506 {
507 editingText = (NSTextField *)control;
508 return YES;
509 }
510
511 - (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
512 {
513 editingText = nil;
514 return YES;
515 }
516
517 /*
518 - (IBAction)volumeSliderMoved:(id)sender
519 {
520 if (isAudio) {
521 MDAudioSetInputVolume([sender floatValue] * 0.01);
522 }
523 }
524 */
525
526 @end

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26