/
Tweak.xm
194 lines (147 loc) · 5.5 KB
/
Tweak.xm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
//
// Tweak.xm
// Spectral
//
// Created by Adam Bell on 2014-01-02.
// Copyright (c) 2014 Adam Bell. All rights reserved.
//
%config(generator=MobileSubstrate);
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>
#import "PrivateHeaders.h"
#import "SBBlurryArtworkView.h"
#include <dlfcn.h>
#define PREFERENCES_PATH @"/User/Library/Preferences/ca.adambell.spectral.plist"
#define PREFERENCES_CHANGED_NOTIFICATION "ca.adambell.spectral.preferences-changed"
#define PREFERENCES_ENABLED_KEY @"spectralEnabled"
%group NowPlayingArtView
static SBBlurryArtworkView *_blurryArtworkView = nil;
static NSDictionary *_preferences = nil;
// Some apps are weird and set the now playing info a billion times a second... this tries to avoid that
static __weak NSData *_artworkData;
static __weak UIImage *_artworkImage;
static __weak _NowPlayingArtView *_artView = nil;
%hook NowPlayingArtPluginController
- (void)viewWillAppear:(BOOL)animated {
%orig;
[[%c(SBUIController) sharedInstance] updateLockscreenArtwork];
}
- (void)viewWillDisappear:(BOOL)animated {
%orig;
[[%c(SBUIController) sharedInstance] updateLockscreenArtwork];
}
%end
%hook SBUIController
- (id)init {
SBUIController *controller = %orig;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(currentSongChanged:)
name:@"SBMediaNowPlayingChangedNotification"
object:nil];
_blurryArtworkView = [[SBBlurryArtworkView alloc] initWithFrame:CGRectZero];
return controller;
}
%new
- (void)updateLockscreenArtwork {
[[NSOperationQueue mainQueue] addOperationWithBlock:^(){
UIImage *artwork = nil;
if ([[UIDevice currentDevice].systemVersion floatValue] < 8.0) {
SBMediaController *mediaController = [%c(SBMediaController) sharedInstance];
//TODO: Try to limit the number of times this needs to be run because it's expensive
NSData *artworkData = [[mediaController _nowPlayingInfo] valueForKey:@"artworkData"];
if (artworkData == _artworkData) {
return;
}
_artworkData = artworkData;
artwork = mediaController.artwork;
} else {
artwork = _artView.artworkView.image;
}
if (artwork != _artworkImage) {
self.lockscreenArtworkImage = artwork;
_artworkImage = artwork;
}
}];
}
%new
- (void)currentSongChanged:(NSNotification *)notification {
[self updateLockscreenArtwork];
}
%new
- (void)blurryArtworkPreferencesChanged {
NSDictionary *prefs = [[NSDictionary alloc] initWithContentsOfFile:PREFERENCES_PATH];
BOOL enabled = [[prefs valueForKey:PREFERENCES_ENABLED_KEY] boolValue];
_blurryArtworkView.hidden = !enabled;
}
%new
- (void)setLockscreenArtworkImage:(UIImage *)artworkImage {
_blurryArtworkView.artworkImage = artworkImage;
}
%new
- (SBBlurryArtworkView *)blurryArtworkView {
return _blurryArtworkView;
}
// Fix for the original lockscreen wallpaper not showing when locked and paused
- (void)cleanUpOnFrontLocked {
%orig;
SBMediaController *mediaController = [%c(SBMediaController) sharedInstance];
if (!mediaController.isPlaying) {
self.lockscreenArtworkImage = nil;
}
}
%end
%hook SBMediaController
- (void)setNowPlayingInfo:(id)info
{
%orig;
[[%c(SBUIController) sharedInstance] updateLockscreenArtwork];
}
%end
%hook _NowPlayingArtView
- (id)initWithFrame:(CGRect)frame
{
id orig = %orig;
_artView = orig;
return orig;
}
- (void)layoutSubviews {
%orig;
_blurryArtworkView.frame = [UIScreen mainScreen].bounds;
// Hack to find the SBLockScreenScrollView and use it as a reference point
// ...don't ever use this in shipping code :P
SBLockScreenScrollView *scrollView = nil;
UIView *superview = self.superview;
Class SBLockScreenScrollViewClass = %c(SBLockScreenScrollView);
while (scrollView == nil) {
for (UIView *subview in superview.subviews) {
if ([subview isKindOfClass:SBLockScreenScrollViewClass])
scrollView = (SBLockScreenScrollView *)subview;
}
superview = superview.superview;
if (superview == nil)
break;
}
if (_blurryArtworkView.superview != nil)
[_blurryArtworkView removeFromSuperview];
if (scrollView != nil)
[scrollView.superview insertSubview:_blurryArtworkView belowSubview:scrollView];
}
%end
%end
static void PreferencesChangedCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
_preferences = [[NSDictionary alloc] initWithContentsOfFile:PREFERENCES_PATH];
[[%c(SBUIController) sharedInstance] blurryArtworkPreferencesChanged];
}
%ctor {
dlopen("/System/Library/SpringBoardPlugins/NowPlayingArtLockScreen.lockbundle/NowPlayingArtLockScreen", 2);
_preferences = [[NSDictionary alloc] initWithContentsOfFile:PREFERENCES_PATH];
if (_preferences == nil) {
_preferences = @{ PREFERENCES_ENABLED_KEY : @(YES) };
[_preferences writeToFile:PREFERENCES_PATH atomically:YES];
}
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, PreferencesChangedCallback, CFSTR(PREFERENCES_CHANGED_NOTIFICATION), NULL, CFNotificationSuspensionBehaviorCoalesce);
%init(NowPlayingArtView);
}