Fix for iOS8/9 and add support to iOS11+

This commit is contained in:
Mario Cheung
2020-08-26 19:48:14 +08:00
parent 27ce5454c3
commit 720b888d82
4 changed files with 297 additions and 48 deletions

View File

@ -1,11 +1,12 @@
ARCHS = armv7 arm64 ARCHS = armv7 arm64
VALID_ARCHS = armv7 armv7s arm64 VALID_ARCHS = armv7 armv7s arm64 arm64e
include $(THEOS)/makefiles/common.mk include $(THEOS)/makefiles/common.mk
TWEAK_NAME = NotifyMusic TWEAK_NAME = NotifyMusic
NotifyMusic_FILES = Tweak.xm NotifyMusic_FILES = Tweak.xm
NotifyMusic_FRAMEWORKS = UIKit NotifyMusic_FRAMEWORKS = UIKit
NotifyMusic_PRIVATE_FRAMEWORKS = MediaRemote
NotifyMusic_LIBRARIES = bulletin NotifyMusic_LIBRARIES = bulletin
include $(THEOS_MAKE_PATH)/tweak.mk include $(THEOS_MAKE_PATH)/tweak.mk

266
Tweak.xm
View File

@ -1,4 +1,12 @@
#import "notify.h"
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <MediaRemote/MediaRemote.h>
@interface JBBulletinManager : NSObject
+(id)sharedInstance;
-(id)showBulletinWithTitle:(NSString *)title message:(NSString *)message bundleID:(NSString *)bundleID;
-(id)showBulletinWithTitle:(NSString *)title message:(NSString *)message bundleID:(NSString *)bundleID hasSound:(BOOL)hasSound soundID:(int)soundID vibrateMode:(int)vibrate soundPath:(NSString *)soundPath attachmentImage:(UIImage *)attachmentImage overrideBundleImage:(UIImage *)overrideBundleImage;
@end
@interface SpringBoard @interface SpringBoard
-(id)_accessibilityFrontMostApplication; -(id)_accessibilityFrontMostApplication;
@ -19,49 +27,255 @@
@property (nonatomic,readonly) NSString * nowPlayingAppDisplayID; @property (nonatomic,readonly) NSString * nowPlayingAppDisplayID;
@property (nonatomic,readonly) UIImage * currentNowPlayingArtwork; @property (nonatomic,readonly) UIImage * currentNowPlayingArtwork;
@property (nonatomic,readonly) NSDictionary * currentNowPlayingInfo; @property (nonatomic,readonly) NSDictionary * currentNowPlayingInfo;
@property (nonatomic,readonly) double currentElapsed;
@property (nonatomic,readonly) double currentDuration;
-(void)_updateCurrentNowPlaying;
-(void)_updatePlaybackState;
-(void)setShouldUpdateNowPlayingArtwork:(BOOL)arg1 ;
@end @end
@interface JBBulletinManager : NSObject @interface SBMediaController
+(id)sharedInstance; @property (retain) NSDictionary * currentNowPlayingInfo;
-(id)showBulletinWithTitle:(NSString *)title message:(NSString *)message bundleID:(NSString *)bundleID; -(id/*SBApplication **/)nowPlayingApplication;
-(id)showBulletinWithTitle:(NSString *)title message:(NSString *)message bundleID:(NSString *)bundleID hasSound:(BOOL)hasSound soundID:(int)soundID vibrateMode:(int)vibrate soundPath:(NSString *)soundPath attachmentImage:(UIImage *)attachmentImage overrideBundleImage:(UIImage *)overrideBundleImage; -(void)setNowPlayingInfo:(NSDictionary *)arg1 ;
-(BOOL)isPlaying;
@end @end
%hook MPUNowPlayingController @interface NotifyMusic : NSObject {
static NSString *cachedTitle; int token;
static NSString *artist;
static NSString *album; BOOL notifyMusicPrefsLoaded;
-(void)_updateCurrentNowPlaying{ BOOL enablewhilelocked;
%orig; BOOL showalbumname;
BOOL albumastitle;
BOOL enableinapp;
BOOL showagainwhenartavail;
BOOL isInProgress;
SBMediaController *cachedMediaController;
MPUNowPlayingController *cachedNowPlayingController;
NSString *cachedMediaInfo;
double durationMod;
BOOL isArtworkUpdated;
}
+(NotifyMusic *)sharedInstance;
-(void)dealloc;
-(void)_updateNotifyMusicPrefs;
-(BOOL)isPlaying;
-(NSString *)nowPlayingAppDisplayID;
-(UIImage *)currentNowPlayingArtwork;
-(NSDictionary *)currentNowPlayingInfo;
-(double)currentDuration;
-(BOOL)_shouldShowNotifyMusic;
-(void)_showNotifyMusic;
@end
@implementation NotifyMusic
+(NotifyMusic *)sharedInstance {
static NotifyMusic *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
-(id)init {
if (self = [super init]) {
notify_register_dispatch("com.gilshahar7.notifymusicprefs", &token, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(int token) {
[self _updateNotifyMusicPrefs];
});
}
return self;
}
-(void)dealloc {
notify_cancel(token);
[super dealloc];
}
-(void)_updateNotifyMusicPrefs {
NSString *settingsPath = @"/var/mobile/Library/Preferences/com.gilshahar7.notifymusicprefs.plist"; NSString *settingsPath = @"/var/mobile/Library/Preferences/com.gilshahar7.notifymusicprefs.plist";
NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:settingsPath]; NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:settingsPath];
BOOL enablewhilelocked = [[prefs objectForKey:@"enablewhilelocked"] boolValue]; enablewhilelocked = [[prefs objectForKey:@"enablewhilelocked"] boolValue];
BOOL showalbumname = [[prefs objectForKey:@"showalbumname"] boolValue]; showalbumname = [[prefs objectForKey:@"showalbumname"] boolValue];
BOOL enableinapp = [[prefs objectForKey:@"enableinapp"] boolValue]; albumastitle = [[prefs objectForKey:@"albumastitle"] boolValue];
enableinapp = [[prefs objectForKey:@"enableinapp"] boolValue];
showagainwhenartavail = [[prefs objectForKey:@"showagainwhenartavail"] boolValue];
}
-(void)_updateDependencyInjectionWithMC:(SBMediaController *)mediaController NPC:(MPUNowPlayingController *)nowPlayingController {
cachedMediaController = mediaController;
cachedNowPlayingController = nowPlayingController;
}
-(BOOL)isPlaying {
if (cachedNowPlayingController) return [cachedNowPlayingController isPlaying];
else if (cachedMediaController) return [cachedMediaController isPlaying];
return NO;
}
-(NSString *)nowPlayingAppDisplayID {
if (cachedNowPlayingController) return [cachedNowPlayingController nowPlayingAppDisplayID];
else if (cachedMediaController) return [[cachedMediaController nowPlayingApplication] bundleIdentifier];
return NULL;
}
-(UIImage *)currentNowPlayingArtwork {
if (cachedNowPlayingController) {
[cachedNowPlayingController setShouldUpdateNowPlayingArtwork:YES];
return [cachedNowPlayingController currentNowPlayingArtwork];
}
else if (cachedMediaController) {
if (![cachedMediaController currentNowPlayingInfo]) return NULL;
NSData *artworkData = [cachedMediaController currentNowPlayingInfo][(__bridge NSString *)kMRMediaRemoteNowPlayingInfoArtworkData];
if (!artworkData) return NULL;
return [UIImage imageWithData:artworkData];
}
return NULL;
}
-(NSDictionary *)currentNowPlayingInfo {
if (cachedNowPlayingController) return [cachedNowPlayingController currentNowPlayingInfo];
else if (cachedMediaController) return [cachedMediaController currentNowPlayingInfo];
return NULL;
}
-(double)currentDuration {
if (cachedNowPlayingController) return [cachedNowPlayingController currentDuration];
else if (cachedMediaController) {
if (![cachedMediaController currentNowPlayingInfo]) return 0;
if (![cachedMediaController currentNowPlayingInfo][(__bridge NSString *)kMRMediaRemoteNowPlayingInfoDuration]) return 0;
return [[cachedMediaController currentNowPlayingInfo][(__bridge NSString *)kMRMediaRemoteNowPlayingInfoDuration] doubleValue];
}
return 0;
}
-(BOOL)_shouldShowNotifyMusic {
if (!notifyMusicPrefsLoaded) [self _updateNotifyMusicPrefs];
NSString *frontMost = [[(SpringBoard *)[UIApplication sharedApplication] _accessibilityFrontMostApplication] bundleIdentifier];
if(!enablewhilelocked && [[%c(SBLockScreenManager) sharedInstance] isUILocked]) return NO;
if(!enableinapp && [self.nowPlayingAppDisplayID isEqualToString:frontMost])
return NO;
return YES;
}
-(void)_showNotifyMusic {
//%orig;
//if (![self _shouldShowNotifyMusic]) return;
if (isInProgress) return;
if (!self.isPlaying) return;
double currentDuration = self.currentDuration;
if (!currentDuration || currentDuration <= 0) return;
isInProgress = YES;
NSString *_title = self.currentNowPlayingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoTitle];
NSString *_artist = self.currentNowPlayingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoArtist];
NSString *_album = self.currentNowPlayingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoAlbum];
NSString *_mediaInfo = [NSString stringWithFormat:@"%@:%@:%@:%@:%d", self.nowPlayingAppDisplayID, _title, _artist, _album, (int)currentDuration];
if (![_mediaInfo isEqualToString:cachedMediaInfo]) durationMod = currentDuration - (int)currentDuration;
BOOL hasArtwork = [self.currentNowPlayingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoArtworkMIMEType] containsString:@"image"];
double delayInSeconds = 0.5; double delayInSeconds = 0.5;
if (hasArtwork) delayInSeconds = 2;
if (hasArtwork && self.currentNowPlayingArtwork == nil) delayInSeconds = 4;
if (currentDuration - (int)currentDuration != durationMod) delayInSeconds = 8;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
if(![cachedTitle isEqualToString:self.currentNowPlayingInfo[@"kMRMediaRemoteNowPlayingInfoTitle"]]){ NSString *nowPlayingAppDisplayID = self.nowPlayingAppDisplayID;
cachedTitle = [self.currentNowPlayingInfo[@"kMRMediaRemoteNowPlayingInfoTitle"] copy]; NSString *title = self.currentNowPlayingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoTitle];
NSString *frontMost = [[(SpringBoard *)[UIApplication sharedApplication] _accessibilityFrontMostApplication] bundleIdentifier]; NSString *artist = self.currentNowPlayingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoArtist];
if((enablewhilelocked || (![[%c(SBLockScreenManager) sharedInstance] isUILocked])) && self.isPlaying){ NSString *album = self.currentNowPlayingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoAlbum];
if(enableinapp || (![self.nowPlayingAppDisplayID isEqualToString:frontMost])){ NSString *mediaInfo = [NSString stringWithFormat:@"%@:%@:%@:%@:%d", nowPlayingAppDisplayID, title, artist, album, (int)self.currentDuration];
artist = [NSString stringWithFormat: @"\n%@", self.currentNowPlayingInfo[@"kMRMediaRemoteNowPlayingInfoArtist"]]; if (![mediaInfo isEqualToString:_mediaInfo]) return;
UIImage *artwork = self.currentNowPlayingArtwork;
if([self.currentNowPlayingInfo[@"kMRMediaRemoteNowPlayingInfoAlbum"] length] > 1 && showalbumname){ if ([mediaInfo isEqualToString:cachedMediaInfo] && (artwork == nil || !showagainwhenartavail || isArtworkUpdated)) return;
album = self.currentNowPlayingInfo[@"kMRMediaRemoteNowPlayingInfoAlbum"]; //if (artwork) artwork = [artwork copy];
}else{ cachedMediaInfo = [mediaInfo copy];
isArtworkUpdated = artwork != nil;
if (![self _shouldShowNotifyMusic]) return;
if(!showalbumname){
album = @"Now Playing"; album = @"Now Playing";
} }
if(self.currentNowPlayingArtwork != nil){ if (showalbumname) {
[[objc_getClass("JBBulletinManager") sharedInstance] showBulletinWithTitle:album message:[NSString stringWithFormat: @"%@%@", self.currentNowPlayingInfo[@"kMRMediaRemoteNowPlayingInfoTitle"], artist] bundleID:self.nowPlayingAppDisplayID hasSound:false soundID:0 vibrateMode:0 soundPath:@"" attachmentImage:self.currentNowPlayingArtwork overrideBundleImage:nil]; NSString *_title, *_message;
if (albumastitle) {
_title = album;
_message = [NSString stringWithFormat: @"%@\n%@", title, artist];
} else { } else {
[[objc_getClass("JBBulletinManager") sharedInstance] showBulletinWithTitle:album message:[NSString stringWithFormat: @"%@%@", self.currentNowPlayingInfo[@"kMRMediaRemoteNowPlayingInfoTitle"], artist] bundleID:self.nowPlayingAppDisplayID]; _title = title;
_message = [NSString stringWithFormat: @"%@\n%@", artist, album];
} }
if(artwork != nil){
[[%c(JBBulletinManager) sharedInstance] showBulletinWithTitle:_title message:_message bundleID:nowPlayingAppDisplayID hasSound:false soundID:0 vibrateMode:0 soundPath:@"" attachmentImage:artwork overrideBundleImage:nil];
}else{
[[%c(JBBulletinManager) sharedInstance] showBulletinWithTitle:_title message:_message bundleID:nowPlayingAppDisplayID];
} }
} else {
if ([album length] <= 0) {
album = @"Now Playing";
}
if(artwork != nil){
[[%c(JBBulletinManager) sharedInstance] showBulletinWithTitle:album message:[NSString stringWithFormat: @"%@\n%@", title, artist] bundleID:nowPlayingAppDisplayID hasSound:false soundID:0 vibrateMode:0 soundPath:@"" attachmentImage:artwork overrideBundleImage:nil];
}else{
[[%c(JBBulletinManager) sharedInstance] showBulletinWithTitle:album message:[NSString stringWithFormat: @"%@\n%@", title, artist] bundleID:nowPlayingAppDisplayID];
} }
} }
}); });
isInProgress = NO;
}
@end
%hook MPUNowPlayingController
static int token;
-(id)init {
self = %orig;
if (self) {
notify_register_dispatch("com.gilshahar7.notifymusic", &token, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(int token) {
[self _updatePlaybackState];
});
}
return self;
}
-(void)dealloc {
notify_cancel(token);
%orig;
}
/*-(void)_updateCurrentNowPlaying{
%orig;
[[NotifyMusic sharedInstance] _updateDependencyInjectionWithMC:nil NPC:self];
[[NotifyMusic sharedInstance] _showNotifyMusic];
}*/
-(void)_updatePlaybackState {
%orig;
[[NotifyMusic sharedInstance] _updateDependencyInjectionWithMC:nil NPC:self];
[[NotifyMusic sharedInstance] _showNotifyMusic];
}
%end
%hook SBMediaController
%property (retain) NSDictionary * currentNowPlayingInfo;
-(void)setNowPlayingInfo:(NSDictionary *)arg1 {
%orig;
if (UIDevice.currentDevice.systemVersion.floatValue >= 11.0) {
MRMediaRemoteGetNowPlayingInfo(dispatch_get_main_queue(), ^(CFDictionaryRef nowPlayingInfo) {
if (self.currentNowPlayingInfo) [self.currentNowPlayingInfo release];
self.currentNowPlayingInfo = [(__bridge NSDictionary *)nowPlayingInfo copy];
[[NotifyMusic sharedInstance] _updateDependencyInjectionWithMC:self NPC:nil];
[[NotifyMusic sharedInstance] _showNotifyMusic];
});
}
else notify_post("com.gilshahar7.notifymusic");
}
-(void)_nowPlayingAppIsPlayingDidChange {
%orig;
[self setNowPlayingInfo:[self _nowPlayingInfo]];
} }
%end %end

View File

@ -1,4 +1,4 @@
ARCHS = armv7 arm64 ARCHS = armv7 arm64 arm64e
include $(THEOS)/makefiles/common.mk include $(THEOS)/makefiles/common.mk
BUNDLE_NAME = notifymusicprefs BUNDLE_NAME = notifymusicprefs

View File

@ -11,6 +11,8 @@
<string>NotifyMusic</string> <string>NotifyMusic</string>
</dict> </dict>
<dict> <dict>
<key>PostNotification</key>
<string>com.gilshahar7.notifymusicprefs</string>
<key>cell</key> <key>cell</key>
<string>PSSwitchCell</string> <string>PSSwitchCell</string>
<key>default</key> <key>default</key>
@ -23,6 +25,8 @@
<string>Enable while locked</string> <string>Enable while locked</string>
</dict> </dict>
<dict> <dict>
<key>PostNotification</key>
<string>com.gilshahar7.notifymusicprefs</string>
<key>cell</key> <key>cell</key>
<string>PSSwitchCell</string> <string>PSSwitchCell</string>
<key>default</key> <key>default</key>
@ -35,6 +39,8 @@
<string>Enable inside now playing app</string> <string>Enable inside now playing app</string>
</dict> </dict>
<dict> <dict>
<key>PostNotification</key>
<string>com.gilshahar7.notifymusicprefs</string>
<key>cell</key> <key>cell</key>
<string>PSSwitchCell</string> <string>PSSwitchCell</string>
<key>default</key> <key>default</key>
@ -44,7 +50,35 @@
<key>key</key> <key>key</key>
<string>showalbumname</string> <string>showalbumname</string>
<key>label</key> <key>label</key>
<string>Show album name in title</string> <string>Show album name</string>
</dict>
<dict>
<key>PostNotification</key>
<string>com.gilshahar7.notifymusicprefs</string>
<key>cell</key>
<string>PSSwitchCell</string>
<key>default</key>
<true/>
<key>defaults</key>
<string>com.gilshahar7.notifymusicprefs</string>
<key>key</key>
<string>albumastitle</string>
<key>label</key>
<string>Album name as title</string>
</dict>
<dict>
<key>PostNotification</key>
<string>com.gilshahar7.notifymusicprefs</string>
<key>cell</key>
<string>PSSwitchCell</string>
<key>default</key>
<true/>
<key>defaults</key>
<string>com.gilshahar7.notifymusicprefs</string>
<key>key</key>
<string>showagainwhenartavail</string>
<key>label</key>
<string>Show again when albumart become available</string>
</dict> </dict>
</array> </array>
<key>title</key> <key>title</key>