]> git.saurik.com Git - cydget.git/blobdiff - CydgetLoader.mm
Implement Cydget-specific media/bulletins @media.
[cydget.git] / CydgetLoader.mm
index 3ea3c7b8b55ca12d80fd589130a4cf013f06976b..823cb27a06e75f50f2f1dd537b5efb7d2246064e 100644 (file)
@@ -60,17 +60,50 @@ MSInitialize {
     }
 }
 
+@interface SBLockScreenNowPlayingPluginController : NSObject
+- (BOOL) isNowPlayingPluginActive;
+@end
+
+@interface SBLockScreenViewController : UIViewController
+- (SBLockScreenView *) lockScreenView;
+- (BOOL) isShowingMediaControls;
+- (void) _toggleMediaControls;
+@end
+
+@interface SBLockScreenManager : NSObject
++ (SBLockScreenManager *) sharedInstance;
+- (SBLockScreenViewController *) lockScreenViewController;
+@end
+
 static bool menu_;
 
 static _H<NSDictionary> settings_;
 static _H<NSMutableArray> cydgets_;
 static size_t active_;
 static unsigned online_;
+static bool nowplaying_;
+
+static bool NowPlaying() {
+    if (kCFCoreFoundationVersionNumber < 800)
+        return false;
+    if (!nowplaying_)
+        return false;
+
+    SBLockScreenViewController *controller([[$SBLockScreenManager sharedInstance] lockScreenViewController]);
+    if (controller != nil) {
+        SBLockScreenNowPlayingPluginController *now(MSHookIvar<SBLockScreenNowPlayingPluginController *>(controller, "_nowPlayingController"));
+        if (now != nil && [now isNowPlayingPluginActive])
+            return true;
+    }
+
+    return false;
+}
 
 @interface CydgetController : NSObject {
 }
 
 + (NSDictionary *) currentConfiguration;
++ (NSString *) currentPath;
 
 @end
 
@@ -81,6 +114,11 @@ static unsigned online_;
     return [cydget objectForKey:@"CYConfiguration"] ?: [cydget objectForKey:@"Configuration"];
 }
 
++ (NSDictionary *) currentPath {
+    NSDictionary *cydget([cydgets_ objectAtIndex:active_]);
+    return [cydget objectForKey:@"CYPath"];
+}
+
 @end
 
 @interface SBUserAgent : NSObject
@@ -157,19 +195,49 @@ MSInstanceMessageHook1(void, SpringBoard, handleKeyEvent, GSEventRef, event) {
     return MSSuperCall(event);
 }
 
+bool media_;
+
+MSInstanceMessageHook0(void, SBLockScreenViewController, _toggleMediaControls) {
+    if (!media_)
+        MSOldCall();
+}
+
+MSInstanceMessageHook0(BOOL, SBLockScreenViewController, handleMenuButtonDoubleTap) {
+    menu_ = false;
+    BOOL value(MSOldCall());
+    if (kCFCoreFoundationVersionNumber >= 800)
+        [self _toggleMediaControls];
+    return value;
+}
+
 MSInstanceMessageHook0(BOOL, SBLockScreenManager, handleMenuButtonTap) {
-    if (!MSOldCall() && menu_) {
-        [[cydgets_ objectAtIndex:active_] disableCydget];
+    media_ = true;
+    BOOL value(MSOldCall());
+    media_ = false;
+
+    if (!value && menu_) {
+        if (active_ != _not(size_t))
+            [[cydgets_ objectAtIndex:active_] disableCydget];
         active_ = (active_ + 1) % [cydgets_ count];
         [[cydgets_ objectAtIndex:active_] enableCydget];
+        // XXX: or siri doesn't disappear correctly
+        return kCFCoreFoundationVersionNumber >= 800 ? value : YES;
     }
 
-    return YES;
+    return value;
 }
 
 void Activate_() {
     menu_ = false;
-    [[cydgets_ objectAtIndex:active_] enableCydget];
+    if (NowPlaying()) {
+        for (active_ = 0; active_ != [cydgets_ count]; ++active_)
+            if ([[[cydgets_ objectAtIndex:active_] objectForKey:@"CYName"] isEqualToString:@"AwayView"])
+                break;
+        if (active_ == [cydgets_ count])
+            active_ = _not(size_t);
+    }
+    if (active_ != _not(size_t))
+        [[cydgets_ objectAtIndex:active_] enableCydget];
 }
 
 static void Undim_(SBAwayController *self) {
@@ -195,7 +263,8 @@ MSInstanceMessageHook1(void, SBAwayController, undimScreen, BOOL, undim) {
 }
 
 static void Deactivate_() {
-    [[cydgets_ objectAtIndex:active_] disableCydget];
+    if (active_ != _not(size_t))
+        [[cydgets_ objectAtIndex:active_] disableCydget];
     active_ = 0;
 }
 
@@ -214,6 +283,11 @@ MSInstanceMessageHook1(void, SBUserAgent, dimScreen, BOOL, dim) {
     MSOldCall(dim);
 }
 
+MSInstanceMessageHook0(void, SpringBoard, _menuButtonWasHeld) {
+    menu_ = false;
+    MSOldCall();
+}
+
 MSInstanceMessageHook1(void, SpringBoard, _menuButtonDown, GSEventRef, event) {
     menu_ = true;
     MSOldCall(event);
@@ -242,6 +316,8 @@ static void CydgetSetup() {
     NSString *plist([NSString stringWithFormat:@"%@/Library/Preferences/com.saurik.Cydget.plist", NSHomeDirectory()]);
     settings_ = [NSMutableDictionary dictionaryWithContentsOfFile:plist] ?: [NSMutableDictionary dictionary];
 
+    nowplaying_ = [[settings_ objectForKey:@"NowPlaying"] boolValue];
+
     NSArray *cydgets([settings_ objectForKey:@"LockCydgets"] ?: [NSArray arrayWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:
         @"Welcome", @"Name", [NSNumber numberWithBool:YES], @"Active", nil
     ], [NSDictionary dictionaryWithObjectsAndKeys:
@@ -250,9 +326,15 @@ static void CydgetSetup() {
 
     cydgets_ = [NSMutableArray arrayWithCapacity:4];
     for (NSDictionary *cydget in cydgets)
-        if ([[cydget objectForKey:@"Active"] boolValue])
-            if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/%@.cydget/Info.plist", Cydgets_, [cydget objectForKey:@"Name"]]])
+        if ([[cydget objectForKey:@"Active"] boolValue]) {
+            NSString *name([cydget objectForKey:@"Name"]);
+            NSString *path([NSString stringWithFormat:@"%@/%@.cydget/Info.plist", Cydgets_, name]);
+            if (NSMutableDictionary *info = [NSMutableDictionary dictionaryWithContentsOfFile:path]) {
+                [info setObject:name forKey:@"CYName"];
+                [info setObject:path forKey:@"CYPath"];
                 [cydgets_ addObject:info];
+            }
+        }
 
     if ([cydgets_ count] == 0)
         cydgets_ = nil;
@@ -262,7 +344,7 @@ static void CydgetSetup() {
 MSInstanceMessageHook1(id, SBLockScreenView, initWithFrame, CGRect, frame) {
     self = MSOldCall(frame);
     CydgetSetup();
-    [[cydgets_ objectAtIndex:active_] enableCydget];
+    Activate_();
     return self;
 }