Skip to content

Instantly share code, notes, and snippets.

@sergealagon
Created August 26, 2025 15:51
Show Gist options
  • Select an option

  • Save sergealagon/a0d07cdac7be22135ba7d70098679d18 to your computer and use it in GitHub Desktop.

Select an option

Save sergealagon/a0d07cdac7be22135ba7d70098679d18 to your computer and use it in GitHub Desktop.
Detect volume button press on jailed iOS device
/* MIT License */
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <objc/message.h>
#import <os/log.h>
/* this is a way to detect volume button press on jailed iOS device */
/* if you cannot use private frameworks, you could probably look into MPVolumeView*/
/* but i never tried it myself. you may also look into AVAudioSession's outputVolume*/
/* below is a demonstration of detecting if both volume buttons are pressed AT THE SAME TIME */
/* feel free to simplify it according to your needs */
@interface MPVolumeControllerSystemDataSource : NSObject
@property (nonatomic, assign, readwrite) float volume; //last volume
@end
static void (*orig__systemVolumeDidChange)(MPVolumeControllerSystemDataSource*, SEL, id) = NULL;
static void new__systemVolumeDidChange(MPVolumeControllerSystemDataSource *self, SEL _cmd, id arg1) {
static NSTimeInterval lastCallTime = 0;
static float lastVol = -1.0f;
static const NSTimeInterval pressThreshold = 0.05; /* gap threshold of 1st & 2nd button time press in ms*/
static const float EPSILON = 0.0005f; /* ts is the tolerance. can be tuned by net change delta of newVol - lastVol */
NSTimeInterval now = CFAbsoluteTimeGetCurrent();
float currentVol = self.volume;
orig__systemVolumeDidChange(self, _cmd, arg1);
NSDictionary *userInfo = [arg1 userInfo];
float newVol = [userInfo[@"Volume"] floatValue];
if (lastCallTime > 0 && (now - lastCallTime) <= pressThreshold && fabs(newVol - lastVol) <= EPSILON) {
os_log(OS_LOG_DEFAULT, "[volumetweak] both vol press detected."); /* you can call any function here */
}
lastCallTime = now;
lastVol = currentVol;
}
__attribute__((constructor)) static void initialize(void) {
const Class className = objc_getClass("MPVolumeControllerSystemDataSource");
const Method method = class_getInstanceMethod(className, sel_registerName("_systemVolumeDidChange:"));
orig__systemVolumeDidChange = (void (*)(MPVolumeControllerSystemDataSource*, SEL, id))method_getImplementation(method);
method_setImplementation(method, (IMP)new__systemVolumeDidChange);
os_log(OS_LOG_DEFAULT, "[volumetweak] started!");
((void (*)(id, SEL))objc_msgSend)(objc_getClass("MPVolumeController"), sel_registerName("new")); /* need to initialize MPVolumeController */
}
/* if you wanna use Theos: */
// %hook MPVolumeControllerSystemDataSource
// static NSTimeInterval lastCallTime = 0;
// static float lastVol = -1.0f;
// static const NSTimeInterval pressThreshold = 0.05; /* gap threshold of 1st & 2nd button time press in ms*/
// static const float EPSILON = 0.0005f; /* ts is the tolerance. can be tuned by net change delta of newVol - lastVol */
// -(void)_systemVolumeDidChange:(id)arg1 {
// NSTimeInterval now = CFAbsoluteTimeGetCurrent();
// float currentVol = self.volume;
// %orig;
// NSDictionary *userInfo = [arg1 userInfo];
// float newVol = [userInfo[@"Volume"] floatValue];
// if (lastCallTime > 0 && (now - lastCallTime) <= pressThreshold && fabs(newVol - lastVol) <= EPSILON) {
// os_log(OS_LOG_DEFAULT, "[volumetweak] both vol press detected.");
// }
// lastCallTime = now;
// lastVol = currentVol;
// }
// %end
// %ctor {
// os_log(OS_LOG_DEFAULT, "[volumetweak] started!");
// ((void (*)(id, SEL))objc_msgSend)(objc_getClass("MPVolumeController"), sel_registerName("new")); /* need to initialize MPVolumeController */
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment