You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

282 lines
11KB

  1. #import "notify.h"
  2. #import <UIKit/UIKit.h>
  3. #import <MediaRemote/MediaRemote.h>
  4. @interface JBBulletinManager : NSObject
  5. +(id)sharedInstance;
  6. -(id)showBulletinWithTitle:(NSString *)title message:(NSString *)message bundleID:(NSString *)bundleID;
  7. -(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;
  8. @end
  9. @interface SpringBoard
  10. -(id)_accessibilityFrontMostApplication;
  11. @end
  12. @interface UIApplication (myTweak)
  13. +(id)sharedApplication;
  14. - (id)bundleIdentifier;
  15. @end
  16. @interface SBLockScreenManager
  17. +(SBLockScreenManager *)sharedInstance;
  18. -(BOOL)isUILocked;
  19. @end
  20. @interface MPUNowPlayingController
  21. @property bool isPlaying;
  22. @property (nonatomic,readonly) NSString * nowPlayingAppDisplayID;
  23. @property (nonatomic,readonly) UIImage * currentNowPlayingArtwork;
  24. @property (nonatomic,readonly) NSDictionary * currentNowPlayingInfo;
  25. @property (nonatomic,readonly) double currentElapsed;
  26. @property (nonatomic,readonly) double currentDuration;
  27. -(void)_updateCurrentNowPlaying;
  28. -(void)_updatePlaybackState;
  29. -(void)setShouldUpdateNowPlayingArtwork:(BOOL)arg1 ;
  30. @end
  31. @interface SBMediaController
  32. @property (retain) NSDictionary * currentNowPlayingInfo;
  33. -(id/*SBApplication **/)nowPlayingApplication;
  34. -(void)setNowPlayingInfo:(NSDictionary *)arg1 ;
  35. -(BOOL)isPlaying;
  36. @end
  37. @interface NotifyMusic : NSObject {
  38. int token;
  39. BOOL notifyMusicPrefsLoaded;
  40. BOOL enablewhilelocked;
  41. BOOL showalbumname;
  42. BOOL albumastitle;
  43. BOOL enableinapp;
  44. BOOL showagainwhenartavail;
  45. BOOL isInProgress;
  46. SBMediaController *cachedMediaController;
  47. MPUNowPlayingController *cachedNowPlayingController;
  48. NSString *cachedMediaInfo;
  49. double durationMod;
  50. BOOL isArtworkUpdated;
  51. }
  52. +(NotifyMusic *)sharedInstance;
  53. -(void)dealloc;
  54. -(void)_updateNotifyMusicPrefs;
  55. -(BOOL)isPlaying;
  56. -(NSString *)nowPlayingAppDisplayID;
  57. -(UIImage *)currentNowPlayingArtwork;
  58. -(NSDictionary *)currentNowPlayingInfo;
  59. -(double)currentDuration;
  60. -(BOOL)_shouldShowNotifyMusic;
  61. -(void)_showNotifyMusic;
  62. @end
  63. @implementation NotifyMusic
  64. +(NotifyMusic *)sharedInstance {
  65. static NotifyMusic *instance = nil;
  66. static dispatch_once_t onceToken;
  67. dispatch_once(&onceToken, ^{
  68. instance = [[self alloc] init];
  69. });
  70. return instance;
  71. }
  72. -(id)init {
  73. if (self = [super init]) {
  74. notify_register_dispatch("com.gilshahar7.notifymusicprefs", &token, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(int token) {
  75. [self _updateNotifyMusicPrefs];
  76. });
  77. }
  78. return self;
  79. }
  80. -(void)dealloc {
  81. notify_cancel(token);
  82. [super dealloc];
  83. }
  84. -(void)_updateNotifyMusicPrefs {
  85. NSString *settingsPath = @"/var/mobile/Library/Preferences/com.gilshahar7.notifymusicprefs.plist";
  86. NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:settingsPath];
  87. enablewhilelocked = [[prefs objectForKey:@"enablewhilelocked"] boolValue];
  88. showalbumname = [[prefs objectForKey:@"showalbumname"] boolValue];
  89. albumastitle = [[prefs objectForKey:@"albumastitle"] boolValue];
  90. enableinapp = [[prefs objectForKey:@"enableinapp"] boolValue];
  91. showagainwhenartavail = [[prefs objectForKey:@"showagainwhenartavail"] boolValue];
  92. }
  93. -(void)_updateDependencyInjectionWithMC:(SBMediaController *)mediaController NPC:(MPUNowPlayingController *)nowPlayingController {
  94. cachedMediaController = mediaController;
  95. cachedNowPlayingController = nowPlayingController;
  96. }
  97. -(BOOL)isPlaying {
  98. if (cachedNowPlayingController) return [cachedNowPlayingController isPlaying];
  99. else if (cachedMediaController) return [cachedMediaController isPlaying];
  100. return NO;
  101. }
  102. -(NSString *)nowPlayingAppDisplayID {
  103. if (cachedNowPlayingController) return [cachedNowPlayingController nowPlayingAppDisplayID];
  104. else if (cachedMediaController) return [[cachedMediaController nowPlayingApplication] bundleIdentifier];
  105. return NULL;
  106. }
  107. -(UIImage *)currentNowPlayingArtwork {
  108. if (cachedNowPlayingController) {
  109. [cachedNowPlayingController setShouldUpdateNowPlayingArtwork:YES];
  110. return [cachedNowPlayingController currentNowPlayingArtwork];
  111. }
  112. else if (cachedMediaController) {
  113. if (![cachedMediaController currentNowPlayingInfo]) return NULL;
  114. NSData *artworkData = [cachedMediaController currentNowPlayingInfo][(__bridge NSString *)kMRMediaRemoteNowPlayingInfoArtworkData];
  115. if (!artworkData) return NULL;
  116. return [UIImage imageWithData:artworkData];
  117. }
  118. return NULL;
  119. }
  120. -(NSDictionary *)currentNowPlayingInfo {
  121. if (cachedNowPlayingController) return [cachedNowPlayingController currentNowPlayingInfo];
  122. else if (cachedMediaController) return [cachedMediaController currentNowPlayingInfo];
  123. return NULL;
  124. }
  125. -(double)currentDuration {
  126. if (cachedNowPlayingController) return [cachedNowPlayingController currentDuration];
  127. else if (cachedMediaController) {
  128. if (![cachedMediaController currentNowPlayingInfo]) return 0;
  129. if (![cachedMediaController currentNowPlayingInfo][(__bridge NSString *)kMRMediaRemoteNowPlayingInfoDuration]) return 0;
  130. return [[cachedMediaController currentNowPlayingInfo][(__bridge NSString *)kMRMediaRemoteNowPlayingInfoDuration] doubleValue];
  131. }
  132. return 0;
  133. }
  134. -(BOOL)_shouldShowNotifyMusic {
  135. if (!notifyMusicPrefsLoaded) [self _updateNotifyMusicPrefs];
  136. NSString *frontMost = [[(SpringBoard *)[UIApplication sharedApplication] _accessibilityFrontMostApplication] bundleIdentifier];
  137. if(!enablewhilelocked && [[%c(SBLockScreenManager) sharedInstance] isUILocked]) return NO;
  138. if(!enableinapp && [self.nowPlayingAppDisplayID isEqualToString:frontMost])
  139. return NO;
  140. return YES;
  141. }
  142. -(void)_showNotifyMusic {
  143. //%orig;
  144. //if (![self _shouldShowNotifyMusic]) return;
  145. if (isInProgress) return;
  146. if (!self.isPlaying) return;
  147. double currentDuration = self.currentDuration;
  148. if (!currentDuration || currentDuration <= 0) return;
  149. isInProgress = YES;
  150. NSString *_title = self.currentNowPlayingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoTitle];
  151. NSString *_artist = self.currentNowPlayingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoArtist];
  152. NSString *_album = self.currentNowPlayingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoAlbum];
  153. NSString *_mediaInfo = [NSString stringWithFormat:@"%@:%@:%@:%@:%d", self.nowPlayingAppDisplayID, _title, _artist, _album, (int)currentDuration];
  154. if (![_mediaInfo isEqualToString:cachedMediaInfo]) durationMod = currentDuration - (int)currentDuration;
  155. BOOL hasArtwork = [self.currentNowPlayingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoArtworkMIMEType] containsString:@"image"];
  156. double delayInSeconds = 0.5;
  157. if (hasArtwork) delayInSeconds = 2;
  158. if (hasArtwork && self.currentNowPlayingArtwork == nil) delayInSeconds = 4;
  159. if (currentDuration - (int)currentDuration != durationMod) delayInSeconds = 8;
  160. dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
  161. dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
  162. NSString *nowPlayingAppDisplayID = self.nowPlayingAppDisplayID;
  163. NSString *title = self.currentNowPlayingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoTitle];
  164. NSString *artist = self.currentNowPlayingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoArtist];
  165. NSString *album = self.currentNowPlayingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoAlbum];
  166. NSString *mediaInfo = [NSString stringWithFormat:@"%@:%@:%@:%@:%d", nowPlayingAppDisplayID, title, artist, album, (int)self.currentDuration];
  167. if (![mediaInfo isEqualToString:_mediaInfo]) return;
  168. UIImage *artwork = self.currentNowPlayingArtwork;
  169. if ([mediaInfo isEqualToString:cachedMediaInfo] && (artwork == nil || !showagainwhenartavail || isArtworkUpdated)) return;
  170. //if (artwork) artwork = [artwork copy];
  171. cachedMediaInfo = [mediaInfo copy];
  172. isArtworkUpdated = artwork != nil;
  173. if (![self _shouldShowNotifyMusic]) return;
  174. if(!showalbumname){
  175. album = @"Now Playing";
  176. }
  177. if (showalbumname) {
  178. NSString *_title, *_message;
  179. if (albumastitle) {
  180. _title = album;
  181. _message = [NSString stringWithFormat: @"%@\n%@", title, artist];
  182. } else {
  183. _title = title;
  184. _message = [NSString stringWithFormat: @"%@\n%@", artist, album];
  185. }
  186. if(artwork != nil){
  187. [[%c(JBBulletinManager) sharedInstance] showBulletinWithTitle:_title message:_message bundleID:nowPlayingAppDisplayID hasSound:false soundID:0 vibrateMode:0 soundPath:@"" attachmentImage:artwork overrideBundleImage:nil];
  188. }else{
  189. [[%c(JBBulletinManager) sharedInstance] showBulletinWithTitle:_title message:_message bundleID:nowPlayingAppDisplayID];
  190. }
  191. } else {
  192. if ([album length] <= 0) {
  193. album = @"Now Playing";
  194. }
  195. if(artwork != nil){
  196. [[%c(JBBulletinManager) sharedInstance] showBulletinWithTitle:album message:[NSString stringWithFormat: @"%@\n%@", title, artist] bundleID:nowPlayingAppDisplayID hasSound:false soundID:0 vibrateMode:0 soundPath:@"" attachmentImage:artwork overrideBundleImage:nil];
  197. }else{
  198. [[%c(JBBulletinManager) sharedInstance] showBulletinWithTitle:album message:[NSString stringWithFormat: @"%@\n%@", title, artist] bundleID:nowPlayingAppDisplayID];
  199. }
  200. }
  201. });
  202. isInProgress = NO;
  203. }
  204. @end
  205. %hook MPUNowPlayingController
  206. static int token;
  207. -(id)init {
  208. self = %orig;
  209. if (self) {
  210. notify_register_dispatch("com.gilshahar7.notifymusic", &token, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(int token) {
  211. [self _updatePlaybackState];
  212. });
  213. }
  214. return self;
  215. }
  216. -(void)dealloc {
  217. notify_cancel(token);
  218. %orig;
  219. }
  220. /*-(void)_updateCurrentNowPlaying{
  221. %orig;
  222. [[NotifyMusic sharedInstance] _updateDependencyInjectionWithMC:nil NPC:self];
  223. [[NotifyMusic sharedInstance] _showNotifyMusic];
  224. }*/
  225. -(void)_updatePlaybackState {
  226. %orig;
  227. [[NotifyMusic sharedInstance] _updateDependencyInjectionWithMC:nil NPC:self];
  228. [[NotifyMusic sharedInstance] _showNotifyMusic];
  229. }
  230. %end
  231. %hook SBMediaController
  232. %property (retain) NSDictionary * currentNowPlayingInfo;
  233. -(void)setNowPlayingInfo:(NSDictionary *)arg1 {
  234. %orig;
  235. if (UIDevice.currentDevice.systemVersion.floatValue >= 11.0) {
  236. MRMediaRemoteGetNowPlayingInfo(dispatch_get_main_queue(), ^(CFDictionaryRef nowPlayingInfo) {
  237. if (self.currentNowPlayingInfo) [self.currentNowPlayingInfo release];
  238. self.currentNowPlayingInfo = [(__bridge NSDictionary *)nowPlayingInfo copy];
  239. [[NotifyMusic sharedInstance] _updateDependencyInjectionWithMC:self NPC:nil];
  240. [[NotifyMusic sharedInstance] _showNotifyMusic];
  241. });
  242. }
  243. else notify_post("com.gilshahar7.notifymusic");
  244. }
  245. -(void)_nowPlayingAppIsPlayingDidChange {
  246. %orig;
  247. [self setNowPlayingInfo:[self _nowPlayingInfo]];
  248. }
  249. %end