AirPods Pro can automatically enable noise cancellation when music is played and switch to transparency mode when music is paused. You can hook the media controller to change noise cancellation mode on your AirPods automatically.
- given the application playing media
- when the application changes the state of playing (from stop/pause to play or vice versa)
- if the current output route is AirPods Pro
- if media is now playing
- set the Bluetooth listening mode to Noise Cancellation
- else
- set the Bluetooth listening mode to Transparency
- if media is now playing
Hook media controller
The media controller class is SBMediaController
. This class contains a method which will be called when the media state changes:
-(void)_mediaRemoteNowPlayingApplicationIsPlayingDidChange:(id)arg1
Code language: Objective-C (objectivec)
A hook on this method will allow you to perform an action whenever the media's ‘now playing’ state changes. To know whether the media has changed from playing to paused or vice versa:
- hook after the built-in implementation of this method is finished,
%orig(arg1);
- then inspect what the current state of play is by looking at
SBMediaController
:-(BOOL)isPlaying;
.
The code at this point is as follows, which includes the outline of a hook on the aforementioned method and the ability for that hook to find whether media is playing:
@interface SBMediaController : NSObject
-(BOOL)isPlaying;
@end
%hook SBMediaController
-(void)_mediaRemoteNowPlayingApplicationIsPlayingDidChange:(id)arg1 {
%orig(arg1);
}
%end
Code language: Objective-C (objectivec)
Get access to AirPods
When media is playing on iPhone, it is routed to an output device such as the built-in speaker, connected headphones or AirPlay. Each of these routes are an instance of MPAVRoute
. You can find the currently active route from the MPAVRoutingController
which has the pickedRoute
property.
@interface MPAVRoutingController : NSObject
@property(readonly, nonatomic) MPAVRoute *pickedRoute;
@end
Code language: Objective-C (objectivec)
To access the pickedRoute
from the
Swift | value(forKey: "_routingController")?.pickedRoute() |
Objective-C | [[self valueForKey:@"_routingController"] pickedRoute] |
routingController
's pickedRoute
To make changes to the state of the AirPods, it's necessary to get the
MPAVRoutingController
provides the chosen MPAVRoute
through the pickedRoute
property.
Choose noise cancellation or transparency mode
We're interested in two of the three listening modes of AirPods Pro:
Noise cancellation mode | AVOutputDeviceBluetoothListeningModeActiveNoiseCancellation | |
Normal mode | AVOutputDeviceBluetoothListeningModeNormal | |
Transparency mode | AVOutputDeviceBluetoothListeningModeAudioTransparency |
If music is playing, we want to choose noise cancellation mode, otherwise we want to set transparency mode.
Swift | isPlaying() ? "AVOutputDeviceBluetoothListeningModeActiveNoiseCancellation" : "AVOutputDeviceBluetoothListeningModeAudioTransparency" |
Objective-C | [self isPlaying] ? @"AVOutputDeviceBluetoothListeningModeActiveNoiseCancellation" : @"AVOutputDeviceBluetoothListeningModeAudioTransparency"]; |
The return value of the above expression is what the listening mode needs to be set to…
Set listening mode
Another class will help us with this: AVOutputDevice
. This class contains a useful method:
-(void)setCurrentBluetoothListeningMode:(NSString *)arg1;
Code language: Objective-C (objectivec)
This method can be called and its returned value can be used to set the value of the property.
Jailbreak tweak
The Banana jailbreak tweak does this automatically for you:
My AirPods Pro and Max are shown both as unconnectable in BT Inspector for IOS and for macOS Monterey. They both are really connected in any of my Apple devices (iPhone, iPad and iMac) and working suitably.
My main need with BT Inspector is to register the time of use and connection of my AirPods in any of my devices (iPhone, iPad and iMac).
If they are shown as unconnectable it is not possible to measure and save these time counters and there is no answer nor change of state when using the "Interrogate" option.
Your App's screenshots show an example with AirPods connected.
Is there a solution for this AirPods' issue I am reporting?