Audio recording in the Cocoa frontend
This commit is contained in:
parent
6055092249
commit
cdfcc4ca2d
51
Cocoa/AudioRecordingAccessoryView.xib
Normal file
51
Cocoa/AudioRecordingAccessoryView.xib
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14868" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||||
|
<dependencies>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14868"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<objects>
|
||||||
|
<customObject id="-2" userLabel="File's Owner" customClass="Document">
|
||||||
|
<connections>
|
||||||
|
<outlet property="audioFormatButton" destination="knX-AW-zt5" id="fKt-eI-H0y"/>
|
||||||
|
<outlet property="audioRecordingAccessoryView" destination="c22-O7-iKe" id="XD8-Gi-qOC"/>
|
||||||
|
</connections>
|
||||||
|
</customObject>
|
||||||
|
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||||
|
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||||
|
<customView id="c22-O7-iKe">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="354" height="36"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Atq-RE-328">
|
||||||
|
<rect key="frame" x="18" y="10" width="56" height="16"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Format:" id="dso-NS-JlD">
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</textFieldCell>
|
||||||
|
</textField>
|
||||||
|
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="knX-AW-zt5">
|
||||||
|
<rect key="frame" x="81" y="4" width="256" height="25"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<popUpButtonCell key="cell" type="push" title="Apple AIFF" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="1" imageScaling="proportionallyDown" inset="2" selectedItem="M3Z-UN-VKZ" id="tLM-Di-Dy3">
|
||||||
|
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
<menu key="menu" id="gqn-SL-AA5">
|
||||||
|
<items>
|
||||||
|
<menuItem title="Apple AIFF" state="on" tag="1" id="M3Z-UN-VKZ"/>
|
||||||
|
<menuItem title="RIFF WAVE" tag="2" id="zA0-Np-4XD"/>
|
||||||
|
<menuItem title="Raw PCM (Stereo 96KHz, 16-bit LE)" id="r9J-4k-XH5"/>
|
||||||
|
</items>
|
||||||
|
</menu>
|
||||||
|
</popUpButtonCell>
|
||||||
|
<connections>
|
||||||
|
<action selector="audioFormatChanged:" target="-2" id="I1k-d9-afp"/>
|
||||||
|
</connections>
|
||||||
|
</popUpButton>
|
||||||
|
</subviews>
|
||||||
|
<point key="canvasLocation" x="75" y="19"/>
|
||||||
|
</customView>
|
||||||
|
</objects>
|
||||||
|
</document>
|
@ -56,6 +56,8 @@
|
|||||||
@property (readonly) GB_oam_info_t *oamInfo;
|
@property (readonly) GB_oam_info_t *oamInfo;
|
||||||
@property uint8_t oamCount;
|
@property uint8_t oamCount;
|
||||||
@property uint8_t oamHeight;
|
@property uint8_t oamHeight;
|
||||||
|
@property (strong) IBOutlet NSView *audioRecordingAccessoryView;
|
||||||
|
@property (strong) IBOutlet NSPopUpButton *audioFormatButton;
|
||||||
|
|
||||||
+ (NSImage *) imageFromData:(NSData *)data width:(NSUInteger) width height:(NSUInteger) height scale:(double) scale;
|
+ (NSImage *) imageFromData:(NSData *)data width:(NSUInteger) width height:(NSUInteger) height scale:(double) scale;
|
||||||
-(uint8_t) readMemory:(uint16_t) addr;
|
-(uint8_t) readMemory:(uint16_t) addr;
|
||||||
|
@ -101,6 +101,9 @@ enum model {
|
|||||||
Document *slave;
|
Document *slave;
|
||||||
signed linkOffset;
|
signed linkOffset;
|
||||||
bool linkCableBit;
|
bool linkCableBit;
|
||||||
|
|
||||||
|
NSSavePanel *_audioSavePanel;
|
||||||
|
bool _isRecordingAudio;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property GBAudioClient *audioClient;
|
@property GBAudioClient *audioClient;
|
||||||
@ -1134,7 +1137,7 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
|
|||||||
return !GB_debugger_is_stopped(&gb);
|
return !GB_debugger_is_stopped(&gb);
|
||||||
}
|
}
|
||||||
else if ([anItem action] == @selector(reset:) && anItem.tag != MODEL_NONE) {
|
else if ([anItem action] == @selector(reset:) && anItem.tag != MODEL_NONE) {
|
||||||
[(NSMenuItem*)anItem setState:anItem.tag == current_model];
|
[(NSMenuItem *)anItem setState:anItem.tag == current_model];
|
||||||
}
|
}
|
||||||
else if ([anItem action] == @selector(interrupt:)) {
|
else if ([anItem action] == @selector(interrupt:)) {
|
||||||
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"DeveloperMode"]) {
|
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"DeveloperMode"]) {
|
||||||
@ -1142,26 +1145,29 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ([anItem action] == @selector(disconnectAllAccessories:)) {
|
else if ([anItem action] == @selector(disconnectAllAccessories:)) {
|
||||||
[(NSMenuItem*)anItem setState:accessory == GBAccessoryNone];
|
[(NSMenuItem *)anItem setState:accessory == GBAccessoryNone];
|
||||||
}
|
}
|
||||||
else if ([anItem action] == @selector(connectPrinter:)) {
|
else if ([anItem action] == @selector(connectPrinter:)) {
|
||||||
[(NSMenuItem*)anItem setState:accessory == GBAccessoryPrinter];
|
[(NSMenuItem *)anItem setState:accessory == GBAccessoryPrinter];
|
||||||
}
|
}
|
||||||
else if ([anItem action] == @selector(connectWorkboy:)) {
|
else if ([anItem action] == @selector(connectWorkboy:)) {
|
||||||
[(NSMenuItem*)anItem setState:accessory == GBAccessoryWorkboy];
|
[(NSMenuItem *)anItem setState:accessory == GBAccessoryWorkboy];
|
||||||
}
|
}
|
||||||
else if ([anItem action] == @selector(connectLinkCable:)) {
|
else if ([anItem action] == @selector(connectLinkCable:)) {
|
||||||
[(NSMenuItem*)anItem setState:[(NSMenuItem *)anItem representedObject] == master ||
|
[(NSMenuItem *)anItem setState:[(NSMenuItem *)anItem representedObject] == master ||
|
||||||
[(NSMenuItem *)anItem representedObject] == slave];
|
[(NSMenuItem *)anItem representedObject] == slave];
|
||||||
}
|
}
|
||||||
else if ([anItem action] == @selector(toggleCheats:)) {
|
else if ([anItem action] == @selector(toggleCheats:)) {
|
||||||
[(NSMenuItem*)anItem setState:GB_cheats_enabled(&gb)];
|
[(NSMenuItem *)anItem setState:GB_cheats_enabled(&gb)];
|
||||||
}
|
}
|
||||||
else if ([anItem action] == @selector(toggleDisplayBackground:)) {
|
else if ([anItem action] == @selector(toggleDisplayBackground:)) {
|
||||||
[(NSMenuItem*)anItem setState:!GB_is_background_rendering_disabled(&gb)];
|
[(NSMenuItem *)anItem setState:!GB_is_background_rendering_disabled(&gb)];
|
||||||
}
|
}
|
||||||
else if ([anItem action] == @selector(toggleDisplayObjects:)) {
|
else if ([anItem action] == @selector(toggleDisplayObjects:)) {
|
||||||
[(NSMenuItem*)anItem setState:!GB_is_object_rendering_disabled(&gb)];
|
[(NSMenuItem *)anItem setState:!GB_is_object_rendering_disabled(&gb)];
|
||||||
|
}
|
||||||
|
else if ([anItem action] == @selector(toggleAudioRecording:)) {
|
||||||
|
[(NSMenuItem *)anItem setTitle:_isRecordingAudio? @"Stop Audio Recording" : @"Start Audio Recording…"];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [super validateUserInterfaceItem:anItem];
|
return [super validateUserInterfaceItem:anItem];
|
||||||
@ -2388,5 +2394,70 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
|
|||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (IBAction)toggleAudioRecording:(id)sender
|
||||||
|
{
|
||||||
|
|
||||||
|
bool shouldResume = running;
|
||||||
|
[self stop];
|
||||||
|
if (_isRecordingAudio) {
|
||||||
|
_isRecordingAudio = false;
|
||||||
|
int error = GB_stop_audio_recording(&gb);
|
||||||
|
if (error) {
|
||||||
|
NSAlert *alert = [[NSAlert alloc] init];
|
||||||
|
[alert setMessageText:[NSString stringWithFormat:@"Could not finalize recording: %s", strerror(error)]];
|
||||||
|
[alert setAlertStyle:NSAlertStyleCritical];
|
||||||
|
[alert runModal];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[self.osdView displayText:@"Audio recording ended"];
|
||||||
|
}
|
||||||
|
if (shouldResume) {
|
||||||
|
[self start];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_audioSavePanel = [NSSavePanel savePanel];
|
||||||
|
if (!self.audioRecordingAccessoryView) {
|
||||||
|
[[NSBundle mainBundle] loadNibNamed:@"AudioRecordingAccessoryView" owner:self topLevelObjects:nil];
|
||||||
|
}
|
||||||
|
_audioSavePanel.accessoryView = self.audioRecordingAccessoryView;
|
||||||
|
[self audioFormatChanged:self.audioFormatButton];
|
||||||
|
|
||||||
|
[_audioSavePanel beginSheetModalForWindow:self.mainWindow completionHandler:^(NSInteger result) {
|
||||||
|
if (result == NSModalResponseOK) {
|
||||||
|
[_audioSavePanel orderOut:self];
|
||||||
|
int error = GB_start_audio_recording(&gb, _audioSavePanel.URL.fileSystemRepresentation, self.audioFormatButton.selectedTag);
|
||||||
|
if (error) {
|
||||||
|
NSAlert *alert = [[NSAlert alloc] init];
|
||||||
|
[alert setMessageText:[NSString stringWithFormat:@"Could not start recording: %s", strerror(error)]];
|
||||||
|
[alert setAlertStyle:NSAlertStyleCritical];
|
||||||
|
[alert runModal];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[self.osdView displayText:@"Audio recording started"];
|
||||||
|
_isRecordingAudio = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shouldResume) {
|
||||||
|
[self start];
|
||||||
|
}
|
||||||
|
_audioSavePanel = nil;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction)audioFormatChanged:(NSPopUpButton *)sender
|
||||||
|
{
|
||||||
|
switch ((GB_audio_format_t)sender.selectedTag) {
|
||||||
|
case GB_AUDIO_FORMAT_RAW:
|
||||||
|
_audioSavePanel.allowedFileTypes = @[@"raw", @"pcm"];
|
||||||
|
break;
|
||||||
|
case GB_AUDIO_FORMAT_AIFF:
|
||||||
|
_audioSavePanel.allowedFileTypes = @[@"aiff", @"aif", @"aifc"];
|
||||||
|
break;
|
||||||
|
case GB_AUDIO_FORMAT_WAV:
|
||||||
|
_audioSavePanel.allowedFileTypes = @[@"wav"];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -370,9 +370,14 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
<menuItem isSeparatorItem="YES" id="DPb-Sh-5tg"/>
|
<menuItem isSeparatorItem="YES" id="DPb-Sh-5tg"/>
|
||||||
<menuItem title="Mute Sound" keyEquivalent="m" id="1UK-8n-QPP">
|
<menuItem title="Start Audio Recording…" keyEquivalent="A" id="1UK-8n-QPP">
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="mute:" target="-1" id="YE5-mi-Yzd"/>
|
<action selector="toggleAudioRecording:" target="-1" id="YE5-mi-Yzd"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
<menuItem title="Mute Sound" keyEquivalent="m" id="zo0-Rh-wTu">
|
||||||
|
<connections>
|
||||||
|
<action selector="mute:" target="-1" id="eK3-ea-ExJ"/>
|
||||||
</connections>
|
</connections>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
</items>
|
</items>
|
||||||
|
Loading…
Reference in New Issue
Block a user