diff --git a/VoidLink/Base.lproj/iPad.storyboard b/VoidLink/Base.lproj/iPad.storyboard
index e5a293e7..4ce8b453 100644
--- a/VoidLink/Base.lproj/iPad.storyboard
+++ b/VoidLink/Base.lproj/iPad.storyboard
@@ -1135,6 +1135,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1182,6 +1202,8 @@
+
+
@@ -1958,7 +1980,7 @@
-
+
@@ -1967,13 +1989,13 @@
-
+
-
+
-
+
diff --git a/VoidLink/Base.lproj/iPhone.storyboard b/VoidLink/Base.lproj/iPhone.storyboard
index dd035362..eb41ec1d 100644
--- a/VoidLink/Base.lproj/iPhone.storyboard
+++ b/VoidLink/Base.lproj/iPhone.storyboard
@@ -1868,6 +1868,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1915,6 +1935,8 @@
+
+
@@ -1989,19 +2011,19 @@
-
+
-
+
-
+
-
+
diff --git a/VoidLink/Database/DataManager.h b/VoidLink/Database/DataManager.h
index 77029987..d5213527 100644
--- a/VoidLink/Database/DataManager.h
+++ b/VoidLink/Database/DataManager.h
@@ -76,6 +76,7 @@ typedef NS_ENUM(NSInteger, WidgetSizeTransition) {
touchPointerVelocityFactor:(CGFloat)touchPointerVelocityFactor
mousePointerVelocityFactor:(CGFloat)mousePointerVelocityFactor
gyroSensitivity:(CGFloat)gyroSensitivity
+ localVolume:(CGFloat)localVolume
touchMoveEventInterval:(NSInteger)touchMoveEventInterval
reverseMouseWheelDirection:(BOOL)reverseMouseWheelDirection
asyncNativeTouchPriority:(NSInteger)asyncNativeTouchPriority
diff --git a/VoidLink/Database/DataManager.m b/VoidLink/Database/DataManager.m
index 57106b74..15937ac1 100644
--- a/VoidLink/Database/DataManager.m
+++ b/VoidLink/Database/DataManager.m
@@ -71,6 +71,7 @@
touchPointerVelocityFactor:(CGFloat)touchPointerVelocityFactor
mousePointerVelocityFactor:(CGFloat)mousePointerVelocityFactor
gyroSensitivity:(CGFloat)gyroSensitivity
+ localVolume:(CGFloat)localVolume
touchMoveEventInterval:(NSInteger)touchMoveEventInterval
reverseMouseWheelDirection:(BOOL)reverseMouseWheelDirection
asyncNativeTouchPriority:(NSInteger)asyncNativeTouchPriority
@@ -121,6 +122,7 @@
settingsToSave.touchPointerVelocityFactor = [NSNumber numberWithFloat:touchPointerVelocityFactor];
settingsToSave.mousePointerVelocityFactor = [NSNumber numberWithFloat:mousePointerVelocityFactor];
settingsToSave.gyroSensitivity = [NSNumber numberWithFloat:gyroSensitivity];
+ settingsToSave.localVolume = [NSNumber numberWithFloat:localVolume];
settingsToSave.touchMoveEventInterval = [NSNumber numberWithInteger:touchMoveEventInterval];
settingsToSave.reverseMouseWheelDirection = reverseMouseWheelDirection;
settingsToSave.asyncNativeTouchPriority = [NSNumber numberWithInteger:asyncNativeTouchPriority];
diff --git a/VoidLink/Database/TemporarySettings.h b/VoidLink/Database/TemporarySettings.h
index 4a5f8d5d..9acfaf83 100644
--- a/VoidLink/Database/TemporarySettings.h
+++ b/VoidLink/Database/TemporarySettings.h
@@ -33,6 +33,7 @@
@property (nonatomic, retain) NSNumber * touchMoveEventInterval;
@property (nonatomic, retain) NSNumber * touchPointerVelocityFactor;
@property (nonatomic, retain) NSNumber * gyroSensitivity;
+@property (nonatomic, retain) NSNumber * localVolume;
@property (nonatomic, retain) NSNumber * emulatedControllerType;
@property (nonatomic, retain) NSNumber * mousePointerVelocityFactor;
@property (nonatomic, retain) NSNumber * pointerVelocityModeDivider;
diff --git a/VoidLink/Database/TemporarySettings.m b/VoidLink/Database/TemporarySettings.m
index f40e5277..b5723a5f 100644
--- a/VoidLink/Database/TemporarySettings.m
+++ b/VoidLink/Database/TemporarySettings.m
@@ -116,6 +116,7 @@
self.touchPointerVelocityFactor = settings.touchPointerVelocityFactor;
self.mousePointerVelocityFactor = settings.mousePointerVelocityFactor;
self.gyroSensitivity = settings.gyroSensitivity;
+ self.localVolume = settings.localVolume;
self.pointerVelocityModeDivider = settings.pointerVelocityModeDivider;
self.unlockDisplayOrientation = settings.unlockDisplayOrientation;
self.resolutionSelected = settings.resolutionSelected;
diff --git a/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents b/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents
index 508ded7a..6befb009 100644
--- a/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents
+++ b/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents
@@ -44,6 +44,7 @@
+
diff --git a/VoidLink/Stream/Connection.h b/VoidLink/Stream/Connection.h
index b7327b58..f4e30315 100644
--- a/VoidLink/Stream/Connection.h
+++ b/VoidLink/Stream/Connection.h
@@ -22,5 +22,6 @@
-(BandwidthTracker *) getBwTracker;
-(BOOL) getVideoStats:(video_stats_t*)stats;
-(NSString*) getActiveCodecName;
++ (void)setVolume:(float)newVolume;
@end
diff --git a/VoidLink/Stream/Connection.m b/VoidLink/Stream/Connection.m
index 767032cf..3c067525 100644
--- a/VoidLink/Stream/Connection.m
+++ b/VoidLink/Stream/Connection.m
@@ -44,6 +44,7 @@ static NSLock* videoStatsLock;
static SDL_AudioDeviceID audioDevice;
static OPUS_MULTISTREAM_CONFIGURATION audioConfig;
static void* audioBuffer;
+static float volume = 1.0;
static int audioFrameSize;
static VideoDecoderRenderer* renderer;
@@ -302,6 +303,13 @@ void ArCleanup(void)
SDL_QuitSubSystem(SDL_INIT_AUDIO);
}
++ (void)setVolume:(float)linearVolume{
+ if (linearVolume <= 0.0f) linearVolume = 0.0f;
+ if (linearVolume >= 1.0f) linearVolume = 1.0f;
+ CGFloat exponent = 2.5;
+ volume = powf(linearVolume, exponent);
+}
+
void ArDecodeAndPlaySample(char* sampleData, int sampleLength)
{
int decodeLen;
@@ -318,9 +326,20 @@ void ArDecodeAndPlaySample(char* sampleData, int sampleLength)
(float*)audioBuffer,
audioConfig.samplesPerFrame,
0);
+
if (decodeLen > 0) {
// Provide backpressure on the queue to ensure too many frames don't build up
// in SDL's audio queue.
+
+ float* fbuf = (float*)audioBuffer;
+
+ if(volume != 1.0){
+ int totalSamples = decodeLen * audioConfig.channelCount;
+ for (int i = 0; i < totalSamples; i++) {
+ fbuf[i] *= volume;
+ }
+ }
+
while (SDL_GetQueuedAudioSize(audioDevice) / audioFrameSize > 10) {
[NSThread sleepForTimeInterval:0.001f];
}
@@ -470,6 +489,8 @@ void ClSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t
_streamConfig.supportedVideoFormats = config.supportedVideoFormats;
_streamConfig.audioConfiguration = config.audioConfiguration;
_streamConfig.redirectMic = config.redirectMic && [MicHandler permissionGranted];
+ NSLog(@"config.localVolume %f", config.localVolume);
+ [Connection setVolume:config.localVolume];
// Since we require iOS 12 or above, we're guaranteed to be running
// on a 64-bit device with ARMv8 crypto instructions, so we don't
diff --git a/VoidLink/Stream/StreamConfiguration.h b/VoidLink/Stream/StreamConfiguration.h
index 5ff686a0..f2019778 100644
--- a/VoidLink/Stream/StreamConfiguration.h
+++ b/VoidLink/Stream/StreamConfiguration.h
@@ -42,5 +42,6 @@
@property BOOL multiController;
@property NSData* serverCert;
@property int localMousePointerMode;
+@property CGFloat localVolume;
@end
diff --git a/VoidLink/Stream/StreamConfiguration.m b/VoidLink/Stream/StreamConfiguration.m
index aab4f9d7..f3be6778 100644
--- a/VoidLink/Stream/StreamConfiguration.m
+++ b/VoidLink/Stream/StreamConfiguration.m
@@ -9,5 +9,5 @@
#import "StreamConfiguration.h"
@implementation StreamConfiguration
-@synthesize host, httpsPort, appID, width, height, frameRate, bitRate, riKeyId, riKey, gamepadMask, appName, optimizeGameSettings, playAudioOnPC, swapABXYButtons, buttonVisualFeedback, gyroMode, emulatedControllerType, audioConfiguration, supportedVideoFormats, multiController, serverCert, rtspSessionUrl, serverCodecModeSupport, enableYUV444, enablePIP;
+@synthesize host, httpsPort, appID, width, height, frameRate, bitRate, riKeyId, riKey, gamepadMask, appName, optimizeGameSettings, playAudioOnPC, swapABXYButtons, buttonVisualFeedback, gyroMode, emulatedControllerType, audioConfiguration, supportedVideoFormats, multiController, serverCert, rtspSessionUrl, serverCodecModeSupport, enableYUV444, enablePIP, localVolume;
@end
diff --git a/VoidLink/ViewControllers/MainFrameViewController.m b/VoidLink/ViewControllers/MainFrameViewController.m
index 03480b70..e2498048 100644
--- a/VoidLink/ViewControllers/MainFrameViewController.m
+++ b/VoidLink/ViewControllers/MainFrameViewController.m
@@ -821,6 +821,7 @@ static NSMutableSet* hostList;
_streamConfig.optimizeGameSettings = streamSettings.optimizeGames;
_streamConfig.playAudioOnPC = streamSettings.playAudioOnPC;
_streamConfig.redirectMic = streamSettings.redirectMic;
+ _streamConfig.localVolume = streamSettings.localVolume.floatValue;
_streamConfig.swapABXYButtons = streamSettings.swapABXYButtons;
_streamConfig.buttonVisualFeedback = streamSettings.buttonVisualFeedback;
_streamConfig.asyncNativeTouchPriority = streamSettings.asyncNativeTouchPriority; // new streamConfig segment
diff --git a/VoidLink/ViewControllers/SettingsViewController.h b/VoidLink/ViewControllers/SettingsViewController.h
index 675fcb3f..a94be53c 100644
--- a/VoidLink/ViewControllers/SettingsViewController.h
+++ b/VoidLink/ViewControllers/SettingsViewController.h
@@ -135,6 +135,9 @@
@property (strong, nonatomic) IBOutlet UIStackView *sendDummyEventStack;
@property (strong, nonatomic) IBOutlet UISwitch *sendDummyEventSwitch;
+@property (strong, nonatomic) IBOutlet UIStackView *localVolumeStack;
+@property (strong, nonatomic) IBOutlet UISlider *localVolumeSlider;
+
@property (nonatomic, strong) MicHandler *micHandler;
diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m
index 93b4563f..0a3cdda2 100644
--- a/VoidLink/ViewControllers/SettingsViewController.m
+++ b/VoidLink/ViewControllers/SettingsViewController.m
@@ -12,6 +12,7 @@
#import "TemporarySettings.h"
#import "DataManager.h"
#import "ThemeManager.h"
+#import "Connection.h"
#import "Plot.h"
#import
@@ -674,6 +675,7 @@ 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.audioConfigStack ofId:@"audioConfigStack" withInfoTag:NO withDynamicLabel:NO to:audioSection];
[audioSection addToParentStack:_parentStack];
@@ -1549,10 +1551,13 @@ BOOL isCustomResolution(int resolutionSelected) {
[self.emulatedControllerTypeSelector setSelectedSegmentIndex:[self controllerTypeToSegmentIndex:tempSettings.emulatedControllerType.intValue]];
[self.emulatedControllerTypeSelector addTarget:self action:@selector(emulatedControllerTypeChanged:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
[self emulatedControllerTypeChanged:self.emulatedControllerTypeSelector];
-
-
-
+
[self.audioOnPcSwitch setOn:tempSettings.playAudioOnPC];
+
+ [self.localVolumeSlider setValue:tempSettings.localVolume.floatValue*100];
+ [self.localVolumeSlider addTarget:self action:@selector(localVolumeSliderMoved:) forControlEvents:UIControlEventValueChanged];
+ [self localVolumeSliderMoved:self.localVolumeSlider];
+
[self.redirectMicSwitch setOn:tempSettings.redirectMic];
[self.redirectMicSwitch addTarget:self action:@selector(redirectMicSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
[self redirectMicSwitchFlipped:self.redirectMicSwitch];
@@ -1903,7 +1908,6 @@ BOOL isCustomResolution(int resolutionSelected) {
[self presentViewController:self.layoutOnScreenControlsVC animated:YES completion:nil];
}
-
- (void) pointerVelocityModeDividerSliderMoved:(UISlider* )sender {
[self findDynamicLabelFromStack:self.pointerVelocityDividerStack].text = [NSString stringWithFormat:@" | %d%% | %d%% | ", (uint8_t)sender.value, 100-(uint8_t)sender.value];
}
@@ -1916,6 +1920,11 @@ BOOL isCustomResolution(int resolutionSelected) {
[self findDynamicLabelFromStack:self.gyroSensitivityStack].text = [NSString stringWithFormat:@" %d%% ", (uint16_t)sender.value]; // Update label display
}
+- (void) localVolumeSliderMoved:(UISlider* )sender {
+ [self findDynamicLabelFromStack:self.localVolumeStack].text = [NSString stringWithFormat:@" %d%% ", (uint16_t)sender.value]; // Update label display
+ if(_mainFrameViewController.settingsExpandedInStreamView) [Connection setVolume:sender.value/100];
+}
+
- (void) backgroundSessionTimerSliderMoved:(UISlider* )sender {
NSString* labelString;
labelString = [LocalizationHelper localizedStringForKey:@" keep %d min ", (uint16_t)sender.value];
@@ -2464,6 +2473,8 @@ BOOL isCustomResolution(int resolutionSelected) {
CGFloat touchPointerVelocityFactor = (CGFloat)(uint16_t)[self map_velocFactorDisplay_fromSliderValue:self.touchPointerVelocityFactorSlider.value]/100;
CGFloat mousePointerVelocityFactor = (CGFloat)(uint16_t)[self map_velocFactorDisplay_fromSliderValue:self.mousePointerVelocityFactorSlider.value]/100;
CGFloat gyroSensitivity = (CGFloat)(uint16_t)self.gyroSensitivitySlider.value/100;
+
+ CGFloat localVolume = self.localVolumeSlider.value/100;
uint16_t touchMoveEventInterval = (uint16_t)self.touchMoveEventIntervalSlider.value;
@@ -2517,6 +2528,7 @@ BOOL isCustomResolution(int resolutionSelected) {
touchPointerVelocityFactor:touchPointerVelocityFactor
mousePointerVelocityFactor:mousePointerVelocityFactor
gyroSensitivity:gyroSensitivity
+ localVolume:localVolume
touchMoveEventInterval:touchMoveEventInterval
reverseMouseWheelDirection:reverseMouseWheelDirection
asyncNativeTouchPriority:asyncNativeTouchPriority
diff --git a/VoidLink/mul.lproj/iPad.xcstrings b/VoidLink/mul.lproj/iPad.xcstrings
index 1569f104..acb249e2 100644
--- a/VoidLink/mul.lproj/iPad.xcstrings
+++ b/VoidLink/mul.lproj/iPad.xcstrings
@@ -679,6 +679,36 @@
}
}
},
+ "AeU-kl-XFa.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Local Volume\"; ObjectID = \"AeU-kl-XFa\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Local Volume"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "本地音量"
+ }
+ },
+ "zh-Hant" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "本地音量"
+ }
+ },
+ "zh-HK" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "本地音量"
+ }
+ }
+ }
+ },
"aFy-0w-YPe.segmentTitles[0]" : {
"comment" : "Class = \"UISegmentedControl\"; aFy-0w-YPe.segmentTitles[0] = \"H.264\"; ObjectID = \"aFy-0w-YPe\";",
"extractionState" : "extracted_with_value",
diff --git a/VoidLink/mul.lproj/iPhone.xcstrings b/VoidLink/mul.lproj/iPhone.xcstrings
index 64dc4126..39ff641f 100644
--- a/VoidLink/mul.lproj/iPhone.xcstrings
+++ b/VoidLink/mul.lproj/iPhone.xcstrings
@@ -1561,6 +1561,36 @@
}
}
},
+ "GbY-52-itv.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Local Volume\"; ObjectID = \"GbY-52-itv\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Local Volume"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "本地音量"
+ }
+ },
+ "zh-Hant" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "本地音量"
+ }
+ },
+ "zh-HK" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "本地音量"
+ }
+ }
+ }
+ },
"ghM-zc-sr6.title" : {
"comment" : "Class = \"UIBarButtonItem\"; title = \"Delete\"; ObjectID = \"ghM-zc-sr6\";",
"extractionState" : "extracted_with_value",