forked from robbiehanson/AlarmClock
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathITunesData.m
257 lines (209 loc) · 8.33 KB
/
ITunesData.m
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
#import "ITunesData.h"
#import "Prefs.h"
@implementation ITunesData
// INIT, DEALLOC
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (id)init
{
if(self = [super init])
{
NSError * error = nil;
library = [[ITLibrary alloc] initWithAPIVersion:@"1.0" error: &error];
if (error) {
[[NSApplication sharedApplication] presentError:error];
}
}
return self;
}
- (void)dealloc
{
NSLog(@"Destroying %@", self);
[library release];
[super dealloc];
}
// DATA EXTRACTION
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
Returns array of playlist dictionaries.
Returns an array, which may be accessed like any other array (objectAtIndex, count, etc...)
Each object in the array is an NSDictionary, which contains info for that particular playlist.
Each playlist dictionary contains the following keys (among others):
Name - Name of playlist
Playlist ID - Unique ID number of playlist, which should be used as name and index in array may change over time.
Playlist Items - Array of dictionaries, each containing a track ID number.
**/
- (NSArray<ITLibPlaylist *> *)playlists
{
return [library allPlaylists];
}
/**
Returns the playlist that has the given playlist ID.
Searches all playlists for the one with the given ID.
When this is found, it is returned.
Otherwise, nil is returned.
@param playlistID - The index of the desired playlist in the library's playlists array.
**/
- (ITLibPlaylist *)playlistForID:(int)playlistID
{
if(playlistID >= 0)
return [[self playlists] objectAtIndex:playlistID];
else
return nil;
}
/**
Returns the dictionary for the given track index.
Each track dictionary contains the following keys (among others):
Name - Name of song (IE - Your Body is a Wonderland)
Artist - Name of artist (IE - John Mayer)
Album - Name of album track is from (IE - Room For Squares)
Total Time - Number of milliseconds in song
Location - File URL
@param trackID - The ID of the desired track in the library's `allMediaItems` array.
**/
- (ITLibMediaItem *)trackForID:(int)trackID
{
if (trackID < [[library allMediaItems] count])
{
return [[library allMediaItems] objectAtIndex:trackID];
}
else
{
return nil;
}
}
/**
Returns the index of the track (in the main library) for the given track ID.
Although tracks are stored in a dictionary, and accessed via a key (their track ID),
an index may be needed when displaying the information in a table, and needing the position of the track.
If the track is found in the library, the index of the track is returned.
If it's not found, -1 is returned.
@param trackID - The persistent ID of the desired track.
**/
- (int)trackIndexForPersistentID:(NSNumber *)trackID
{
// Note: The main library is always the first playlist
return [self trackIndexForPersistentID:trackID withPlaylistID:0];
}
/**
Returns the index of the track (in the given playlist) for the given track ID.
Although tracks are stored in a dictionary, and accessed via a key (their track ID),
an index may be needed when displaying the information in a table, and needing the position of the track.
If the track is found in the given playlist, the index of the track is returned.
If it's not found, -1 is returned.
@param trackID - The persistent ID of the desired track.
@param playlistIndex - The index of the playlist that should be searched for the position of the given track.
**/
- (int)trackIndexForPersistentID:(NSNumber *)trackPersistentID withPlaylistID:(int)playlistIndex
{
// First make sure the playlistIndex is valid
if((playlistIndex < 0) || (playlistIndex >= [[self playlists] count]))
{
return -1;
}
NSArray<ITLibMediaItem *> *playlist = [[self playlistForID:playlistIndex] items];
int index = 0;
BOOL found = NO;
while(!found && (index < [playlist count]))
{
NSNumber* trackRef = [[playlist objectAtIndex:index] persistentID];
if([trackPersistentID isEqualToNumber:trackRef])
found = YES;
else
index++;
}
if(found)
return index;
else
return -1;
}
// ID VALIDATION
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
Returns the proper trackID for the given persistentID.
Track ID's are not persistent across multiple instances of iTunesData.
Thus storing the trackID will not guarantee the same song will be played after the music library is altered.
Luckily Apple provides a persistentID which may be used to lookup a song.
However, the trackID is the key in which to lookup the song, so it is more or less necessary.
This method provides a means with which to map a persistentID to its corresponding trackID.
The trackID which is assumed to be correct is passed along with it.
This helps, because often times it is correct, and thus a search may be avoided.
@param trackID - The old trackID that was used for the song with this persistentID.
@param persistentTrackID - This is the persistentID for the song, which doesn't change as the library is altered.
@return The trackID that currently corresponds to the given persistentID, or -1 if the persistentID was not found.
**/
- (int)validateTrackID:(int)trackID withPersistentTrackID:(NSNumber *)persistentTrackID
{
// Ignore the validation request if the persistentTrackID is nil (uninitialized)
// This will happen for new alarms
// It will also happen after upgrading to 2.2.1, where prior versions didn't support persistent ID's.
if(persistentTrackID == nil)
{
return trackID;
}
// Get the track for the specified trackID
ITLibMediaItem *item = [self trackForID:trackID];
// Does the persistentID match the one given
if((item != nil) && [[item persistentID] isEqualToNumber:persistentTrackID])
{
// It's a match! Just return the original trackID.
return trackID;
}
// The trackID has changed!
// Now we have to loop through the tracks, and find the one with the correct persistentID
int result = -1;
for (int i = 0; i < [[library allMediaItems] count]; i++)
{
ITLibMediaItem *currentTrack = [[library allMediaItems] objectAtIndex:i];
if ([[currentTrack persistentID] isEqualToNumber:persistentTrackID])
{
result = i;
break;
}
}
return result;
}
/**
Returns the proper playlistID for the given persistentID.
Playlist ID's are not persistent across multiple instances of iTunesData.
Thus storing the playlistID will not guarantee the same playlist will be played after the music library is altered.
Luckily Apple provides a persistentID which may be used to lookup a playlist.
However, the playlistID is the key in which to lookup the playlist, so it is more or less necessary.
This method provides a means with which to map a persistentID to its corresponding playlistID.
The playlistID which is assumed to be correct is passed along with it.
This helps, because often times it is correct, and thus a search may be avoided.
@param playlistID - The old playlistID that was used for the song with this persistentID.
@param persistentPlaylistID - This is the persistentID for the playlist, which doesn't change as the library is altered.
@return The playlistID that currently corresponds to the given persistentID, or -1 if the persistentID was not found.
**/
- (int)validatePlaylistID:(int)playlistID withPersistentPlaylistID:(NSNumber *)persistentPlaylistID
{
// Ignore the validation request if the persistentPlaylistID is nil (uninitialized)
// This will happen for new alarms
// It will also happen after upgrading to 2.2.1, where prior versions didn't support persistent ID's.
if(persistentPlaylistID == nil)
{
return playlistID;
}
// Get the playlist for the specified playlistID
ITLibPlaylist *playlist = [self playlistForID:playlistID];
// Does the persistentID match the one given
if((playlist != nil) && [[playlist persistentID] isEqualToNumber:persistentPlaylistID])
{
// It's a match.! Just return the original playlistID.
return playlistID;
}
// The playlistID has changed!
// Now we have to loop through the playlists, and find the one with the correct persistentID
int result = -1;
for (int i = 0; i < [[library allPlaylists] count]; i++)
{
ITLibPlaylist *currentPlaylist = [[library allPlaylists] objectAtIndex:i];
if ([[currentPlaylist persistentID] isEqualToNumber:persistentPlaylistID])
{
result = i;
break;
}
}
return result;
}
@end