Audio recording in the Cocoa frontend

This commit is contained in:
Lior Halphon 2022-05-21 02:17:59 +03:00
parent 6055092249
commit cdfcc4ca2d
4 changed files with 139 additions and 10 deletions

View 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>

View File

@ -56,6 +56,8 @@
@property (readonly) GB_oam_info_t *oamInfo;
@property uint8_t oamCount;
@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;
-(uint8_t) readMemory:(uint16_t) addr;

View File

@ -101,6 +101,9 @@ enum model {
Document *slave;
signed linkOffset;
bool linkCableBit;
NSSavePanel *_audioSavePanel;
bool _isRecordingAudio;
}
@property GBAudioClient *audioClient;
@ -1134,7 +1137,7 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
return !GB_debugger_is_stopped(&gb);
}
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:)) {
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"DeveloperMode"]) {
@ -1142,26 +1145,29 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
}
}
else if ([anItem action] == @selector(disconnectAllAccessories:)) {
[(NSMenuItem*)anItem setState:accessory == GBAccessoryNone];
[(NSMenuItem *)anItem setState:accessory == GBAccessoryNone];
}
else if ([anItem action] == @selector(connectPrinter:)) {
[(NSMenuItem*)anItem setState:accessory == GBAccessoryPrinter];
[(NSMenuItem *)anItem setState:accessory == GBAccessoryPrinter];
}
else if ([anItem action] == @selector(connectWorkboy:)) {
[(NSMenuItem*)anItem setState:accessory == GBAccessoryWorkboy];
[(NSMenuItem *)anItem setState:accessory == GBAccessoryWorkboy];
}
else if ([anItem action] == @selector(connectLinkCable:)) {
[(NSMenuItem*)anItem setState:[(NSMenuItem *)anItem representedObject] == master ||
[(NSMenuItem *)anItem setState:[(NSMenuItem *)anItem representedObject] == master ||
[(NSMenuItem *)anItem representedObject] == slave];
}
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:)) {
[(NSMenuItem*)anItem setState:!GB_is_background_rendering_disabled(&gb)];
[(NSMenuItem *)anItem setState:!GB_is_background_rendering_disabled(&gb)];
}
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];
@ -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

View File

@ -370,9 +370,14 @@
</connections>
</menuItem>
<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>
<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>
</menuItem>
</items>