diff --git a/VoidLink/Base.lproj/iPad.storyboard b/VoidLink/Base.lproj/iPad.storyboard
index 4ce8b453..373eb8e5 100644
--- a/VoidLink/Base.lproj/iPad.storyboard
+++ b/VoidLink/Base.lproj/iPad.storyboard
@@ -1155,6 +1155,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1258,6 +1278,8 @@
+
+
diff --git a/VoidLink/Base.lproj/iPhone.storyboard b/VoidLink/Base.lproj/iPhone.storyboard
index eb41ec1d..a33e7a19 100644
--- a/VoidLink/Base.lproj/iPhone.storyboard
+++ b/VoidLink/Base.lproj/iPhone.storyboard
@@ -1869,7 +1869,7 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1990,6 +2010,8 @@
+
+
@@ -2011,19 +2033,19 @@
-
+
-
+
-
+
-
+
diff --git a/VoidLink/Database/DataManager.h b/VoidLink/Database/DataManager.h
index d5213527..c3ab661b 100644
--- a/VoidLink/Database/DataManager.h
+++ b/VoidLink/Database/DataManager.h
@@ -88,6 +88,7 @@ typedef NS_ENUM(NSInteger, WidgetSizeTransition) {
swapABXYButtons:(BOOL)swapABXYButtons
audioOnPC:(BOOL)audioOnPC
redirectMic:(BOOL)redirectMic
+ useBuiltinMic:(BOOL)useBuiltinMic
preferredCodec:(uint32_t)preferredCodec
enableYUV444:(BOOL)enableYUV444
enablePIP:(BOOL)enablePIP
diff --git a/VoidLink/Database/DataManager.m b/VoidLink/Database/DataManager.m
index 15937ac1..7c1585fc 100644
--- a/VoidLink/Database/DataManager.m
+++ b/VoidLink/Database/DataManager.m
@@ -83,6 +83,7 @@
swapABXYButtons:(BOOL)swapABXYButtons
audioOnPC:(BOOL)audioOnPC
redirectMic:(BOOL)redirectMic
+ useBuiltinMic:(BOOL)useBuiltinMic
preferredCodec:(uint32_t)preferredCodec
enableYUV444:(BOOL)enableYUV444
enablePIP:(BOOL)enablePIP
@@ -134,6 +135,7 @@
settingsToSave.swapABXYButtons = swapABXYButtons;
settingsToSave.playAudioOnPC = audioOnPC;
settingsToSave.redirectMic = redirectMic;
+ settingsToSave.useBuiltinMic = useBuiltinMic;
settingsToSave.preferredCodec = preferredCodec;
settingsToSave.enableYUV444 = enableYUV444;
settingsToSave.enablePIP = enablePIP;
diff --git a/VoidLink/Database/TemporarySettings.h b/VoidLink/Database/TemporarySettings.h
index 9acfaf83..cc2e4fd3 100644
--- a/VoidLink/Database/TemporarySettings.h
+++ b/VoidLink/Database/TemporarySettings.h
@@ -57,6 +57,7 @@
@property (nonatomic) BOOL swapABXYButtons;
@property (nonatomic) BOOL playAudioOnPC;
@property (nonatomic) BOOL redirectMic;
+@property (nonatomic) BOOL useBuiltinMic;
@property (nonatomic) BOOL optimizeGames;
@property (nonatomic) BOOL enableHdr;
@property (nonatomic) BOOL btMouseSupport;
diff --git a/VoidLink/Database/TemporarySettings.m b/VoidLink/Database/TemporarySettings.m
index b5723a5f..76802096 100644
--- a/VoidLink/Database/TemporarySettings.m
+++ b/VoidLink/Database/TemporarySettings.m
@@ -91,6 +91,7 @@
self.frameQueueSize = settings.frameQueueSize;
self.playAudioOnPC = settings.playAudioOnPC;
self.redirectMic = settings.redirectMic;
+ self.useBuiltinMic = settings.useBuiltinMic;
self.enableHdr = settings.enableHdr;
self.optimizeGames = settings.optimizeGames;
self.multiController = settings.multiController;
diff --git a/VoidLink/Input/MicHandler.swift b/VoidLink/Input/MicHandler.swift
index 527eecc4..02adc98c 100644
--- a/VoidLink/Input/MicHandler.swift
+++ b/VoidLink/Input/MicHandler.swift
@@ -20,6 +20,7 @@ public class MicHandler: NSObject {
private var audioSink: Any?
private var micInputFormat: AVAudioFormat!
private var isRecording = false
+ private var useBuiltinMic = false
private var pcm16Buffer: [Int16] = []
private let bufferQueue = DispatchQueue(label: "pcm.buffer.queue")
@@ -42,8 +43,9 @@ public class MicHandler: NSObject {
public weak var delegate: MicHandlerDelegate?
- public override init() {
+ @objc public init(useBuiltinMic:Bool) {
super.init()
+ self.useBuiltinMic = useBuiltinMic
do {
try configureSession()
try configureEngine()
@@ -185,6 +187,17 @@ public class MicHandler: NSObject {
try session.setAllowHapticsAndSystemSoundsDuringRecording(true)
}
try session.setActive(true)
+
+ // 列出所有可用输入
+ if self.useBuiltinMic, let inputs = session.availableInputs {
+ for port in inputs {
+ if port.portType == .builtInMic {
+ try session.setPreferredInput(port)
+ print("Set preferred input to built-in mic")
+ break
+ }
+ }
+ }
}
private func sendOpusFrame() {
diff --git a/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents b/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents
index 6befb009..e86ad2cc 100644
--- a/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents
+++ b/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents
@@ -71,6 +71,7 @@
+
\ No newline at end of file
diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings
index 3f897c5e..4b149a4f 100644
--- a/VoidLink/Localization/Localizable.xcstrings
+++ b/VoidLink/Localization/Localizable.xcstrings
@@ -5670,6 +5670,35 @@
}
}
},
+ "useBuiltinMicStackTip" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "When enabled, app will use built-in mic when Bluetooth headset is connected, which benefits audio quality."
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "开启后, App将在蓝牙耳机接入状态下使用设备内置麦克风, 以维持蓝牙耳机最佳音质。"
+ }
+ },
+ "zh-Hant" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "開啟後,App 在藍牙耳機連接時將使用裝置內建麥克風,以維持藍牙耳機的最佳音質。"
+ }
+ },
+ "zh-HK" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "開啟後,App 在藍牙耳機連接時將使用裝置內建麥克風,以維持藍牙耳機的最佳音質。"
+ }
+ }
+ }
+ },
"Version %@" : {
},
diff --git a/VoidLink/ViewControllers/MainFrameViewController.m b/VoidLink/ViewControllers/MainFrameViewController.m
index e2498048..281059c7 100644
--- a/VoidLink/ViewControllers/MainFrameViewController.m
+++ b/VoidLink/ViewControllers/MainFrameViewController.m
@@ -1200,6 +1200,8 @@ static NSMutableSet* hostList;
// Disable mic switch if sunshine does not support mic redirection
[settingsViewController.redirectMicSwitch setEnabled:!_settingsExpandedInStreamView||streamFrameViewController.micStreamInitialized];
if(_settingsExpandedInStreamView && !streamFrameViewController.micStreamInitialized) [settingsViewController.redirectMicSwitch setOn:false];
+ [settingsViewController setHidden:!settingsViewController.redirectMicSwitch.isOn forStack:settingsViewController.useBuiltinMicStack];
+ [settingsViewController.useBuiltinMicSwitch setEnabled:!_settingsExpandedInStreamView];
}
- (void)revealController:(SWRevealViewController *)revealController didMoveToPosition:(FrontViewPosition)position {
diff --git a/VoidLink/ViewControllers/SettingsViewController.h b/VoidLink/ViewControllers/SettingsViewController.h
index a94be53c..8d3287fd 100644
--- a/VoidLink/ViewControllers/SettingsViewController.h
+++ b/VoidLink/ViewControllers/SettingsViewController.h
@@ -138,6 +138,9 @@
@property (strong, nonatomic) IBOutlet UIStackView *localVolumeStack;
@property (strong, nonatomic) IBOutlet UISlider *localVolumeSlider;
+@property (strong, nonatomic) IBOutlet UIStackView *useBuiltinMicStack;
+@property (strong, nonatomic) IBOutlet UISwitch *useBuiltinMicSwitch;
+
@property (nonatomic, strong) MicHandler *micHandler;
diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m
index 0a3cdda2..f66b8a61 100644
--- a/VoidLink/ViewControllers/SettingsViewController.m
+++ b/VoidLink/ViewControllers/SettingsViewController.m
@@ -677,9 +677,10 @@ BOOL isCustomResolution(int resolutionSelected) {
[self addSetting:self.audioOnPcStack ofId:@"audioOnPcStack" withInfoTag:NO withDynamicLabel:NO to:audioSection];
[self addSetting:self.localVolumeStack ofId:@"localVolumeStack" withInfoTag:NO withDynamicLabel:YES to:audioSection];
[self addSetting:self.redirectMicStack ofId:@"redirectMicStack" withInfoTag:YES withDynamicLabel:NO to:audioSection];
+ [self addSetting:self.useBuiltinMicStack ofId:@"useBuiltinMicStack" withInfoTag:YES withDynamicLabel:NO to:audioSection];
[self addSetting:self.audioConfigStack ofId:@"audioConfigStack" withInfoTag:NO withDynamicLabel:NO to:audioSection];
[audioSection addToParentStack:_parentStack];
- [audioSection setExpanded:YES];
+ [audioSection setExpanded:YES];
otherSection = [[MenuSectionView alloc] init];
@@ -1158,6 +1159,10 @@ BOOL isCustomResolution(int resolutionSelected) {
tipText = [LocalizationHelper localizedStringForKey:@"sendDummyEventStackTip"];
showOnlineDocAction = false;
}
+ if([sender.superview.accessibilityIdentifier isEqualToString: @"useBuiltinMicStack"]){
+ tipText = [LocalizationHelper localizedStringForKey:@"useBuiltinMicStackTip"];
+ showOnlineDocAction = false;
+ }
UIAlertController *tipsAlertController = [UIAlertController alertControllerWithTitle: [LocalizationHelper localizedStringForKey:@"Tips"] message:tipText preferredStyle:UIAlertControllerStyleAlert];
@@ -1562,6 +1567,8 @@ BOOL isCustomResolution(int resolutionSelected) {
[self.redirectMicSwitch addTarget:self action:@selector(redirectMicSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
[self redirectMicSwitchFlipped:self.redirectMicSwitch];
+ [self.useBuiltinMicSwitch setOn:tempSettings.useBuiltinMic];
+
_lastSelectedResolutionIndex = resolution;
[self.resolutionSelector setSelectedSegmentIndex:resolution];
[self.resolutionSelector addTarget:self action:@selector(newResolutionChosen) forControlEvents:UIControlEventValueChanged];
@@ -2070,6 +2077,7 @@ BOOL isCustomResolution(int resolutionSelected) {
- (void)redirectMicSwitchFlipped:(UISwitch* )sender{
if(sender.isOn) [self checkAndRequestMicPermission];
+ [self setHidden:!sender.isOn forStack:_useBuiltinMicStack];
}
- (void)enableOswForNativeTouchSwitchFlipped:(UISwitch *)sender{
@@ -2491,6 +2499,7 @@ BOOL isCustomResolution(int resolutionSelected) {
NSInteger emulatedControllerType = [self segmentIndexToControllerType:self.emulatedControllerTypeSelector.selectedSegmentIndex]; //self.emulatedControllerTypeSelector.selectedSegmentIndex;
BOOL audioOnPC = self.audioOnPcSwitch.isOn;
BOOL redirectMic = self.redirectMicSwitch.isOn;
+ BOOL useBuiltinMic = self.useBuiltinMicSwitch.isOn;
uint32_t preferredCodec = [self getChosenCodecPreference];
BOOL enableYUV444 = self.yuv444Switch.isOn;
BOOL enablePIP = self.pipSwitch.isOn;
@@ -2540,6 +2549,7 @@ BOOL isCustomResolution(int resolutionSelected) {
swapABXYButtons:swapABXYButtons
audioOnPC:audioOnPC
redirectMic:redirectMic
+ useBuiltinMic:useBuiltinMic
preferredCodec:preferredCodec
enableYUV444:enableYUV444
enablePIP:enablePIP
diff --git a/VoidLink/ViewControllers/StreamFrameViewController.m b/VoidLink/ViewControllers/StreamFrameViewController.m
index 18a1a168..af0f65aa 100644
--- a/VoidLink/ViewControllers/StreamFrameViewController.m
+++ b/VoidLink/ViewControllers/StreamFrameViewController.m
@@ -1302,7 +1302,7 @@
dispatch_after(delay, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if(self->_streamConfig.redirectMic){
self->_micStreamInitialized = true;
- self->micHandler = [MicHandler new];
+ self->micHandler = [[MicHandler alloc] initWithUseBuiltinMic:self->_settings.useBuiltinMic];
[self->micHandler startTapping];
}
});
diff --git a/VoidLink/mul.lproj/iPad.xcstrings b/VoidLink/mul.lproj/iPad.xcstrings
index acb249e2..408b2ecd 100644
--- a/VoidLink/mul.lproj/iPad.xcstrings
+++ b/VoidLink/mul.lproj/iPad.xcstrings
@@ -13,7 +13,7 @@
},
"zh-Hans" : {
"stringUnit" : {
- "state" : "needs_review",
+ "state" : "translated",
"value" : "异步多点触控"
}
},
@@ -43,7 +43,7 @@
},
"zh-Hans" : {
"stringUnit" : {
- "state" : "needs_review",
+ "state" : "translated",
"value" : "关闭"
}
},
@@ -103,7 +103,7 @@
},
"zh-Hans" : {
"stringUnit" : {
- "state" : "needs_review",
+ "state" : "translated",
"value" : "队列缓冲"
}
},
@@ -175,7 +175,7 @@
},
"zh-Hans" : {
"stringUnit" : {
- "state" : "needs_review",
+ "state" : "translated",
"value" : "被窗口捕获"
}
},
@@ -631,19 +631,19 @@
},
"zh-Hans" : {
"stringUnit" : {
- "state" : "needs_review",
+ "state" : "translated",
"value" : "内置"
}
},
"zh-Hant" : {
"stringUnit" : {
- "state" : "needs_review",
+ "state" : "translated",
"value" : "內建"
}
},
"zh-HK" : {
"stringUnit" : {
- "state" : "needs_review",
+ "state" : "translated",
"value" : "內建"
}
}
@@ -955,6 +955,36 @@
}
}
},
+ "bfV-QT-eKw.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Use Built-in Mic\"; ObjectID = \"bfV-QT-eKw\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Use Built-in Mic"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "使用内置Mic"
+ }
+ },
+ "zh-Hant" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "使用內建Mic"
+ }
+ },
+ "zh-HK" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "使用內建Mic"
+ }
+ }
+ }
+ },
"bhC-da-VGd.segmentTitles[0]" : {
"comment" : "Class = \"UISegmentedControl\"; bhC-da-VGd.segmentTitles[0] = \"Touchpad\"; ObjectID = \"bhC-da-VGd\";",
"extractionState" : "extracted_with_value",
diff --git a/VoidLink/mul.lproj/iPhone.xcstrings b/VoidLink/mul.lproj/iPhone.xcstrings
index 39ff641f..0ade7140 100644
--- a/VoidLink/mul.lproj/iPhone.xcstrings
+++ b/VoidLink/mul.lproj/iPhone.xcstrings
@@ -1621,6 +1621,36 @@
}
}
},
+ "GiW-tl-1GX.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Use Built-in Mic\"; ObjectID = \"GiW-tl-1GX\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Use Built-in Mic"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "使用内置Mic"
+ }
+ },
+ "zh-Hant" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "使用內建Mic"
+ }
+ },
+ "zh-HK" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "使用內建Mic"
+ }
+ }
+ }
+ },
"hfR-K8-Ti4.segmentTitles[0]" : {
"comment" : "Class = \"UISegmentedControl\"; hfR-K8-Ti4.segmentTitles[0] = \"Stereo\"; ObjectID = \"hfR-K8-Ti4\";",
"extractionState" : "extracted_with_value",