Merge lp:~urbanape/ubuntuone-ios-music/chunked-downloads into lp:ubuntuone-ios-music
- chunked-downloads
- Merge into trunk
Proposed by
Zachery Bir
Status: | Merged |
---|---|
Approved by: | Jason Foreman |
Approved revision: | 235 |
Merged at revision: | 215 |
Proposed branch: | lp:~urbanape/ubuntuone-ios-music/chunked-downloads |
Merge into: | lp:ubuntuone-ios-music |
Diff against target: |
4309 lines (+2621/-931) 58 files modified
Models/Album.h (+26/-0) Models/Album.m (+114/-0) Models/Artist.h (+26/-0) Models/Artist.m (+114/-0) Models/Generated/_Album.h (+122/-0) Models/Generated/_Album.m (+86/-0) Models/Generated/_Artist.h (+97/-0) Models/Generated/_Artist.m (+79/-0) Models/Generated/_Playlist.h (+79/-0) Models/Generated/_Playlist.m (+68/-0) Models/Generated/_PlaylistSongIndex.h (+79/-0) Models/Generated/_PlaylistSongIndex.m (+81/-0) Models/Generated/_Song.h (+327/-0) Models/Generated/_Song.m (+298/-0) Models/Playlist.h (+29/-0) Models/Playlist.m (+130/-0) Models/PlaylistSongIndex.h (+20/-0) Models/PlaylistSongIndex.m (+22/-0) Models/Song.h (+25/-0) Models/Song.m (+96/-0) U1Music-Info.plist (+1/-1) U1Music.xcodeproj/project.pbxproj (+87/-23) controls/AlbumArtistUITableViewCell.h (+3/-0) controls/AlbumArtistUITableViewCell.m (+1/-1) controls/AlbumUITableViewCell.h (+3/-0) controls/AlbumUITableViewCell.m (+1/-1) controls/ArtistUITableViewCell.h (+24/-0) controls/ArtistUITableViewCell.m (+23/-0) controls/PlaylistUITableViewCell.h (+23/-0) controls/PlaylistUITableViewCell.m (+22/-0) models/Album.h (+0/-58) models/Album.m (+0/-131) models/Artist.h (+0/-59) models/Artist.m (+0/-135) models/Playlist.h (+0/-47) models/Playlist.m (+0/-136) models/PlaylistSongIndex.h (+0/-32) models/PlaylistSongIndex.m (+0/-27) models/Song.h (+0/-67) models/Song.m (+0/-113) music.xcdatamodeld/.xccurrentversion (+1/-1) utilities/AlbumParser.m (+1/-1) utilities/ArtistParser.m (+1/-1) utilities/Globals.h (+1/-0) utilities/Globals.m (+6/-0) utilities/PlaylistParser.m (+1/-1) utilities/operations/Downloader.m (+117/-26) utilities/operations/U1ChunkDownloadOperation.h (+24/-0) utilities/operations/U1ChunkDownloadOperation.m (+68/-0) utilities/operations/U1SerializedDownloadOperation.h (+22/-0) utilities/operations/U1SerializedDownloadOperation.m (+57/-0) view_controllers/AlbumListViewController.m (+33/-0) view_controllers/AlbumViewController.m (+59/-59) view_controllers/ArtistListViewController.m (+46/-5) view_controllers/ArtistViewController.m (+34/-1) view_controllers/PlaylistListViewController.m (+43/-2) view_controllers/PlaylistViewController.m (+1/-1) xibs/MainWindow.xib (+0/-2) |
To merge this branch: | bzr merge lp:~urbanape/ubuntuone-ios-music/chunked-downloads |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jason Foreman (community) | Approve | ||
Review via email: mp+91498@code.launchpad.net |
Commit message
Description of the change
This branch provides for downloading files in chunks. This only replaces the downloader's functionality; it doesn't provide means to resume partial downloads.
To post a comment you must log in.
Revision history for this message
Zachery Bir (urbanape) wrote : | # |
Revision history for this message
Jason Foreman (threeve) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory 'Models' |
2 | === added file 'Models/Album.h' |
3 | --- Models/Album.h 1970-01-01 00:00:00 +0000 |
4 | +++ Models/Album.h 2012-02-03 20:23:18 +0000 |
5 | @@ -0,0 +1,26 @@ |
6 | +// |
7 | +// Copyright 2012 Canonical Ltd. |
8 | +// |
9 | +// This program is free software: you can redistribute it and/or modify it |
10 | +// under the terms of the GNU Affero General Public License version 3, |
11 | +// as published by the Free Software Foundation. |
12 | +// |
13 | +// This program is distributed in the hope that it will be useful, but |
14 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
15 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
16 | +// PURPOSE. See the GNU Affero General Public License for more details. |
17 | +// |
18 | +// You should have received a copy of the GNU Affero General Public License |
19 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | + |
21 | +#import "_Album.h" |
22 | + |
23 | +@interface Album : _Album {} |
24 | ++ (BOOL)albumWithIdExists:(NSString*)anAlbumId; |
25 | ++ (Album*)albumWithId:(NSString*)anAlbumId; |
26 | ++ (Album*)albumWithTitle:(NSString*)albumTitle artist:(NSString*)albumArtist; |
27 | +- (BOOL)matchesSearchQuery:(NSString *)query; |
28 | +- (NSError*)loadSongs; |
29 | +- (NSString*)dearticlizedTitle; |
30 | +- (BOOL)hasCachedSongs; |
31 | +@end |
32 | |
33 | === added file 'Models/Album.m' |
34 | --- Models/Album.m 1970-01-01 00:00:00 +0000 |
35 | +++ Models/Album.m 2012-02-03 20:23:18 +0000 |
36 | @@ -0,0 +1,114 @@ |
37 | +// |
38 | +// Copyright 2012 Canonical Ltd. |
39 | +// |
40 | +// This program is free software: you can redistribute it and/or modify it |
41 | +// under the terms of the GNU Affero General Public License version 3, |
42 | +// as published by the Free Software Foundation. |
43 | +// |
44 | +// This program is distributed in the hope that it will be useful, but |
45 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
46 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
47 | +// PURPOSE. See the GNU Affero General Public License for more details. |
48 | +// |
49 | +// You should have received a copy of the GNU Affero General Public License |
50 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
51 | + |
52 | +#import "Album.h" |
53 | +#import "Artist.h" |
54 | +#import "NSMutableArray+Extras.h" |
55 | +#import "NSString+Extras.h" |
56 | +#import "AlbumParser.h" |
57 | +#import "Subsonic.h" |
58 | + |
59 | +@interface Album () |
60 | ++ (Album*)albumMatchingPredicate:(NSPredicate*)predicate; |
61 | +@end |
62 | + |
63 | +@implementation Album |
64 | + |
65 | ++ (BOOL)albumWithIdExists:(NSString*)anAlbumId |
66 | +{ |
67 | + return (nil != [Album albumWithId:anAlbumId]); |
68 | +} |
69 | + |
70 | ++ (Album*)albumWithId:(NSString*)anAlbumId |
71 | +{ |
72 | + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"albumId == %@", anAlbumId]; |
73 | + return [self albumMatchingPredicate:predicate]; |
74 | +} |
75 | + |
76 | ++ (Album*)albumWithTitle:(NSString*)albumTitle artist:(NSString*)albumArtist; |
77 | +{ |
78 | + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"title == %@ AND artist = %@", albumTitle, albumArtist]; |
79 | + return [self albumMatchingPredicate:predicate]; |
80 | +} |
81 | + |
82 | ++ (Album*)albumMatchingPredicate:(NSPredicate*)predicate; |
83 | +{ |
84 | + NSFetchRequest * fetch = [[NSFetchRequest alloc] init]; |
85 | + NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Album" inManagedObjectContext:PerThreadManagedObjectContext()]; |
86 | + [fetch setEntity:entityDescription]; |
87 | + [fetch setPredicate:predicate]; |
88 | + NSError * error = nil; |
89 | + NSArray * matches = [PerThreadManagedObjectContext() executeFetchRequest:fetch error:&error]; |
90 | + [fetch release]; |
91 | + |
92 | + return [matches lastObject]; |
93 | +} |
94 | + |
95 | +- (NSString *)dearticlizedTitle |
96 | +{ |
97 | + return [self.title dearticlizedString]; |
98 | +} |
99 | + |
100 | +- (NSError*)loadSongs |
101 | +{ |
102 | + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
103 | + NSError *error = nil; |
104 | + |
105 | + NSMutableArray *parameters = [NSMutableArray array]; |
106 | + [parameters addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"id", self.albumId, nil]]; |
107 | + NSURL *url = [[Subsonic sharedSubsonic] getMetadataURL:@"getAlbum.view" parameters:parameters]; |
108 | + NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url]; |
109 | + |
110 | + AlbumParser *parser = [[AlbumParser alloc] init]; |
111 | + parser.albumObjectId = [self objectID]; |
112 | + |
113 | + [xmlParser setDelegate:parser]; |
114 | + |
115 | + if (![xmlParser parse]) |
116 | + { |
117 | + error = [[xmlParser parserError] copy]; |
118 | + } |
119 | + |
120 | + [xmlParser release]; |
121 | + [parser release]; |
122 | + [pool release]; |
123 | + |
124 | + return [error autorelease]; |
125 | +} |
126 | + |
127 | +- (NSString*)description |
128 | +{ |
129 | + return [NSString stringWithFormat:@"%@ - %@ (%@) (art: %@) MOC %@",self.artist,self.title,self.albumId,self.coverArtId, [self managedObjectContext]]; |
130 | +} |
131 | + |
132 | +- (BOOL)matchesSearchQuery:(NSString *)query |
133 | +{ |
134 | + NSRange titleResultsRange = [self.title rangeOfString:query options:NSCaseInsensitiveSearch]; |
135 | + return titleResultsRange.length > 0; |
136 | +} |
137 | + |
138 | +- (BOOL)hasCachedSongs; |
139 | +{ |
140 | + NSManagedObjectContext *moc = [self managedObjectContext]; |
141 | + NSEntityDescription *songEntity = [NSEntityDescription entityForName:@"Song" inManagedObjectContext:moc]; |
142 | + NSFetchRequest *fetch = [[[NSFetchRequest alloc] init] autorelease]; |
143 | + [fetch setEntity:songEntity]; |
144 | + [fetch setPredicate:[NSPredicate predicateWithFormat:@"album = %@ and cachedSongPath != NIL", self.title]]; |
145 | + |
146 | + NSArray *results = [[self managedObjectContext] executeFetchRequest:fetch error:NULL]; |
147 | + return [results count] > 0; |
148 | +} |
149 | + |
150 | +@end |
151 | |
152 | === added file 'Models/Artist.h' |
153 | --- Models/Artist.h 1970-01-01 00:00:00 +0000 |
154 | +++ Models/Artist.h 2012-02-03 20:23:18 +0000 |
155 | @@ -0,0 +1,26 @@ |
156 | +// |
157 | +// Copyright 2012 Canonical Ltd. |
158 | +// |
159 | +// This program is free software: you can redistribute it and/or modify it |
160 | +// under the terms of the GNU Affero General Public License version 3, |
161 | +// as published by the Free Software Foundation. |
162 | +// |
163 | +// This program is distributed in the hope that it will be useful, but |
164 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
165 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
166 | +// PURPOSE. See the GNU Affero General Public License for more details. |
167 | +// |
168 | +// You should have received a copy of the GNU Affero General Public License |
169 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
170 | + |
171 | +#import "_Artist.h" |
172 | + |
173 | +@interface Artist : _Artist {} |
174 | ++ (Artist*)artistWithId:(NSString*)anArtistId; |
175 | ++ (BOOL)artistWithIdExists:(NSString*)anArtistId; |
176 | ++ (Artist*)artistWithName:(NSString*)artistName; |
177 | +- (BOOL)matchesSearchQuery:(NSString *)query; |
178 | +- (NSString *)dearticlizedName; |
179 | +- (NSError*)loadAlbums; |
180 | +- (BOOL)hasCachedSongs; |
181 | +@end |
182 | |
183 | === added file 'Models/Artist.m' |
184 | --- Models/Artist.m 1970-01-01 00:00:00 +0000 |
185 | +++ Models/Artist.m 2012-02-03 20:23:18 +0000 |
186 | @@ -0,0 +1,114 @@ |
187 | +// |
188 | +// Copyright 2012 Canonical Ltd. |
189 | +// |
190 | +// This program is free software: you can redistribute it and/or modify it |
191 | +// under the terms of the GNU Affero General Public License version 3, |
192 | +// as published by the Free Software Foundation. |
193 | +// |
194 | +// This program is distributed in the hope that it will be useful, but |
195 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
196 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
197 | +// PURPOSE. See the GNU Affero General Public License for more details. |
198 | +// |
199 | +// You should have received a copy of the GNU Affero General Public License |
200 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
201 | + |
202 | +#import "Artist.h" |
203 | +#import "Album.h" |
204 | +#import "Subsonic.h" |
205 | +#import "NSMutableArray+Extras.h" |
206 | +#import "NSString+Extras.h" |
207 | +#import "ArtistParser.h" |
208 | + |
209 | +@interface Artist () |
210 | ++ (Artist*)artistMatchingPredicate:(NSPredicate*)predicate; |
211 | +@end |
212 | + |
213 | +@implementation Artist |
214 | + |
215 | ++ (BOOL)artistWithIdExists:(NSString*)anArtistId |
216 | +{ |
217 | + return [Artist artistWithId:anArtistId] != nil; |
218 | +} |
219 | + |
220 | ++ (Artist*)artistWithId:(NSString*)anArtistId |
221 | +{ |
222 | + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"artistId == %@", anArtistId]; |
223 | + return [self artistMatchingPredicate:predicate]; |
224 | +} |
225 | + |
226 | ++ (Artist*)artistWithName:(NSString*)artistName; |
227 | +{ |
228 | + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == %@", artistName]; |
229 | + return [self artistMatchingPredicate:predicate]; |
230 | +} |
231 | + |
232 | ++ (Artist*)artistMatchingPredicate:(NSPredicate*)predicate; |
233 | +{ |
234 | + NSFetchRequest * fetch = [[NSFetchRequest alloc] init]; |
235 | + NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Artist" inManagedObjectContext:PerThreadManagedObjectContext()]; |
236 | + [fetch setEntity:entityDescription]; |
237 | + [fetch setPredicate:predicate]; |
238 | + NSError * error = nil; |
239 | + NSArray * matches = [PerThreadManagedObjectContext() executeFetchRequest:fetch error:&error]; |
240 | + [fetch release]; |
241 | + |
242 | + return [matches lastObject]; |
243 | +} |
244 | + |
245 | +- (NSString*)description |
246 | +{ |
247 | + return [NSString stringWithFormat:@"%@ (%@) MOC %@",self.name, self.artistId, [self managedObjectContext]]; |
248 | +} |
249 | + |
250 | +- (BOOL)matchesSearchQuery:(NSString *)query |
251 | +{ |
252 | + NSRange titleResultsRange = [self.name rangeOfString:query options:NSCaseInsensitiveSearch]; |
253 | + return titleResultsRange.length > 0; |
254 | +} |
255 | + |
256 | +- (NSString *)dearticlizedName |
257 | +{ |
258 | + return [self.name dearticlizedString]; |
259 | +} |
260 | + |
261 | +// Note: executes synchronously! |
262 | +- (NSError*)loadAlbums |
263 | +{ |
264 | + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
265 | + NSError *error = nil; |
266 | + |
267 | + NSMutableArray *parameters = [NSMutableArray array]; |
268 | + [parameters addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"id", self.artistId, nil]]; |
269 | + NSURL *url = [[Subsonic sharedSubsonic] getMetadataURL:@"getMusicDirectory.view" parameters:parameters]; |
270 | + NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url]; |
271 | + ArtistParser *parser = [[ArtistParser alloc] init]; |
272 | + parser.artistManagedObjectID = [self objectID]; |
273 | + [xmlParser setDelegate:parser]; |
274 | + |
275 | + if (![xmlParser parse]) |
276 | + { |
277 | + error = [[xmlParser parserError] copy]; |
278 | + } |
279 | + |
280 | + [xmlParser release]; |
281 | + [parser release]; |
282 | + [pool release]; |
283 | + |
284 | + return [error autorelease]; |
285 | +} |
286 | + |
287 | +- (BOOL)hasCachedSongs; |
288 | +{ |
289 | + NSManagedObjectContext *moc = [self managedObjectContext]; |
290 | + NSEntityDescription *songEntity = [NSEntityDescription entityForName:@"Song" inManagedObjectContext:moc]; |
291 | + NSFetchRequest *fetch = [[[NSFetchRequest alloc] init] autorelease]; |
292 | + [fetch setEntity:songEntity]; |
293 | + [fetch setPredicate:[NSPredicate predicateWithFormat:@"artist = %@ and cachedSongPath != NIL", self.name]]; |
294 | + |
295 | + NSError *error = nil; |
296 | + NSArray *results = [moc executeFetchRequest:fetch error:&error]; |
297 | + return [results count] > 0; |
298 | +} |
299 | + |
300 | +@end |
301 | |
302 | === renamed file 'models/CachedSongsPlaylist.h' => 'Models/CachedSongsPlaylist.h' |
303 | === renamed file 'models/CachedSongsPlaylist.m' => 'Models/CachedSongsPlaylist.m' |
304 | === added directory 'Models/Generated' |
305 | === added file 'Models/Generated/_Album.h' |
306 | --- Models/Generated/_Album.h 1970-01-01 00:00:00 +0000 |
307 | +++ Models/Generated/_Album.h 2012-02-03 20:23:18 +0000 |
308 | @@ -0,0 +1,122 @@ |
309 | +// DO NOT EDIT. This file is machine-generated and constantly overwritten. |
310 | +// Make changes to Album.h instead. |
311 | + |
312 | +#import <CoreData/CoreData.h> |
313 | + |
314 | + |
315 | +@class Artist; |
316 | +@class Song; |
317 | + |
318 | + |
319 | + |
320 | + |
321 | + |
322 | + |
323 | +@interface AlbumID : NSManagedObjectID {} |
324 | +@end |
325 | + |
326 | +@interface _Album : NSManagedObject {} |
327 | ++ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_; |
328 | ++ (NSString*)entityName; |
329 | ++ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_; |
330 | +- (AlbumID*)objectID; |
331 | + |
332 | + |
333 | + |
334 | + |
335 | +@property (nonatomic, retain) NSString *albumId; |
336 | + |
337 | + |
338 | +//- (BOOL)validateAlbumId:(id*)value_ error:(NSError**)error_; |
339 | + |
340 | + |
341 | + |
342 | + |
343 | +@property (nonatomic, retain) NSString *artist; |
344 | + |
345 | + |
346 | +//- (BOOL)validateArtist:(id*)value_ error:(NSError**)error_; |
347 | + |
348 | + |
349 | + |
350 | + |
351 | +@property (nonatomic, retain) NSString *coverArtId; |
352 | + |
353 | + |
354 | +//- (BOOL)validateCoverArtId:(id*)value_ error:(NSError**)error_; |
355 | + |
356 | + |
357 | + |
358 | + |
359 | +@property (nonatomic, retain) NSString *title; |
360 | + |
361 | + |
362 | +//- (BOOL)validateTitle:(id*)value_ error:(NSError**)error_; |
363 | + |
364 | + |
365 | + |
366 | + |
367 | + |
368 | +@property (nonatomic, retain) Artist* artistEntity; |
369 | + |
370 | +//- (BOOL)validateArtistEntity:(id*)value_ error:(NSError**)error_; |
371 | + |
372 | + |
373 | + |
374 | + |
375 | +@property (nonatomic, retain) NSSet* songs; |
376 | + |
377 | +- (NSMutableSet*)songsSet; |
378 | + |
379 | + |
380 | + |
381 | + |
382 | +@end |
383 | + |
384 | +@interface _Album (CoreDataGeneratedAccessors) |
385 | + |
386 | +- (void)addSongs:(NSSet*)value_; |
387 | +- (void)removeSongs:(NSSet*)value_; |
388 | +- (void)addSongsObject:(Song*)value_; |
389 | +- (void)removeSongsObject:(Song*)value_; |
390 | + |
391 | +@end |
392 | + |
393 | +@interface _Album (CoreDataGeneratedPrimitiveAccessors) |
394 | + |
395 | + |
396 | +- (NSString*)primitiveAlbumId; |
397 | +- (void)setPrimitiveAlbumId:(NSString*)value; |
398 | + |
399 | + |
400 | + |
401 | + |
402 | +- (NSString*)primitiveArtist; |
403 | +- (void)setPrimitiveArtist:(NSString*)value; |
404 | + |
405 | + |
406 | + |
407 | + |
408 | +- (NSString*)primitiveCoverArtId; |
409 | +- (void)setPrimitiveCoverArtId:(NSString*)value; |
410 | + |
411 | + |
412 | + |
413 | + |
414 | +- (NSString*)primitiveTitle; |
415 | +- (void)setPrimitiveTitle:(NSString*)value; |
416 | + |
417 | + |
418 | + |
419 | + |
420 | + |
421 | +- (Artist*)primitiveArtistEntity; |
422 | +- (void)setPrimitiveArtistEntity:(Artist*)value; |
423 | + |
424 | + |
425 | + |
426 | +- (NSMutableSet*)primitiveSongs; |
427 | +- (void)setPrimitiveSongs:(NSMutableSet*)value; |
428 | + |
429 | + |
430 | +@end |
431 | |
432 | === added file 'Models/Generated/_Album.m' |
433 | --- Models/Generated/_Album.m 1970-01-01 00:00:00 +0000 |
434 | +++ Models/Generated/_Album.m 2012-02-03 20:23:18 +0000 |
435 | @@ -0,0 +1,86 @@ |
436 | +// DO NOT EDIT. This file is machine-generated and constantly overwritten. |
437 | +// Make changes to Album.m instead. |
438 | + |
439 | +#import "_Album.h" |
440 | + |
441 | +@implementation AlbumID |
442 | +@end |
443 | + |
444 | +@implementation _Album |
445 | + |
446 | ++ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_ { |
447 | + NSParameterAssert(moc_); |
448 | + return [NSEntityDescription insertNewObjectForEntityForName:@"Album" inManagedObjectContext:moc_]; |
449 | +} |
450 | + |
451 | ++ (NSString*)entityName { |
452 | + return @"Album"; |
453 | +} |
454 | + |
455 | ++ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_ { |
456 | + NSParameterAssert(moc_); |
457 | + return [NSEntityDescription entityForName:@"Album" inManagedObjectContext:moc_]; |
458 | +} |
459 | + |
460 | +- (AlbumID*)objectID { |
461 | + return (AlbumID*)[super objectID]; |
462 | +} |
463 | + |
464 | ++ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { |
465 | + NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; |
466 | + |
467 | + |
468 | + return keyPaths; |
469 | +} |
470 | + |
471 | + |
472 | + |
473 | + |
474 | +@dynamic albumId; |
475 | + |
476 | + |
477 | + |
478 | + |
479 | + |
480 | + |
481 | +@dynamic artist; |
482 | + |
483 | + |
484 | + |
485 | + |
486 | + |
487 | + |
488 | +@dynamic coverArtId; |
489 | + |
490 | + |
491 | + |
492 | + |
493 | + |
494 | + |
495 | +@dynamic title; |
496 | + |
497 | + |
498 | + |
499 | + |
500 | + |
501 | + |
502 | +@dynamic artistEntity; |
503 | + |
504 | + |
505 | + |
506 | +@dynamic songs; |
507 | + |
508 | + |
509 | +- (NSMutableSet*)songsSet { |
510 | + [self willAccessValueForKey:@"songs"]; |
511 | + NSMutableSet *result = (NSMutableSet*)[self mutableSetValueForKey:@"songs"]; |
512 | + [self didAccessValueForKey:@"songs"]; |
513 | + return result; |
514 | +} |
515 | + |
516 | + |
517 | + |
518 | + |
519 | + |
520 | + |
521 | +@end |
522 | |
523 | === added file 'Models/Generated/_Artist.h' |
524 | --- Models/Generated/_Artist.h 1970-01-01 00:00:00 +0000 |
525 | +++ Models/Generated/_Artist.h 2012-02-03 20:23:18 +0000 |
526 | @@ -0,0 +1,97 @@ |
527 | +// DO NOT EDIT. This file is machine-generated and constantly overwritten. |
528 | +// Make changes to Artist.h instead. |
529 | + |
530 | +#import <CoreData/CoreData.h> |
531 | + |
532 | + |
533 | +@class Album; |
534 | +@class Song; |
535 | + |
536 | + |
537 | + |
538 | + |
539 | +@interface ArtistID : NSManagedObjectID {} |
540 | +@end |
541 | + |
542 | +@interface _Artist : NSManagedObject {} |
543 | ++ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_; |
544 | ++ (NSString*)entityName; |
545 | ++ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_; |
546 | +- (ArtistID*)objectID; |
547 | + |
548 | + |
549 | + |
550 | + |
551 | +@property (nonatomic, retain) NSString *artistId; |
552 | + |
553 | + |
554 | +//- (BOOL)validateArtistId:(id*)value_ error:(NSError**)error_; |
555 | + |
556 | + |
557 | + |
558 | + |
559 | +@property (nonatomic, retain) NSString *name; |
560 | + |
561 | + |
562 | +//- (BOOL)validateName:(id*)value_ error:(NSError**)error_; |
563 | + |
564 | + |
565 | + |
566 | + |
567 | + |
568 | +@property (nonatomic, retain) NSSet* albums; |
569 | + |
570 | +- (NSMutableSet*)albumsSet; |
571 | + |
572 | + |
573 | + |
574 | + |
575 | +@property (nonatomic, retain) NSSet* songs; |
576 | + |
577 | +- (NSMutableSet*)songsSet; |
578 | + |
579 | + |
580 | + |
581 | + |
582 | +@end |
583 | + |
584 | +@interface _Artist (CoreDataGeneratedAccessors) |
585 | + |
586 | +- (void)addAlbums:(NSSet*)value_; |
587 | +- (void)removeAlbums:(NSSet*)value_; |
588 | +- (void)addAlbumsObject:(Album*)value_; |
589 | +- (void)removeAlbumsObject:(Album*)value_; |
590 | + |
591 | +- (void)addSongs:(NSSet*)value_; |
592 | +- (void)removeSongs:(NSSet*)value_; |
593 | +- (void)addSongsObject:(Song*)value_; |
594 | +- (void)removeSongsObject:(Song*)value_; |
595 | + |
596 | +@end |
597 | + |
598 | +@interface _Artist (CoreDataGeneratedPrimitiveAccessors) |
599 | + |
600 | + |
601 | +- (NSString*)primitiveArtistId; |
602 | +- (void)setPrimitiveArtistId:(NSString*)value; |
603 | + |
604 | + |
605 | + |
606 | + |
607 | +- (NSString*)primitiveName; |
608 | +- (void)setPrimitiveName:(NSString*)value; |
609 | + |
610 | + |
611 | + |
612 | + |
613 | + |
614 | +- (NSMutableSet*)primitiveAlbums; |
615 | +- (void)setPrimitiveAlbums:(NSMutableSet*)value; |
616 | + |
617 | + |
618 | + |
619 | +- (NSMutableSet*)primitiveSongs; |
620 | +- (void)setPrimitiveSongs:(NSMutableSet*)value; |
621 | + |
622 | + |
623 | +@end |
624 | |
625 | === added file 'Models/Generated/_Artist.m' |
626 | --- Models/Generated/_Artist.m 1970-01-01 00:00:00 +0000 |
627 | +++ Models/Generated/_Artist.m 2012-02-03 20:23:18 +0000 |
628 | @@ -0,0 +1,79 @@ |
629 | +// DO NOT EDIT. This file is machine-generated and constantly overwritten. |
630 | +// Make changes to Artist.m instead. |
631 | + |
632 | +#import "_Artist.h" |
633 | + |
634 | +@implementation ArtistID |
635 | +@end |
636 | + |
637 | +@implementation _Artist |
638 | + |
639 | ++ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_ { |
640 | + NSParameterAssert(moc_); |
641 | + return [NSEntityDescription insertNewObjectForEntityForName:@"Artist" inManagedObjectContext:moc_]; |
642 | +} |
643 | + |
644 | ++ (NSString*)entityName { |
645 | + return @"Artist"; |
646 | +} |
647 | + |
648 | ++ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_ { |
649 | + NSParameterAssert(moc_); |
650 | + return [NSEntityDescription entityForName:@"Artist" inManagedObjectContext:moc_]; |
651 | +} |
652 | + |
653 | +- (ArtistID*)objectID { |
654 | + return (ArtistID*)[super objectID]; |
655 | +} |
656 | + |
657 | ++ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { |
658 | + NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; |
659 | + |
660 | + |
661 | + return keyPaths; |
662 | +} |
663 | + |
664 | + |
665 | + |
666 | + |
667 | +@dynamic artistId; |
668 | + |
669 | + |
670 | + |
671 | + |
672 | + |
673 | + |
674 | +@dynamic name; |
675 | + |
676 | + |
677 | + |
678 | + |
679 | + |
680 | + |
681 | +@dynamic albums; |
682 | + |
683 | + |
684 | +- (NSMutableSet*)albumsSet { |
685 | + [self willAccessValueForKey:@"albums"]; |
686 | + NSMutableSet *result = (NSMutableSet*)[self mutableSetValueForKey:@"albums"]; |
687 | + [self didAccessValueForKey:@"albums"]; |
688 | + return result; |
689 | +} |
690 | + |
691 | + |
692 | +@dynamic songs; |
693 | + |
694 | + |
695 | +- (NSMutableSet*)songsSet { |
696 | + [self willAccessValueForKey:@"songs"]; |
697 | + NSMutableSet *result = (NSMutableSet*)[self mutableSetValueForKey:@"songs"]; |
698 | + [self didAccessValueForKey:@"songs"]; |
699 | + return result; |
700 | +} |
701 | + |
702 | + |
703 | + |
704 | + |
705 | + |
706 | + |
707 | +@end |
708 | |
709 | === added file 'Models/Generated/_Playlist.h' |
710 | --- Models/Generated/_Playlist.h 1970-01-01 00:00:00 +0000 |
711 | +++ Models/Generated/_Playlist.h 2012-02-03 20:23:18 +0000 |
712 | @@ -0,0 +1,79 @@ |
713 | +// DO NOT EDIT. This file is machine-generated and constantly overwritten. |
714 | +// Make changes to Playlist.h instead. |
715 | + |
716 | +#import <CoreData/CoreData.h> |
717 | + |
718 | + |
719 | +@class PlaylistSongIndex; |
720 | + |
721 | + |
722 | + |
723 | + |
724 | +@interface PlaylistID : NSManagedObjectID {} |
725 | +@end |
726 | + |
727 | +@interface _Playlist : NSManagedObject {} |
728 | ++ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_; |
729 | ++ (NSString*)entityName; |
730 | ++ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_; |
731 | +- (PlaylistID*)objectID; |
732 | + |
733 | + |
734 | + |
735 | + |
736 | +@property (nonatomic, retain) NSString *name; |
737 | + |
738 | + |
739 | +//- (BOOL)validateName:(id*)value_ error:(NSError**)error_; |
740 | + |
741 | + |
742 | + |
743 | + |
744 | +@property (nonatomic, retain) NSString *playlistId; |
745 | + |
746 | + |
747 | +//- (BOOL)validatePlaylistId:(id*)value_ error:(NSError**)error_; |
748 | + |
749 | + |
750 | + |
751 | + |
752 | + |
753 | +@property (nonatomic, retain) NSSet* playlistSongIndexes; |
754 | + |
755 | +- (NSMutableSet*)playlistSongIndexesSet; |
756 | + |
757 | + |
758 | + |
759 | + |
760 | +@end |
761 | + |
762 | +@interface _Playlist (CoreDataGeneratedAccessors) |
763 | + |
764 | +- (void)addPlaylistSongIndexes:(NSSet*)value_; |
765 | +- (void)removePlaylistSongIndexes:(NSSet*)value_; |
766 | +- (void)addPlaylistSongIndexesObject:(PlaylistSongIndex*)value_; |
767 | +- (void)removePlaylistSongIndexesObject:(PlaylistSongIndex*)value_; |
768 | + |
769 | +@end |
770 | + |
771 | +@interface _Playlist (CoreDataGeneratedPrimitiveAccessors) |
772 | + |
773 | + |
774 | +- (NSString*)primitiveName; |
775 | +- (void)setPrimitiveName:(NSString*)value; |
776 | + |
777 | + |
778 | + |
779 | + |
780 | +- (NSString*)primitivePlaylistId; |
781 | +- (void)setPrimitivePlaylistId:(NSString*)value; |
782 | + |
783 | + |
784 | + |
785 | + |
786 | + |
787 | +- (NSMutableSet*)primitivePlaylistSongIndexes; |
788 | +- (void)setPrimitivePlaylistSongIndexes:(NSMutableSet*)value; |
789 | + |
790 | + |
791 | +@end |
792 | |
793 | === added file 'Models/Generated/_Playlist.m' |
794 | --- Models/Generated/_Playlist.m 1970-01-01 00:00:00 +0000 |
795 | +++ Models/Generated/_Playlist.m 2012-02-03 20:23:18 +0000 |
796 | @@ -0,0 +1,68 @@ |
797 | +// DO NOT EDIT. This file is machine-generated and constantly overwritten. |
798 | +// Make changes to Playlist.m instead. |
799 | + |
800 | +#import "_Playlist.h" |
801 | + |
802 | +@implementation PlaylistID |
803 | +@end |
804 | + |
805 | +@implementation _Playlist |
806 | + |
807 | ++ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_ { |
808 | + NSParameterAssert(moc_); |
809 | + return [NSEntityDescription insertNewObjectForEntityForName:@"Playlist" inManagedObjectContext:moc_]; |
810 | +} |
811 | + |
812 | ++ (NSString*)entityName { |
813 | + return @"Playlist"; |
814 | +} |
815 | + |
816 | ++ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_ { |
817 | + NSParameterAssert(moc_); |
818 | + return [NSEntityDescription entityForName:@"Playlist" inManagedObjectContext:moc_]; |
819 | +} |
820 | + |
821 | +- (PlaylistID*)objectID { |
822 | + return (PlaylistID*)[super objectID]; |
823 | +} |
824 | + |
825 | ++ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { |
826 | + NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; |
827 | + |
828 | + |
829 | + return keyPaths; |
830 | +} |
831 | + |
832 | + |
833 | + |
834 | + |
835 | +@dynamic name; |
836 | + |
837 | + |
838 | + |
839 | + |
840 | + |
841 | + |
842 | +@dynamic playlistId; |
843 | + |
844 | + |
845 | + |
846 | + |
847 | + |
848 | + |
849 | +@dynamic playlistSongIndexes; |
850 | + |
851 | + |
852 | +- (NSMutableSet*)playlistSongIndexesSet { |
853 | + [self willAccessValueForKey:@"playlistSongIndexes"]; |
854 | + NSMutableSet *result = (NSMutableSet*)[self mutableSetValueForKey:@"playlistSongIndexes"]; |
855 | + [self didAccessValueForKey:@"playlistSongIndexes"]; |
856 | + return result; |
857 | +} |
858 | + |
859 | + |
860 | + |
861 | + |
862 | + |
863 | + |
864 | +@end |
865 | |
866 | === added file 'Models/Generated/_PlaylistSongIndex.h' |
867 | --- Models/Generated/_PlaylistSongIndex.h 1970-01-01 00:00:00 +0000 |
868 | +++ Models/Generated/_PlaylistSongIndex.h 2012-02-03 20:23:18 +0000 |
869 | @@ -0,0 +1,79 @@ |
870 | +// DO NOT EDIT. This file is machine-generated and constantly overwritten. |
871 | +// Make changes to PlaylistSongIndex.h instead. |
872 | + |
873 | +#import <CoreData/CoreData.h> |
874 | + |
875 | + |
876 | +@class Playlist; |
877 | +@class Song; |
878 | + |
879 | + |
880 | + |
881 | +@interface PlaylistSongIndexID : NSManagedObjectID {} |
882 | +@end |
883 | + |
884 | +@interface _PlaylistSongIndex : NSManagedObject {} |
885 | ++ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_; |
886 | ++ (NSString*)entityName; |
887 | ++ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_; |
888 | +- (PlaylistSongIndexID*)objectID; |
889 | + |
890 | + |
891 | + |
892 | + |
893 | +@property (nonatomic, retain) NSNumber *index; |
894 | + |
895 | + |
896 | +@property int indexValue; |
897 | +- (int)indexValue; |
898 | +- (void)setIndexValue:(int)value_; |
899 | + |
900 | +//- (BOOL)validateIndex:(id*)value_ error:(NSError**)error_; |
901 | + |
902 | + |
903 | + |
904 | + |
905 | + |
906 | +@property (nonatomic, retain) Playlist* playlistEntity; |
907 | + |
908 | +//- (BOOL)validatePlaylistEntity:(id*)value_ error:(NSError**)error_; |
909 | + |
910 | + |
911 | + |
912 | + |
913 | +@property (nonatomic, retain) Song* songEntity; |
914 | + |
915 | +//- (BOOL)validateSongEntity:(id*)value_ error:(NSError**)error_; |
916 | + |
917 | + |
918 | + |
919 | + |
920 | +@end |
921 | + |
922 | +@interface _PlaylistSongIndex (CoreDataGeneratedAccessors) |
923 | + |
924 | +@end |
925 | + |
926 | +@interface _PlaylistSongIndex (CoreDataGeneratedPrimitiveAccessors) |
927 | + |
928 | + |
929 | +- (NSNumber*)primitiveIndex; |
930 | +- (void)setPrimitiveIndex:(NSNumber*)value; |
931 | + |
932 | +- (int)primitiveIndexValue; |
933 | +- (void)setPrimitiveIndexValue:(int)value_; |
934 | + |
935 | + |
936 | + |
937 | + |
938 | + |
939 | +- (Playlist*)primitivePlaylistEntity; |
940 | +- (void)setPrimitivePlaylistEntity:(Playlist*)value; |
941 | + |
942 | + |
943 | + |
944 | +- (Song*)primitiveSongEntity; |
945 | +- (void)setPrimitiveSongEntity:(Song*)value; |
946 | + |
947 | + |
948 | +@end |
949 | |
950 | === added file 'Models/Generated/_PlaylistSongIndex.m' |
951 | --- Models/Generated/_PlaylistSongIndex.m 1970-01-01 00:00:00 +0000 |
952 | +++ Models/Generated/_PlaylistSongIndex.m 2012-02-03 20:23:18 +0000 |
953 | @@ -0,0 +1,81 @@ |
954 | +// DO NOT EDIT. This file is machine-generated and constantly overwritten. |
955 | +// Make changes to PlaylistSongIndex.m instead. |
956 | + |
957 | +#import "_PlaylistSongIndex.h" |
958 | + |
959 | +@implementation PlaylistSongIndexID |
960 | +@end |
961 | + |
962 | +@implementation _PlaylistSongIndex |
963 | + |
964 | ++ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_ { |
965 | + NSParameterAssert(moc_); |
966 | + return [NSEntityDescription insertNewObjectForEntityForName:@"PlaylistSongIndex" inManagedObjectContext:moc_]; |
967 | +} |
968 | + |
969 | ++ (NSString*)entityName { |
970 | + return @"PlaylistSongIndex"; |
971 | +} |
972 | + |
973 | ++ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_ { |
974 | + NSParameterAssert(moc_); |
975 | + return [NSEntityDescription entityForName:@"PlaylistSongIndex" inManagedObjectContext:moc_]; |
976 | +} |
977 | + |
978 | +- (PlaylistSongIndexID*)objectID { |
979 | + return (PlaylistSongIndexID*)[super objectID]; |
980 | +} |
981 | + |
982 | ++ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { |
983 | + NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; |
984 | + |
985 | + if ([key isEqualToString:@"indexValue"]) { |
986 | + NSSet *affectingKey = [NSSet setWithObject:@"index"]; |
987 | + keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey]; |
988 | + } |
989 | + |
990 | + return keyPaths; |
991 | +} |
992 | + |
993 | + |
994 | + |
995 | + |
996 | +@dynamic index; |
997 | + |
998 | + |
999 | + |
1000 | +- (int)indexValue { |
1001 | + NSNumber *result = [self index]; |
1002 | + return [result intValue]; |
1003 | +} |
1004 | + |
1005 | +- (void)setIndexValue:(int)value_ { |
1006 | + [self setIndex:[NSNumber numberWithInt:value_]]; |
1007 | +} |
1008 | + |
1009 | +- (int)primitiveIndexValue { |
1010 | + NSNumber *result = [self primitiveIndex]; |
1011 | + return [result intValue]; |
1012 | +} |
1013 | + |
1014 | +- (void)setPrimitiveIndexValue:(int)value_ { |
1015 | + [self setPrimitiveIndex:[NSNumber numberWithInt:value_]]; |
1016 | +} |
1017 | + |
1018 | + |
1019 | + |
1020 | + |
1021 | + |
1022 | +@dynamic playlistEntity; |
1023 | + |
1024 | + |
1025 | + |
1026 | +@dynamic songEntity; |
1027 | + |
1028 | + |
1029 | + |
1030 | + |
1031 | + |
1032 | + |
1033 | + |
1034 | +@end |
1035 | |
1036 | === added file 'Models/Generated/_Song.h' |
1037 | --- Models/Generated/_Song.h 1970-01-01 00:00:00 +0000 |
1038 | +++ Models/Generated/_Song.h 2012-02-03 20:23:18 +0000 |
1039 | @@ -0,0 +1,327 @@ |
1040 | +// DO NOT EDIT. This file is machine-generated and constantly overwritten. |
1041 | +// Make changes to Song.h instead. |
1042 | + |
1043 | +#import <CoreData/CoreData.h> |
1044 | + |
1045 | + |
1046 | +@class Album; |
1047 | +@class Artist; |
1048 | +@class PlaylistSongIndex; |
1049 | + |
1050 | + |
1051 | + |
1052 | + |
1053 | + |
1054 | + |
1055 | + |
1056 | + |
1057 | + |
1058 | + |
1059 | + |
1060 | + |
1061 | + |
1062 | + |
1063 | + |
1064 | + |
1065 | +@interface SongID : NSManagedObjectID {} |
1066 | +@end |
1067 | + |
1068 | +@interface _Song : NSManagedObject {} |
1069 | ++ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_; |
1070 | ++ (NSString*)entityName; |
1071 | ++ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_; |
1072 | +- (SongID*)objectID; |
1073 | + |
1074 | + |
1075 | + |
1076 | + |
1077 | +@property (nonatomic, retain) NSString *album; |
1078 | + |
1079 | + |
1080 | +//- (BOOL)validateAlbum:(id*)value_ error:(NSError**)error_; |
1081 | + |
1082 | + |
1083 | + |
1084 | + |
1085 | +@property (nonatomic, retain) NSString *artist; |
1086 | + |
1087 | + |
1088 | +//- (BOOL)validateArtist:(id*)value_ error:(NSError**)error_; |
1089 | + |
1090 | + |
1091 | + |
1092 | + |
1093 | +@property (nonatomic, retain) NSNumber *bitRate; |
1094 | + |
1095 | + |
1096 | +@property int bitRateValue; |
1097 | +- (int)bitRateValue; |
1098 | +- (void)setBitRateValue:(int)value_; |
1099 | + |
1100 | +//- (BOOL)validateBitRate:(id*)value_ error:(NSError**)error_; |
1101 | + |
1102 | + |
1103 | + |
1104 | + |
1105 | +@property (nonatomic, retain) NSString *cachedSongPath; |
1106 | + |
1107 | + |
1108 | +//- (BOOL)validateCachedSongPath:(id*)value_ error:(NSError**)error_; |
1109 | + |
1110 | + |
1111 | + |
1112 | + |
1113 | +@property (nonatomic, retain) NSString *coverArtId; |
1114 | + |
1115 | + |
1116 | +//- (BOOL)validateCoverArtId:(id*)value_ error:(NSError**)error_; |
1117 | + |
1118 | + |
1119 | + |
1120 | + |
1121 | +@property (nonatomic, retain) NSNumber *discNumber; |
1122 | + |
1123 | + |
1124 | +@property int discNumberValue; |
1125 | +- (int)discNumberValue; |
1126 | +- (void)setDiscNumberValue:(int)value_; |
1127 | + |
1128 | +//- (BOOL)validateDiscNumber:(id*)value_ error:(NSError**)error_; |
1129 | + |
1130 | + |
1131 | + |
1132 | + |
1133 | +@property (nonatomic, retain) NSNumber *duration; |
1134 | + |
1135 | + |
1136 | +@property int durationValue; |
1137 | +- (int)durationValue; |
1138 | +- (void)setDurationValue:(int)value_; |
1139 | + |
1140 | +//- (BOOL)validateDuration:(id*)value_ error:(NSError**)error_; |
1141 | + |
1142 | + |
1143 | + |
1144 | + |
1145 | +@property (nonatomic, retain) NSString *genre; |
1146 | + |
1147 | + |
1148 | +//- (BOOL)validateGenre:(id*)value_ error:(NSError**)error_; |
1149 | + |
1150 | + |
1151 | + |
1152 | + |
1153 | +@property (nonatomic, retain) NSString *path; |
1154 | + |
1155 | + |
1156 | +//- (BOOL)validatePath:(id*)value_ error:(NSError**)error_; |
1157 | + |
1158 | + |
1159 | + |
1160 | + |
1161 | +@property (nonatomic, retain) NSNumber *size; |
1162 | + |
1163 | + |
1164 | +@property int sizeValue; |
1165 | +- (int)sizeValue; |
1166 | +- (void)setSizeValue:(int)value_; |
1167 | + |
1168 | +//- (BOOL)validateSize:(id*)value_ error:(NSError**)error_; |
1169 | + |
1170 | + |
1171 | + |
1172 | + |
1173 | +@property (nonatomic, retain) NSString *songId; |
1174 | + |
1175 | + |
1176 | +//- (BOOL)validateSongId:(id*)value_ error:(NSError**)error_; |
1177 | + |
1178 | + |
1179 | + |
1180 | + |
1181 | +@property (nonatomic, retain) NSString *title; |
1182 | + |
1183 | + |
1184 | +//- (BOOL)validateTitle:(id*)value_ error:(NSError**)error_; |
1185 | + |
1186 | + |
1187 | + |
1188 | + |
1189 | +@property (nonatomic, retain) NSNumber *track; |
1190 | + |
1191 | + |
1192 | +@property int trackValue; |
1193 | +- (int)trackValue; |
1194 | +- (void)setTrackValue:(int)value_; |
1195 | + |
1196 | +//- (BOOL)validateTrack:(id*)value_ error:(NSError**)error_; |
1197 | + |
1198 | + |
1199 | + |
1200 | + |
1201 | +@property (nonatomic, retain) NSNumber *year; |
1202 | + |
1203 | + |
1204 | +@property int yearValue; |
1205 | +- (int)yearValue; |
1206 | +- (void)setYearValue:(int)value_; |
1207 | + |
1208 | +//- (BOOL)validateYear:(id*)value_ error:(NSError**)error_; |
1209 | + |
1210 | + |
1211 | + |
1212 | + |
1213 | + |
1214 | +@property (nonatomic, retain) Album* albumEntity; |
1215 | + |
1216 | +//- (BOOL)validateAlbumEntity:(id*)value_ error:(NSError**)error_; |
1217 | + |
1218 | + |
1219 | + |
1220 | + |
1221 | +@property (nonatomic, retain) Artist* artistEntity; |
1222 | + |
1223 | +//- (BOOL)validateArtistEntity:(id*)value_ error:(NSError**)error_; |
1224 | + |
1225 | + |
1226 | + |
1227 | + |
1228 | +@property (nonatomic, retain) NSSet* playlistSongIndexes; |
1229 | + |
1230 | +- (NSMutableSet*)playlistSongIndexesSet; |
1231 | + |
1232 | + |
1233 | + |
1234 | + |
1235 | +@end |
1236 | + |
1237 | +@interface _Song (CoreDataGeneratedAccessors) |
1238 | + |
1239 | +- (void)addPlaylistSongIndexes:(NSSet*)value_; |
1240 | +- (void)removePlaylistSongIndexes:(NSSet*)value_; |
1241 | +- (void)addPlaylistSongIndexesObject:(PlaylistSongIndex*)value_; |
1242 | +- (void)removePlaylistSongIndexesObject:(PlaylistSongIndex*)value_; |
1243 | + |
1244 | +@end |
1245 | + |
1246 | +@interface _Song (CoreDataGeneratedPrimitiveAccessors) |
1247 | + |
1248 | + |
1249 | +- (NSString*)primitiveAlbum; |
1250 | +- (void)setPrimitiveAlbum:(NSString*)value; |
1251 | + |
1252 | + |
1253 | + |
1254 | + |
1255 | +- (NSString*)primitiveArtist; |
1256 | +- (void)setPrimitiveArtist:(NSString*)value; |
1257 | + |
1258 | + |
1259 | + |
1260 | + |
1261 | +- (NSNumber*)primitiveBitRate; |
1262 | +- (void)setPrimitiveBitRate:(NSNumber*)value; |
1263 | + |
1264 | +- (int)primitiveBitRateValue; |
1265 | +- (void)setPrimitiveBitRateValue:(int)value_; |
1266 | + |
1267 | + |
1268 | + |
1269 | + |
1270 | +- (NSString*)primitiveCachedSongPath; |
1271 | +- (void)setPrimitiveCachedSongPath:(NSString*)value; |
1272 | + |
1273 | + |
1274 | + |
1275 | + |
1276 | +- (NSString*)primitiveCoverArtId; |
1277 | +- (void)setPrimitiveCoverArtId:(NSString*)value; |
1278 | + |
1279 | + |
1280 | + |
1281 | + |
1282 | +- (NSNumber*)primitiveDiscNumber; |
1283 | +- (void)setPrimitiveDiscNumber:(NSNumber*)value; |
1284 | + |
1285 | +- (int)primitiveDiscNumberValue; |
1286 | +- (void)setPrimitiveDiscNumberValue:(int)value_; |
1287 | + |
1288 | + |
1289 | + |
1290 | + |
1291 | +- (NSNumber*)primitiveDuration; |
1292 | +- (void)setPrimitiveDuration:(NSNumber*)value; |
1293 | + |
1294 | +- (int)primitiveDurationValue; |
1295 | +- (void)setPrimitiveDurationValue:(int)value_; |
1296 | + |
1297 | + |
1298 | + |
1299 | + |
1300 | +- (NSString*)primitiveGenre; |
1301 | +- (void)setPrimitiveGenre:(NSString*)value; |
1302 | + |
1303 | + |
1304 | + |
1305 | + |
1306 | +- (NSString*)primitivePath; |
1307 | +- (void)setPrimitivePath:(NSString*)value; |
1308 | + |
1309 | + |
1310 | + |
1311 | + |
1312 | +- (NSNumber*)primitiveSize; |
1313 | +- (void)setPrimitiveSize:(NSNumber*)value; |
1314 | + |
1315 | +- (int)primitiveSizeValue; |
1316 | +- (void)setPrimitiveSizeValue:(int)value_; |
1317 | + |
1318 | + |
1319 | + |
1320 | + |
1321 | +- (NSString*)primitiveSongId; |
1322 | +- (void)setPrimitiveSongId:(NSString*)value; |
1323 | + |
1324 | + |
1325 | + |
1326 | + |
1327 | +- (NSString*)primitiveTitle; |
1328 | +- (void)setPrimitiveTitle:(NSString*)value; |
1329 | + |
1330 | + |
1331 | + |
1332 | + |
1333 | +- (NSNumber*)primitiveTrack; |
1334 | +- (void)setPrimitiveTrack:(NSNumber*)value; |
1335 | + |
1336 | +- (int)primitiveTrackValue; |
1337 | +- (void)setPrimitiveTrackValue:(int)value_; |
1338 | + |
1339 | + |
1340 | + |
1341 | + |
1342 | +- (NSNumber*)primitiveYear; |
1343 | +- (void)setPrimitiveYear:(NSNumber*)value; |
1344 | + |
1345 | +- (int)primitiveYearValue; |
1346 | +- (void)setPrimitiveYearValue:(int)value_; |
1347 | + |
1348 | + |
1349 | + |
1350 | + |
1351 | + |
1352 | +- (Album*)primitiveAlbumEntity; |
1353 | +- (void)setPrimitiveAlbumEntity:(Album*)value; |
1354 | + |
1355 | + |
1356 | + |
1357 | +- (Artist*)primitiveArtistEntity; |
1358 | +- (void)setPrimitiveArtistEntity:(Artist*)value; |
1359 | + |
1360 | + |
1361 | + |
1362 | +- (NSMutableSet*)primitivePlaylistSongIndexes; |
1363 | +- (void)setPrimitivePlaylistSongIndexes:(NSMutableSet*)value; |
1364 | + |
1365 | + |
1366 | +@end |
1367 | |
1368 | === added file 'Models/Generated/_Song.m' |
1369 | --- Models/Generated/_Song.m 1970-01-01 00:00:00 +0000 |
1370 | +++ Models/Generated/_Song.m 2012-02-03 20:23:18 +0000 |
1371 | @@ -0,0 +1,298 @@ |
1372 | +// DO NOT EDIT. This file is machine-generated and constantly overwritten. |
1373 | +// Make changes to Song.m instead. |
1374 | + |
1375 | +#import "_Song.h" |
1376 | + |
1377 | +@implementation SongID |
1378 | +@end |
1379 | + |
1380 | +@implementation _Song |
1381 | + |
1382 | ++ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_ { |
1383 | + NSParameterAssert(moc_); |
1384 | + return [NSEntityDescription insertNewObjectForEntityForName:@"Song" inManagedObjectContext:moc_]; |
1385 | +} |
1386 | + |
1387 | ++ (NSString*)entityName { |
1388 | + return @"Song"; |
1389 | +} |
1390 | + |
1391 | ++ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_ { |
1392 | + NSParameterAssert(moc_); |
1393 | + return [NSEntityDescription entityForName:@"Song" inManagedObjectContext:moc_]; |
1394 | +} |
1395 | + |
1396 | +- (SongID*)objectID { |
1397 | + return (SongID*)[super objectID]; |
1398 | +} |
1399 | + |
1400 | ++ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { |
1401 | + NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; |
1402 | + |
1403 | + if ([key isEqualToString:@"bitRateValue"]) { |
1404 | + NSSet *affectingKey = [NSSet setWithObject:@"bitRate"]; |
1405 | + keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey]; |
1406 | + } |
1407 | + if ([key isEqualToString:@"discNumberValue"]) { |
1408 | + NSSet *affectingKey = [NSSet setWithObject:@"discNumber"]; |
1409 | + keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey]; |
1410 | + } |
1411 | + if ([key isEqualToString:@"durationValue"]) { |
1412 | + NSSet *affectingKey = [NSSet setWithObject:@"duration"]; |
1413 | + keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey]; |
1414 | + } |
1415 | + if ([key isEqualToString:@"sizeValue"]) { |
1416 | + NSSet *affectingKey = [NSSet setWithObject:@"size"]; |
1417 | + keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey]; |
1418 | + } |
1419 | + if ([key isEqualToString:@"trackValue"]) { |
1420 | + NSSet *affectingKey = [NSSet setWithObject:@"track"]; |
1421 | + keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey]; |
1422 | + } |
1423 | + if ([key isEqualToString:@"yearValue"]) { |
1424 | + NSSet *affectingKey = [NSSet setWithObject:@"year"]; |
1425 | + keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey]; |
1426 | + } |
1427 | + |
1428 | + return keyPaths; |
1429 | +} |
1430 | + |
1431 | + |
1432 | + |
1433 | + |
1434 | +@dynamic album; |
1435 | + |
1436 | + |
1437 | + |
1438 | + |
1439 | + |
1440 | + |
1441 | +@dynamic artist; |
1442 | + |
1443 | + |
1444 | + |
1445 | + |
1446 | + |
1447 | + |
1448 | +@dynamic bitRate; |
1449 | + |
1450 | + |
1451 | + |
1452 | +- (int)bitRateValue { |
1453 | + NSNumber *result = [self bitRate]; |
1454 | + return [result intValue]; |
1455 | +} |
1456 | + |
1457 | +- (void)setBitRateValue:(int)value_ { |
1458 | + [self setBitRate:[NSNumber numberWithInt:value_]]; |
1459 | +} |
1460 | + |
1461 | +- (int)primitiveBitRateValue { |
1462 | + NSNumber *result = [self primitiveBitRate]; |
1463 | + return [result intValue]; |
1464 | +} |
1465 | + |
1466 | +- (void)setPrimitiveBitRateValue:(int)value_ { |
1467 | + [self setPrimitiveBitRate:[NSNumber numberWithInt:value_]]; |
1468 | +} |
1469 | + |
1470 | + |
1471 | + |
1472 | + |
1473 | + |
1474 | +@dynamic cachedSongPath; |
1475 | + |
1476 | + |
1477 | + |
1478 | + |
1479 | + |
1480 | + |
1481 | +@dynamic coverArtId; |
1482 | + |
1483 | + |
1484 | + |
1485 | + |
1486 | + |
1487 | + |
1488 | +@dynamic discNumber; |
1489 | + |
1490 | + |
1491 | + |
1492 | +- (int)discNumberValue { |
1493 | + NSNumber *result = [self discNumber]; |
1494 | + return [result intValue]; |
1495 | +} |
1496 | + |
1497 | +- (void)setDiscNumberValue:(int)value_ { |
1498 | + [self setDiscNumber:[NSNumber numberWithInt:value_]]; |
1499 | +} |
1500 | + |
1501 | +- (int)primitiveDiscNumberValue { |
1502 | + NSNumber *result = [self primitiveDiscNumber]; |
1503 | + return [result intValue]; |
1504 | +} |
1505 | + |
1506 | +- (void)setPrimitiveDiscNumberValue:(int)value_ { |
1507 | + [self setPrimitiveDiscNumber:[NSNumber numberWithInt:value_]]; |
1508 | +} |
1509 | + |
1510 | + |
1511 | + |
1512 | + |
1513 | + |
1514 | +@dynamic duration; |
1515 | + |
1516 | + |
1517 | + |
1518 | +- (int)durationValue { |
1519 | + NSNumber *result = [self duration]; |
1520 | + return [result intValue]; |
1521 | +} |
1522 | + |
1523 | +- (void)setDurationValue:(int)value_ { |
1524 | + [self setDuration:[NSNumber numberWithInt:value_]]; |
1525 | +} |
1526 | + |
1527 | +- (int)primitiveDurationValue { |
1528 | + NSNumber *result = [self primitiveDuration]; |
1529 | + return [result intValue]; |
1530 | +} |
1531 | + |
1532 | +- (void)setPrimitiveDurationValue:(int)value_ { |
1533 | + [self setPrimitiveDuration:[NSNumber numberWithInt:value_]]; |
1534 | +} |
1535 | + |
1536 | + |
1537 | + |
1538 | + |
1539 | + |
1540 | +@dynamic genre; |
1541 | + |
1542 | + |
1543 | + |
1544 | + |
1545 | + |
1546 | + |
1547 | +@dynamic path; |
1548 | + |
1549 | + |
1550 | + |
1551 | + |
1552 | + |
1553 | + |
1554 | +@dynamic size; |
1555 | + |
1556 | + |
1557 | + |
1558 | +- (int)sizeValue { |
1559 | + NSNumber *result = [self size]; |
1560 | + return [result intValue]; |
1561 | +} |
1562 | + |
1563 | +- (void)setSizeValue:(int)value_ { |
1564 | + [self setSize:[NSNumber numberWithInt:value_]]; |
1565 | +} |
1566 | + |
1567 | +- (int)primitiveSizeValue { |
1568 | + NSNumber *result = [self primitiveSize]; |
1569 | + return [result intValue]; |
1570 | +} |
1571 | + |
1572 | +- (void)setPrimitiveSizeValue:(int)value_ { |
1573 | + [self setPrimitiveSize:[NSNumber numberWithInt:value_]]; |
1574 | +} |
1575 | + |
1576 | + |
1577 | + |
1578 | + |
1579 | + |
1580 | +@dynamic songId; |
1581 | + |
1582 | + |
1583 | + |
1584 | + |
1585 | + |
1586 | + |
1587 | +@dynamic title; |
1588 | + |
1589 | + |
1590 | + |
1591 | + |
1592 | + |
1593 | + |
1594 | +@dynamic track; |
1595 | + |
1596 | + |
1597 | + |
1598 | +- (int)trackValue { |
1599 | + NSNumber *result = [self track]; |
1600 | + return [result intValue]; |
1601 | +} |
1602 | + |
1603 | +- (void)setTrackValue:(int)value_ { |
1604 | + [self setTrack:[NSNumber numberWithInt:value_]]; |
1605 | +} |
1606 | + |
1607 | +- (int)primitiveTrackValue { |
1608 | + NSNumber *result = [self primitiveTrack]; |
1609 | + return [result intValue]; |
1610 | +} |
1611 | + |
1612 | +- (void)setPrimitiveTrackValue:(int)value_ { |
1613 | + [self setPrimitiveTrack:[NSNumber numberWithInt:value_]]; |
1614 | +} |
1615 | + |
1616 | + |
1617 | + |
1618 | + |
1619 | + |
1620 | +@dynamic year; |
1621 | + |
1622 | + |
1623 | + |
1624 | +- (int)yearValue { |
1625 | + NSNumber *result = [self year]; |
1626 | + return [result intValue]; |
1627 | +} |
1628 | + |
1629 | +- (void)setYearValue:(int)value_ { |
1630 | + [self setYear:[NSNumber numberWithInt:value_]]; |
1631 | +} |
1632 | + |
1633 | +- (int)primitiveYearValue { |
1634 | + NSNumber *result = [self primitiveYear]; |
1635 | + return [result intValue]; |
1636 | +} |
1637 | + |
1638 | +- (void)setPrimitiveYearValue:(int)value_ { |
1639 | + [self setPrimitiveYear:[NSNumber numberWithInt:value_]]; |
1640 | +} |
1641 | + |
1642 | + |
1643 | + |
1644 | + |
1645 | + |
1646 | +@dynamic albumEntity; |
1647 | + |
1648 | + |
1649 | + |
1650 | +@dynamic artistEntity; |
1651 | + |
1652 | + |
1653 | + |
1654 | +@dynamic playlistSongIndexes; |
1655 | + |
1656 | + |
1657 | +- (NSMutableSet*)playlistSongIndexesSet { |
1658 | + [self willAccessValueForKey:@"playlistSongIndexes"]; |
1659 | + NSMutableSet *result = (NSMutableSet*)[self mutableSetValueForKey:@"playlistSongIndexes"]; |
1660 | + [self didAccessValueForKey:@"playlistSongIndexes"]; |
1661 | + return result; |
1662 | +} |
1663 | + |
1664 | + |
1665 | + |
1666 | + |
1667 | + |
1668 | + |
1669 | +@end |
1670 | |
1671 | === renamed file 'models/MOC.h' => 'Models/MOC.h' |
1672 | === renamed file 'models/MOC.m' => 'Models/MOC.m' |
1673 | === added file 'Models/Playlist.h' |
1674 | --- Models/Playlist.h 1970-01-01 00:00:00 +0000 |
1675 | +++ Models/Playlist.h 2012-02-03 20:23:18 +0000 |
1676 | @@ -0,0 +1,29 @@ |
1677 | +// |
1678 | +// Copyright 2012 Canonical Ltd. |
1679 | +// |
1680 | +// This program is free software: you can redistribute it and/or modify it |
1681 | +// under the terms of the GNU Affero General Public License version 3, |
1682 | +// as published by the Free Software Foundation. |
1683 | +// |
1684 | +// This program is distributed in the hope that it will be useful, but |
1685 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
1686 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1687 | +// PURPOSE. See the GNU Affero General Public License for more details. |
1688 | +// |
1689 | +// You should have received a copy of the GNU Affero General Public License |
1690 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
1691 | + |
1692 | +#import "_Playlist.h" |
1693 | + |
1694 | +@class Song; |
1695 | + |
1696 | +@interface Playlist : _Playlist {} |
1697 | ++ (BOOL)playlistWithNameExists:(NSString*)aPlaylistName; |
1698 | ++ (Playlist*)playlistWithName:(NSString*)aPlaylistName; |
1699 | +- (BOOL)matchesSearchQuery:(NSString *)query; |
1700 | +- (NSError*)loadSongs; |
1701 | +- (NSArray *)songs; |
1702 | +- (BOOL)isEditable; |
1703 | +- (void)addSong:(Song*)song; |
1704 | +- (void)removeSong:(Song*)song; |
1705 | +@end |
1706 | |
1707 | === added file 'Models/Playlist.m' |
1708 | --- Models/Playlist.m 1970-01-01 00:00:00 +0000 |
1709 | +++ Models/Playlist.m 2012-02-03 20:23:18 +0000 |
1710 | @@ -0,0 +1,130 @@ |
1711 | +// |
1712 | +// Copyright 2012 Canonical Ltd. |
1713 | +// |
1714 | +// This program is free software: you can redistribute it and/or modify it |
1715 | +// under the terms of the GNU Affero General Public License version 3, |
1716 | +// as published by the Free Software Foundation. |
1717 | +// |
1718 | +// This program is distributed in the hope that it will be useful, but |
1719 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
1720 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1721 | +// PURPOSE. See the GNU Affero General Public License for more details. |
1722 | +// |
1723 | +// You should have received a copy of the GNU Affero General Public License |
1724 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
1725 | + |
1726 | +#import "Playlist.h" |
1727 | +#import "Subsonic.h" |
1728 | +#import "NSMutableArray+Extras.h" |
1729 | +#import "PlaylistParser.h" |
1730 | +#import "PlaylistSongIndex.h" |
1731 | +#import "Song.h" |
1732 | + |
1733 | +@implementation Playlist |
1734 | + |
1735 | ++ (BOOL)playlistWithNameExists:(NSString *)aPlaylistName |
1736 | +{ |
1737 | + return (nil != [Playlist playlistWithName:aPlaylistName]); |
1738 | +} |
1739 | + |
1740 | ++ (Playlist *)playlistWithName:(NSString *)aPlaylistName |
1741 | +{ |
1742 | + NSFetchRequest * fetch = [[NSFetchRequest alloc] init]; |
1743 | + NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Playlist" inManagedObjectContext:PerThreadManagedObjectContext()]; |
1744 | + [fetch setEntity:entityDescription]; |
1745 | + |
1746 | + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == %@", aPlaylistName]; |
1747 | + [fetch setPredicate:predicate]; |
1748 | + |
1749 | + NSError * error = nil; |
1750 | + NSArray * matches = [PerThreadManagedObjectContext() executeFetchRequest:fetch error:&error]; |
1751 | + [fetch release]; |
1752 | + |
1753 | + if ([matches count] > 0) |
1754 | + { |
1755 | + return [matches objectAtIndex:0]; |
1756 | + } |
1757 | + else |
1758 | + { |
1759 | + return nil; |
1760 | + } |
1761 | +} |
1762 | + |
1763 | +- (NSError*)loadSongs |
1764 | +{ |
1765 | + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
1766 | + NSError *error = nil; |
1767 | + |
1768 | + NSMutableArray *parameters = [NSMutableArray array]; |
1769 | + [parameters addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"id", self.playlistId, nil]]; |
1770 | + NSURL *url = [[Subsonic sharedSubsonic] getMetadataURL:@"getPlaylist.view" parameters:parameters]; |
1771 | + NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url]; |
1772 | + |
1773 | + PlaylistParser *parser = [[PlaylistParser alloc] init]; |
1774 | + parser.playlistObjectId = [self objectID]; |
1775 | + |
1776 | + [xmlParser setDelegate:parser]; |
1777 | + |
1778 | + if (![xmlParser parse]) |
1779 | + { |
1780 | + error = [[xmlParser parserError] copy]; |
1781 | + } |
1782 | + |
1783 | + [xmlParser release]; |
1784 | + [parser release]; |
1785 | + [pool release]; |
1786 | + |
1787 | + return [error autorelease]; |
1788 | +} |
1789 | + |
1790 | +- (NSArray *)songs |
1791 | +{ |
1792 | + // return playlistSongIndexes sorted by index |
1793 | + NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"index" ascending:YES]; |
1794 | + NSArray *results = [[self.playlistSongIndexes sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]] valueForKey:@"songEntity"]; |
1795 | + return results; |
1796 | +} |
1797 | + |
1798 | +// Do the crazy PlaylistSongIndex lookup/clobber dance inside these methods |
1799 | +- (void)addSong:(Song *)song |
1800 | +{ |
1801 | + PlaylistSongIndex *playlistSongIndex = [NSEntityDescription insertNewObjectForEntityForName:@"PlaylistSongIndex" inManagedObjectContext:PerThreadManagedObjectContext()]; |
1802 | + playlistSongIndex.playlistEntity = self; |
1803 | + playlistSongIndex.songEntity = song; |
1804 | + playlistSongIndex.index = [NSNumber numberWithUnsignedInt:[self.playlistSongIndexes count]]; |
1805 | + SaveContext(); |
1806 | +} |
1807 | + |
1808 | +- (void)removeSong:(Song *)song |
1809 | +{ |
1810 | + // Look up (potentially) all records where playlistEntity is self, and songEntity is song, and blow them away |
1811 | + NSSet *condemned = [self.playlistSongIndexes filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"songEntity = %@", song]]; |
1812 | + for (PlaylistSongIndex *playlistSongIndex in condemned) |
1813 | + { |
1814 | + [PerThreadManagedObjectContext() deleteObject:playlistSongIndex]; |
1815 | + } |
1816 | + SaveContext(); |
1817 | + |
1818 | + [[self.playlistSongIndexes sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"index" ascending:YES]]] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { |
1819 | + ((PlaylistSongIndex *)obj).index = [NSNumber numberWithUnsignedInt:idx]; |
1820 | + }]; |
1821 | + SaveContext(); |
1822 | +} |
1823 | + |
1824 | +- (NSString*)description |
1825 | +{ |
1826 | + return [NSString stringWithFormat:@"%@ (%@) MOC %@", self.name, self.playlistId, [self managedObjectContext]]; |
1827 | +} |
1828 | + |
1829 | +- (BOOL)matchesSearchQuery:(NSString *)query |
1830 | +{ |
1831 | + NSRange titleResultsRange = [self.name rangeOfString:query options:NSCaseInsensitiveSearch]; |
1832 | + return titleResultsRange.length > 0; |
1833 | +} |
1834 | + |
1835 | +- (BOOL)isEditable; |
1836 | +{ |
1837 | + return YES; |
1838 | +} |
1839 | + |
1840 | +@end |
1841 | |
1842 | === added file 'Models/PlaylistSongIndex.h' |
1843 | --- Models/PlaylistSongIndex.h 1970-01-01 00:00:00 +0000 |
1844 | +++ Models/PlaylistSongIndex.h 2012-02-03 20:23:18 +0000 |
1845 | @@ -0,0 +1,20 @@ |
1846 | +// |
1847 | +// Copyright 2012 Canonical Ltd. |
1848 | +// |
1849 | +// This program is free software: you can redistribute it and/or modify it |
1850 | +// under the terms of the GNU Affero General Public License version 3, |
1851 | +// as published by the Free Software Foundation. |
1852 | +// |
1853 | +// This program is distributed in the hope that it will be useful, but |
1854 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
1855 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1856 | +// PURPOSE. See the GNU Affero General Public License for more details. |
1857 | +// |
1858 | +// You should have received a copy of the GNU Affero General Public License |
1859 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
1860 | + |
1861 | +#import "_PlaylistSongIndex.h" |
1862 | + |
1863 | +@interface PlaylistSongIndex : _PlaylistSongIndex {} |
1864 | +// Custom logic goes here. |
1865 | +@end |
1866 | |
1867 | === added file 'Models/PlaylistSongIndex.m' |
1868 | --- Models/PlaylistSongIndex.m 1970-01-01 00:00:00 +0000 |
1869 | +++ Models/PlaylistSongIndex.m 2012-02-03 20:23:18 +0000 |
1870 | @@ -0,0 +1,22 @@ |
1871 | +// |
1872 | +// Copyright 2012 Canonical Ltd. |
1873 | +// |
1874 | +// This program is free software: you can redistribute it and/or modify it |
1875 | +// under the terms of the GNU Affero General Public License version 3, |
1876 | +// as published by the Free Software Foundation. |
1877 | +// |
1878 | +// This program is distributed in the hope that it will be useful, but |
1879 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
1880 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1881 | +// PURPOSE. See the GNU Affero General Public License for more details. |
1882 | +// |
1883 | +// You should have received a copy of the GNU Affero General Public License |
1884 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
1885 | + |
1886 | +#import "PlaylistSongIndex.h" |
1887 | + |
1888 | +@implementation PlaylistSongIndex |
1889 | + |
1890 | +// Custom logic goes here. |
1891 | + |
1892 | +@end |
1893 | |
1894 | === added file 'Models/Song.h' |
1895 | --- Models/Song.h 1970-01-01 00:00:00 +0000 |
1896 | +++ Models/Song.h 2012-02-03 20:23:18 +0000 |
1897 | @@ -0,0 +1,25 @@ |
1898 | +// |
1899 | +// Copyright 2012 Canonical Ltd. |
1900 | +// |
1901 | +// This program is free software: you can redistribute it and/or modify it |
1902 | +// under the terms of the GNU Affero General Public License version 3, |
1903 | +// as published by the Free Software Foundation. |
1904 | +// |
1905 | +// This program is distributed in the hope that it will be useful, but |
1906 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
1907 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1908 | +// PURPOSE. See the GNU Affero General Public License for more details. |
1909 | +// |
1910 | +// You should have received a copy of the GNU Affero General Public License |
1911 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
1912 | + |
1913 | +#import "_Song.h" |
1914 | + |
1915 | +@interface Song : _Song {} |
1916 | ++ (BOOL)songWithIdExists:(NSString*)aSongId; |
1917 | ++ (Song*)songWithId:(NSString*)aSongId; |
1918 | +- (BOOL)matchesSearchQuery:(NSString *)query; |
1919 | +- (NSString *)dearticlizedTitle; |
1920 | +- (BOOL)cachedSongExists; |
1921 | +- (NSURL*)cachedSongURL; |
1922 | +@end |
1923 | |
1924 | === added file 'Models/Song.m' |
1925 | --- Models/Song.m 1970-01-01 00:00:00 +0000 |
1926 | +++ Models/Song.m 2012-02-03 20:23:18 +0000 |
1927 | @@ -0,0 +1,96 @@ |
1928 | +// |
1929 | +// Copyright 2012 Canonical Ltd. |
1930 | +// |
1931 | +// This program is free software: you can redistribute it and/or modify it |
1932 | +// under the terms of the GNU Affero General Public License version 3, |
1933 | +// as published by the Free Software Foundation. |
1934 | +// |
1935 | +// This program is distributed in the hope that it will be useful, but |
1936 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
1937 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1938 | +// PURPOSE. See the GNU Affero General Public License for more details. |
1939 | +// |
1940 | +// You should have received a copy of the GNU Affero General Public License |
1941 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
1942 | + |
1943 | +#import "Song.h" |
1944 | +#import "Artist.h" |
1945 | +#import "Album.h" |
1946 | +#import "NSString+Extras.h" |
1947 | + |
1948 | +@implementation Song |
1949 | + |
1950 | ++ (BOOL)songWithIdExists:(NSString*)aSongId |
1951 | +{ |
1952 | + return (nil != [Song songWithId:aSongId]); |
1953 | +} |
1954 | + |
1955 | ++ (Song*)songWithId:(NSString*)aSongId |
1956 | +{ |
1957 | + NSFetchRequest * fetch = [[NSFetchRequest alloc] init]; |
1958 | + NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Song" inManagedObjectContext:PerThreadManagedObjectContext()]; |
1959 | + [fetch setEntity:entityDescription]; |
1960 | + |
1961 | + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"songId == %@", aSongId]; |
1962 | + [fetch setPredicate:predicate]; |
1963 | + |
1964 | + NSError * error = nil; |
1965 | + NSArray * matches = [PerThreadManagedObjectContext() executeFetchRequest:fetch error:&error]; |
1966 | + [fetch release]; |
1967 | + |
1968 | + if ([matches count] > 0) |
1969 | + { |
1970 | + return [matches objectAtIndex:0]; |
1971 | + } |
1972 | + else |
1973 | + { |
1974 | + return nil; |
1975 | + } |
1976 | +} |
1977 | + |
1978 | +- (NSURL*)cachedSongURL |
1979 | +{ |
1980 | + return [CachedMusicDirectory() URLByAppendingPathComponent:self.songId]; |
1981 | +} |
1982 | + |
1983 | +- (BOOL)cachedSongExists |
1984 | +{ |
1985 | + return self.cachedSongPath != nil; |
1986 | +} |
1987 | + |
1988 | +- (NSComparisonResult)compare:(Song*)s |
1989 | +{ |
1990 | + NSUInteger selfPathArray[] = {[self.discNumber integerValue], [self.track integerValue]}; |
1991 | + NSUInteger otherPathArray[] = {[s.discNumber integerValue], [s.track integerValue]}; |
1992 | + |
1993 | + NSIndexPath *selfPath = [NSIndexPath indexPathWithIndexes:selfPathArray length:2]; |
1994 | + NSIndexPath *otherPath = [NSIndexPath indexPathWithIndexes:otherPathArray length:2]; |
1995 | + |
1996 | + return [selfPath compare:otherPath]; |
1997 | +} |
1998 | + |
1999 | +- (NSString*)description |
2000 | +{ |
2001 | + NSArray *keys = [NSArray arrayWithObjects:@"title", @"songId", @"artist", @"album", @"genre", @"coverArtId", @"path", @"duration", @"bitRate", @"track", @"year", @"size", nil]; |
2002 | + |
2003 | + NSMutableString *desc = [NSMutableString string]; |
2004 | + |
2005 | + for (NSString *k in keys) |
2006 | + { |
2007 | + [desc appendFormat:@"%@:%@ :: ",k, [self valueForKey:k]]; |
2008 | + } |
2009 | + return desc; |
2010 | +} |
2011 | + |
2012 | +- (BOOL)matchesSearchQuery:(NSString *)query |
2013 | +{ |
2014 | + NSRange titleResultsRange = [self.title rangeOfString:query options:NSCaseInsensitiveSearch]; |
2015 | + return titleResultsRange.length > 0; |
2016 | +} |
2017 | + |
2018 | +- (NSString *)dearticlizedTitle |
2019 | +{ |
2020 | + return [self.title dearticlizedString]; |
2021 | +} |
2022 | + |
2023 | +@end |
2024 | |
2025 | === modified file 'U1Music-Info.plist' |
2026 | --- U1Music-Info.plist 2011-11-10 19:50:55 +0000 |
2027 | +++ U1Music-Info.plist 2012-02-03 20:23:18 +0000 |
2028 | @@ -39,7 +39,7 @@ |
2029 | </dict> |
2030 | </array> |
2031 | <key>CFBundleVersion</key> |
2032 | - <string>30</string> |
2033 | + <string>31</string> |
2034 | <key>LSRequiresIPhoneOS</key> |
2035 | <false/> |
2036 | <key>NSMainNibFile</key> |
2037 | |
2038 | === modified file 'U1Music.xcodeproj/project.pbxproj' |
2039 | --- U1Music.xcodeproj/project.pbxproj 2011-11-03 18:33:32 +0000 |
2040 | +++ U1Music.xcodeproj/project.pbxproj 2012-02-03 20:23:18 +0000 |
2041 | @@ -3,7 +3,7 @@ |
2042 | archiveVersion = 1; |
2043 | classes = { |
2044 | }; |
2045 | - objectVersion = 45; |
2046 | + objectVersion = 46; |
2047 | objects = { |
2048 | |
2049 | /* Begin PBXBuildFile section */ |
2050 | @@ -57,15 +57,26 @@ |
2051 | 91406E9813849F2400A7DA67 /* uncached.png in Resources */ = {isa = PBXBuildFile; fileRef = 91406E9213849F2400A7DA67 /* uncached.png */; }; |
2052 | 91406E9913849F2400A7DA67 /* uncached@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 91406E9313849F2400A7DA67 /* uncached@2x.png */; }; |
2053 | 91406EEA138AEEE000A7DA67 /* NSString+Extras.m in Sources */ = {isa = PBXBuildFile; fileRef = 91406EE9138AEEE000A7DA67 /* NSString+Extras.m */; }; |
2054 | + 914AC3FF14B61D8A00C7D5A3 /* CachedSongsPlaylist.m in Sources */ = {isa = PBXBuildFile; fileRef = 914AC3F114B61D8A00C7D5A3 /* CachedSongsPlaylist.m */; }; |
2055 | + 914AC40014B61D8A00C7D5A3 /* _Album.m in Sources */ = {isa = PBXBuildFile; fileRef = 914AC3F414B61D8A00C7D5A3 /* _Album.m */; }; |
2056 | + 914AC40114B61D8A00C7D5A3 /* _Artist.m in Sources */ = {isa = PBXBuildFile; fileRef = 914AC3F614B61D8A00C7D5A3 /* _Artist.m */; }; |
2057 | + 914AC40214B61D8A00C7D5A3 /* _Playlist.m in Sources */ = {isa = PBXBuildFile; fileRef = 914AC3F814B61D8A00C7D5A3 /* _Playlist.m */; }; |
2058 | + 914AC40314B61D8A00C7D5A3 /* _PlaylistSongIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 914AC3FA14B61D8A00C7D5A3 /* _PlaylistSongIndex.m */; }; |
2059 | + 914AC40414B61D8A00C7D5A3 /* _Song.m in Sources */ = {isa = PBXBuildFile; fileRef = 914AC3FC14B61D8A00C7D5A3 /* _Song.m */; }; |
2060 | + 914AC40514B61D8A00C7D5A3 /* PlaylistSongIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 914AC3FE14B61D8A00C7D5A3 /* PlaylistSongIndex.m */; }; |
2061 | 919376F3135CC1CF0030B7BD /* PlaylistEditSongUITableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 919376F2135CC1CF0030B7BD /* PlaylistEditSongUITableViewCell.m */; }; |
2062 | 91B3A4441344CF92006C8193 /* SubsonicIndexedTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 91B3A4431344CF91006C8193 /* SubsonicIndexedTableViewController.m */; }; |
2063 | 91BE4018138E8D2300D44D68 /* UIActionSheet+Blocks.m in Sources */ = {isa = PBXBuildFile; fileRef = 91BE4015138E8D2300D44D68 /* UIActionSheet+Blocks.m */; }; |
2064 | 91BE4019138E8D2300D44D68 /* UIAlertView+Blocks.m in Sources */ = {isa = PBXBuildFile; fileRef = 91BE4017138E8D2300D44D68 /* UIAlertView+Blocks.m */; }; |
2065 | 91BE401C138E8D3A00D44D68 /* RIButtonItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 91BE401B138E8D3A00D44D68 /* RIButtonItem.m */; }; |
2066 | + 91C8CCAF14B7883600A0E311 /* ArtistUITableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C8CCAE14B7883600A0E311 /* ArtistUITableViewCell.m */; }; |
2067 | 91D18DAB13B228D3001BEB42 /* uncached-disabled.png in Resources */ = {isa = PBXBuildFile; fileRef = 91D18DA913B228D3001BEB42 /* uncached-disabled.png */; }; |
2068 | 91D18DAC13B228D3001BEB42 /* uncached-disabled@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 91D18DAA13B228D3001BEB42 /* uncached-disabled@2x.png */; }; |
2069 | + 91D3A16F14B93B2A003D4FC0 /* MOC.m in Sources */ = {isa = PBXBuildFile; fileRef = 91D3A16E14B93B2A003D4FC0 /* MOC.m */; }; |
2070 | + 91D3A17214BE12FE003D4FC0 /* PlaylistUITableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 91D3A17114BE12FE003D4FC0 /* PlaylistUITableViewCell.m */; }; |
2071 | 91DB6B9F13E9C7190029BC77 /* about_logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 91DB6B9E13E9C7190029BC77 /* about_logo.png */; }; |
2072 | - 91E0778913ABAD6200AA7CB2 /* PlaylistSongIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 91E0778813ABAD6200AA7CB2 /* PlaylistSongIndex.m */; }; |
2073 | + 91E3E46414D33A2D006ED32F /* U1SerializedDownloadOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 91E3E46314D33A2D006ED32F /* U1SerializedDownloadOperation.m */; }; |
2074 | + 91E3E46814D33A6F006ED32F /* U1ChunkDownloadOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 91E3E46714D33A6F006ED32F /* U1ChunkDownloadOperation.m */; }; |
2075 | 91E88609132DA82000618994 /* PlaylistParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 91E88608132DA82000618994 /* PlaylistParser.m */; }; |
2076 | 9316628812264A74003B0EB7 /* NSDate+Extras.m in Sources */ = {isa = PBXBuildFile; fileRef = 9316628712264A74003B0EB7 /* NSDate+Extras.m */; }; |
2077 | 932E7A6E1254747E00E7C8FF /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 932E7A6D1254747E00E7C8FF /* Default@2x.png */; }; |
2078 | @@ -106,7 +117,6 @@ |
2079 | 93D6B5151252CB34007880B0 /* music_57@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 93D6B5141252CB34007880B0 /* music_57@2x.png */; }; |
2080 | 93D6B54B1252CE57007880B0 /* URLQueryStringParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D6B54A1252CE57007880B0 /* URLQueryStringParser.m */; }; |
2081 | 93DFFE3F135D70B60061F29F /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93DFFE3E135D70B60061F29F /* CoreData.framework */; }; |
2082 | - 93DFFE45135D71030061F29F /* MOC.m in Sources */ = {isa = PBXBuildFile; fileRef = 93DFFE44135D71030061F29F /* MOC.m */; }; |
2083 | 93DFFE4D135D71760061F29F /* music.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 93DFFE4C135D71760061F29F /* music.xcdatamodeld */; }; |
2084 | 93DFFE54135D72420061F29F /* NSManagedObjectContext+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 93DFFE53135D72420061F29F /* NSManagedObjectContext+Additions.m */; }; |
2085 | 93EE2AF0124993F100E7E060 /* ArtistListParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 93EE2AEF124993F100E7E060 /* ArtistListParser.m */; }; |
2086 | @@ -142,7 +152,6 @@ |
2087 | 93FA43A7124DEE0E0080DF62 /* whitetrack.png in Resources */ = {isa = PBXBuildFile; fileRef = 93FA43A4124DEE0E0080DF62 /* whitetrack.png */; }; |
2088 | 93FA43B5124DF07C0080DF62 /* player_overlay_bg.png in Resources */ = {isa = PBXBuildFile; fileRef = 93FA43B3124DF07C0080DF62 /* player_overlay_bg.png */; }; |
2089 | 93FA43B6124DF07C0080DF62 /* player_overlay_bg@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 93FA43B4124DF07C0080DF62 /* player_overlay_bg@2x.png */; }; |
2090 | - 9646DB7D13A8FF4700CB42D2 /* CachedSongsPlaylist.m in Sources */ = {isa = PBXBuildFile; fileRef = 9646DB7C13A8FF4700CB42D2 /* CachedSongsPlaylist.m */; }; |
2091 | 964FA3C213CA5C4F0018A65B /* JSONKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 964FA39513CA5C040018A65B /* JSONKit.m */; }; |
2092 | 964FA3C313CA5C4F0018A65B /* NSMutableURLRequest+Parameters.m in Sources */ = {isa = PBXBuildFile; fileRef = 964FA39A13CA5C040018A65B /* NSMutableURLRequest+Parameters.m */; }; |
2093 | 964FA3C413CA5C4F0018A65B /* NSString+URLEncoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 964FA39C13CA5C040018A65B /* NSString+URLEncoding.m */; }; |
2094 | @@ -248,6 +257,21 @@ |
2095 | 91406E9313849F2400A7DA67 /* uncached@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "uncached@2x.png"; sourceTree = "<group>"; }; |
2096 | 91406EE8138AEEE000A7DA67 /* NSString+Extras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+Extras.h"; sourceTree = "<group>"; }; |
2097 | 91406EE9138AEEE000A7DA67 /* NSString+Extras.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+Extras.m"; sourceTree = "<group>"; }; |
2098 | + 914AC3EE14B60ECC00C7D5A3 /* U1Music 2.2-31.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "U1Music 2.2-31.xcdatamodel"; sourceTree = "<group>"; }; |
2099 | + 914AC3F014B61D8A00C7D5A3 /* CachedSongsPlaylist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CachedSongsPlaylist.h; path = Models/CachedSongsPlaylist.h; sourceTree = SOURCE_ROOT; }; |
2100 | + 914AC3F114B61D8A00C7D5A3 /* CachedSongsPlaylist.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CachedSongsPlaylist.m; path = Models/CachedSongsPlaylist.m; sourceTree = SOURCE_ROOT; }; |
2101 | + 914AC3F314B61D8A00C7D5A3 /* _Album.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _Album.h; sourceTree = "<group>"; }; |
2102 | + 914AC3F414B61D8A00C7D5A3 /* _Album.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _Album.m; sourceTree = "<group>"; }; |
2103 | + 914AC3F514B61D8A00C7D5A3 /* _Artist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _Artist.h; sourceTree = "<group>"; }; |
2104 | + 914AC3F614B61D8A00C7D5A3 /* _Artist.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _Artist.m; sourceTree = "<group>"; }; |
2105 | + 914AC3F714B61D8A00C7D5A3 /* _Playlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _Playlist.h; sourceTree = "<group>"; }; |
2106 | + 914AC3F814B61D8A00C7D5A3 /* _Playlist.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _Playlist.m; sourceTree = "<group>"; }; |
2107 | + 914AC3F914B61D8A00C7D5A3 /* _PlaylistSongIndex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _PlaylistSongIndex.h; sourceTree = "<group>"; }; |
2108 | + 914AC3FA14B61D8A00C7D5A3 /* _PlaylistSongIndex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _PlaylistSongIndex.m; sourceTree = "<group>"; }; |
2109 | + 914AC3FB14B61D8A00C7D5A3 /* _Song.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _Song.h; sourceTree = "<group>"; }; |
2110 | + 914AC3FC14B61D8A00C7D5A3 /* _Song.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _Song.m; sourceTree = "<group>"; }; |
2111 | + 914AC3FD14B61D8A00C7D5A3 /* PlaylistSongIndex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlaylistSongIndex.h; path = Models/PlaylistSongIndex.h; sourceTree = SOURCE_ROOT; }; |
2112 | + 914AC3FE14B61D8A00C7D5A3 /* PlaylistSongIndex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PlaylistSongIndex.m; path = Models/PlaylistSongIndex.m; sourceTree = SOURCE_ROOT; }; |
2113 | 919376F1135CC1CF0030B7BD /* PlaylistEditSongUITableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlaylistEditSongUITableViewCell.h; sourceTree = "<group>"; }; |
2114 | 919376F2135CC1CF0030B7BD /* PlaylistEditSongUITableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlaylistEditSongUITableViewCell.m; sourceTree = "<group>"; }; |
2115 | 91B3A4421344CF90006C8193 /* SubsonicIndexedTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubsonicIndexedTableViewController.h; sourceTree = "<group>"; }; |
2116 | @@ -258,11 +282,19 @@ |
2117 | 91BE4017138E8D2300D44D68 /* UIAlertView+Blocks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIAlertView+Blocks.m"; sourceTree = "<group>"; }; |
2118 | 91BE401A138E8D3A00D44D68 /* RIButtonItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RIButtonItem.h; sourceTree = "<group>"; }; |
2119 | 91BE401B138E8D3A00D44D68 /* RIButtonItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RIButtonItem.m; sourceTree = "<group>"; }; |
2120 | + 91C8CCAD14B7883600A0E311 /* ArtistUITableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArtistUITableViewCell.h; sourceTree = "<group>"; }; |
2121 | + 91C8CCAE14B7883600A0E311 /* ArtistUITableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ArtistUITableViewCell.m; sourceTree = "<group>"; }; |
2122 | 91D18DA913B228D3001BEB42 /* uncached-disabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "uncached-disabled.png"; sourceTree = "<group>"; }; |
2123 | 91D18DAA13B228D3001BEB42 /* uncached-disabled@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "uncached-disabled@2x.png"; sourceTree = "<group>"; }; |
2124 | + 91D3A16D14B93B2A003D4FC0 /* MOC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MOC.h; path = Models/MOC.h; sourceTree = SOURCE_ROOT; }; |
2125 | + 91D3A16E14B93B2A003D4FC0 /* MOC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MOC.m; path = Models/MOC.m; sourceTree = SOURCE_ROOT; }; |
2126 | + 91D3A17014BE12FE003D4FC0 /* PlaylistUITableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlaylistUITableViewCell.h; sourceTree = "<group>"; }; |
2127 | + 91D3A17114BE12FE003D4FC0 /* PlaylistUITableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlaylistUITableViewCell.m; sourceTree = "<group>"; }; |
2128 | 91DB6B9E13E9C7190029BC77 /* about_logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = about_logo.png; sourceTree = "<group>"; }; |
2129 | - 91E0778713ABAD6100AA7CB2 /* PlaylistSongIndex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlaylistSongIndex.h; sourceTree = "<group>"; }; |
2130 | - 91E0778813ABAD6200AA7CB2 /* PlaylistSongIndex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlaylistSongIndex.m; sourceTree = "<group>"; }; |
2131 | + 91E3E46214D33A2D006ED32F /* U1SerializedDownloadOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = U1SerializedDownloadOperation.h; sourceTree = "<group>"; }; |
2132 | + 91E3E46314D33A2D006ED32F /* U1SerializedDownloadOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = U1SerializedDownloadOperation.m; sourceTree = "<group>"; }; |
2133 | + 91E3E46614D33A6F006ED32F /* U1ChunkDownloadOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = U1ChunkDownloadOperation.h; sourceTree = "<group>"; }; |
2134 | + 91E3E46714D33A6F006ED32F /* U1ChunkDownloadOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = U1ChunkDownloadOperation.m; sourceTree = "<group>"; }; |
2135 | 91E88607132DA82000618994 /* PlaylistParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlaylistParser.h; sourceTree = "<group>"; }; |
2136 | 91E88608132DA82000618994 /* PlaylistParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlaylistParser.m; sourceTree = "<group>"; }; |
2137 | 9316628612264A74003B0EB7 /* NSDate+Extras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+Extras.h"; sourceTree = "<group>"; }; |
2138 | @@ -326,8 +358,6 @@ |
2139 | 93D6B5491252CE57007880B0 /* URLQueryStringParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLQueryStringParser.h; sourceTree = "<group>"; }; |
2140 | 93D6B54A1252CE57007880B0 /* URLQueryStringParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = URLQueryStringParser.m; sourceTree = "<group>"; }; |
2141 | 93DFFE3E135D70B60061F29F /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; |
2142 | - 93DFFE43135D71030061F29F /* MOC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOC.h; sourceTree = "<group>"; }; |
2143 | - 93DFFE44135D71030061F29F /* MOC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOC.m; sourceTree = "<group>"; }; |
2144 | 93DFFE48135D71550061F29F /* music.xcdatamodel */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = wrapper.xcdatamodel; path = music.xcdatamodel; sourceTree = "<group>"; }; |
2145 | 93DFFE52135D72420061F29F /* NSManagedObjectContext+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObjectContext+Additions.h"; sourceTree = "<group>"; }; |
2146 | 93DFFE53135D72420061F29F /* NSManagedObjectContext+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectContext+Additions.m"; sourceTree = "<group>"; }; |
2147 | @@ -381,8 +411,6 @@ |
2148 | 93FA43A4124DEE0E0080DF62 /* whitetrack.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = whitetrack.png; sourceTree = "<group>"; }; |
2149 | 93FA43B3124DF07C0080DF62 /* player_overlay_bg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = player_overlay_bg.png; sourceTree = "<group>"; }; |
2150 | 93FA43B4124DF07C0080DF62 /* player_overlay_bg@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "player_overlay_bg@2x.png"; sourceTree = "<group>"; }; |
2151 | - 9646DB7B13A8FF4700CB42D2 /* CachedSongsPlaylist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedSongsPlaylist.h; sourceTree = "<group>"; }; |
2152 | - 9646DB7C13A8FF4700CB42D2 /* CachedSongsPlaylist.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CachedSongsPlaylist.m; sourceTree = "<group>"; }; |
2153 | 964FA39313CA5C040018A65B /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = CHANGELOG.md; sourceTree = "<group>"; }; |
2154 | 964FA39413CA5C040018A65B /* JSONKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSONKit.h; sourceTree = "<group>"; }; |
2155 | 964FA39513CA5C040018A65B /* JSONKit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JSONKit.m; sourceTree = "<group>"; }; |
2156 | @@ -641,6 +669,24 @@ |
2157 | path = "TestFlight SDK"; |
2158 | sourceTree = "<group>"; |
2159 | }; |
2160 | + 914AC3F214B61D8A00C7D5A3 /* Generated */ = { |
2161 | + isa = PBXGroup; |
2162 | + children = ( |
2163 | + 914AC3F314B61D8A00C7D5A3 /* _Album.h */, |
2164 | + 914AC3F414B61D8A00C7D5A3 /* _Album.m */, |
2165 | + 914AC3F514B61D8A00C7D5A3 /* _Artist.h */, |
2166 | + 914AC3F614B61D8A00C7D5A3 /* _Artist.m */, |
2167 | + 914AC3F714B61D8A00C7D5A3 /* _Playlist.h */, |
2168 | + 914AC3F814B61D8A00C7D5A3 /* _Playlist.m */, |
2169 | + 914AC3F914B61D8A00C7D5A3 /* _PlaylistSongIndex.h */, |
2170 | + 914AC3FA14B61D8A00C7D5A3 /* _PlaylistSongIndex.m */, |
2171 | + 914AC3FB14B61D8A00C7D5A3 /* _Song.h */, |
2172 | + 914AC3FC14B61D8A00C7D5A3 /* _Song.m */, |
2173 | + ); |
2174 | + name = Generated; |
2175 | + path = Models/Generated; |
2176 | + sourceTree = SOURCE_ROOT; |
2177 | + }; |
2178 | 9316628512264A74003B0EB7 /* Categories */ = { |
2179 | isa = PBXGroup; |
2180 | children = ( |
2181 | @@ -702,6 +748,10 @@ |
2182 | 936F230912284D1900070F43 /* NamedTextFieldCell.m */, |
2183 | 912D1262134A162000721EE4 /* AlertPrompt.h */, |
2184 | 912D1263134A162000721EE4 /* AlertPrompt.m */, |
2185 | + 91C8CCAD14B7883600A0E311 /* ArtistUITableViewCell.h */, |
2186 | + 91C8CCAE14B7883600A0E311 /* ArtistUITableViewCell.m */, |
2187 | + 91D3A17014BE12FE003D4FC0 /* PlaylistUITableViewCell.h */, |
2188 | + 91D3A17114BE12FE003D4FC0 /* PlaylistUITableViewCell.m */, |
2189 | ); |
2190 | name = Controls; |
2191 | path = controls; |
2192 | @@ -710,8 +760,9 @@ |
2193 | 936F20651227363800070F43 /* Models */ = { |
2194 | isa = PBXGroup; |
2195 | children = ( |
2196 | - 93DFFE43135D71030061F29F /* MOC.h */, |
2197 | - 93DFFE44135D71030061F29F /* MOC.m */, |
2198 | + 914AC3F214B61D8A00C7D5A3 /* Generated */, |
2199 | + 91D3A16D14B93B2A003D4FC0 /* MOC.h */, |
2200 | + 91D3A16E14B93B2A003D4FC0 /* MOC.m */, |
2201 | 93F3344E1247FA2C006C6707 /* Album.h */, |
2202 | 93F3344F1247FA2C006C6707 /* Album.m */, |
2203 | 93F334501247FA2C006C6707 /* Artist.h */, |
2204 | @@ -720,10 +771,10 @@ |
2205 | 936F208F12273D9000070F43 /* Song.m */, |
2206 | 936F20661227364200070F43 /* Playlist.h */, |
2207 | 936F20671227364200070F43 /* Playlist.m */, |
2208 | - 9646DB7B13A8FF4700CB42D2 /* CachedSongsPlaylist.h */, |
2209 | - 9646DB7C13A8FF4700CB42D2 /* CachedSongsPlaylist.m */, |
2210 | - 91E0778713ABAD6100AA7CB2 /* PlaylistSongIndex.h */, |
2211 | - 91E0778813ABAD6200AA7CB2 /* PlaylistSongIndex.m */, |
2212 | + 914AC3FD14B61D8A00C7D5A3 /* PlaylistSongIndex.h */, |
2213 | + 914AC3FE14B61D8A00C7D5A3 /* PlaylistSongIndex.m */, |
2214 | + 914AC3F014B61D8A00C7D5A3 /* CachedSongsPlaylist.h */, |
2215 | + 914AC3F114B61D8A00C7D5A3 /* CachedSongsPlaylist.m */, |
2216 | ); |
2217 | name = Models; |
2218 | path = models; |
2219 | @@ -732,6 +783,10 @@ |
2220 | 937FAA0C137CFC1B00507E51 /* operations */ = { |
2221 | isa = PBXGroup; |
2222 | children = ( |
2223 | + 91E3E46214D33A2D006ED32F /* U1SerializedDownloadOperation.h */, |
2224 | + 91E3E46314D33A2D006ED32F /* U1SerializedDownloadOperation.m */, |
2225 | + 91E3E46614D33A6F006ED32F /* U1ChunkDownloadOperation.h */, |
2226 | + 91E3E46714D33A6F006ED32F /* U1ChunkDownloadOperation.m */, |
2227 | 937FAA16137CFC7200507E51 /* DownloadOperation.h */, |
2228 | 937FAA17137CFC7200507E51 /* DownloadOperation.m */, |
2229 | 937FAA13137CFC5000507E51 /* Downloader.h */, |
2230 | @@ -976,10 +1031,11 @@ |
2231 | 29B97313FDCFA39411CA2CEA /* Project object */ = { |
2232 | isa = PBXProject; |
2233 | attributes = { |
2234 | + LastUpgradeCheck = 0420; |
2235 | ORGANIZATIONNAME = Canonical; |
2236 | }; |
2237 | buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "U1Music" */; |
2238 | - compatibilityVersion = "Xcode 3.1"; |
2239 | + compatibilityVersion = "Xcode 3.2"; |
2240 | developmentRegion = English; |
2241 | hasScannedForEncodings = 1; |
2242 | knownRegions = ( |
2243 | @@ -1162,7 +1218,6 @@ |
2244 | 91018B4E135A724B0051EFDC /* PlaylistEditArtistViewController.m in Sources */, |
2245 | 91018B4F135A724B0051EFDC /* PlaylistEditSongListViewController.m in Sources */, |
2246 | 919376F3135CC1CF0030B7BD /* PlaylistEditSongUITableViewCell.m in Sources */, |
2247 | - 93DFFE45135D71030061F29F /* MOC.m in Sources */, |
2248 | 93DFFE4D135D71760061F29F /* music.xcdatamodeld in Sources */, |
2249 | 93DFFE54135D72420061F29F /* NSManagedObjectContext+Additions.m in Sources */, |
2250 | 937FAA11137CFC1B00507E51 /* AlbumArtLoader.m in Sources */, |
2251 | @@ -1176,14 +1231,24 @@ |
2252 | 91BE4019138E8D2300D44D68 /* UIAlertView+Blocks.m in Sources */, |
2253 | 91BE401C138E8D3A00D44D68 /* RIButtonItem.m in Sources */, |
2254 | 9674C2C513A7DC01004509E4 /* UORadialProgressControl.m in Sources */, |
2255 | - 9646DB7D13A8FF4700CB42D2 /* CachedSongsPlaylist.m in Sources */, |
2256 | 96FB790A13AA628700D8D4A4 /* UONetworkStatusCoordinator.m in Sources */, |
2257 | - 91E0778913ABAD6200AA7CB2 /* PlaylistSongIndex.m in Sources */, |
2258 | 9654C9BC13C7826900D0EEA0 /* UOSSOCredentialsViewController.m in Sources */, |
2259 | 9654C9C713C7AF9200D0EEA0 /* UOMusicLoginController.m in Sources */, |
2260 | 964FA3DF13CA5D1D0018A65B /* UOJSONFetchOperation.m in Sources */, |
2261 | 964FA3EA13CA848D0018A65B /* UOHTTPFetchOperation.m in Sources */, |
2262 | 964FA3ED13CA8C490018A65B /* UOSSOMusicCredsFetchOperation.m in Sources */, |
2263 | + 914AC3FF14B61D8A00C7D5A3 /* CachedSongsPlaylist.m in Sources */, |
2264 | + 914AC40014B61D8A00C7D5A3 /* _Album.m in Sources */, |
2265 | + 914AC40114B61D8A00C7D5A3 /* _Artist.m in Sources */, |
2266 | + 914AC40214B61D8A00C7D5A3 /* _Playlist.m in Sources */, |
2267 | + 914AC40314B61D8A00C7D5A3 /* _PlaylistSongIndex.m in Sources */, |
2268 | + 914AC40414B61D8A00C7D5A3 /* _Song.m in Sources */, |
2269 | + 914AC40514B61D8A00C7D5A3 /* PlaylistSongIndex.m in Sources */, |
2270 | + 91C8CCAF14B7883600A0E311 /* ArtistUITableViewCell.m in Sources */, |
2271 | + 91D3A16F14B93B2A003D4FC0 /* MOC.m in Sources */, |
2272 | + 91D3A17214BE12FE003D4FC0 /* PlaylistUITableViewCell.m in Sources */, |
2273 | + 91E3E46414D33A2D006ED32F /* U1SerializedDownloadOperation.m in Sources */, |
2274 | + 91E3E46814D33A6F006ED32F /* U1ChunkDownloadOperation.m in Sources */, |
2275 | ); |
2276 | runOnlyForDeploymentPostprocessing = 0; |
2277 | }; |
2278 | @@ -1266,7 +1331,6 @@ |
2279 | GCC_WARN_UNUSED_VARIABLE = YES; |
2280 | IPHONEOS_DEPLOYMENT_TARGET = 4.0; |
2281 | OTHER_CFLAGS = ""; |
2282 | - PREBINDING = NO; |
2283 | PROVISIONING_PROFILE = ""; |
2284 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; |
2285 | SDKROOT = iphoneos; |
2286 | @@ -1285,7 +1349,6 @@ |
2287 | GCC_WARN_ABOUT_RETURN_TYPE = YES; |
2288 | GCC_WARN_UNUSED_VARIABLE = YES; |
2289 | IPHONEOS_DEPLOYMENT_TARGET = 4.0; |
2290 | - PREBINDING = NO; |
2291 | PROVISIONING_PROFILE = ""; |
2292 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; |
2293 | SDKROOT = iphoneos; |
2294 | @@ -1319,9 +1382,10 @@ |
2295 | 93DFFE4C135D71760061F29F /* music.xcdatamodeld */ = { |
2296 | isa = XCVersionGroup; |
2297 | children = ( |
2298 | + 914AC3EE14B60ECC00C7D5A3 /* U1Music 2.2-31.xcdatamodel */, |
2299 | 93DFFE48135D71550061F29F /* music.xcdatamodel */, |
2300 | ); |
2301 | - currentVersion = 93DFFE48135D71550061F29F /* music.xcdatamodel */; |
2302 | + currentVersion = 914AC3EE14B60ECC00C7D5A3 /* U1Music 2.2-31.xcdatamodel */; |
2303 | path = music.xcdatamodeld; |
2304 | sourceTree = "<group>"; |
2305 | versionGroupType = wrapper.xcdatamodel; |
2306 | |
2307 | === modified file 'controls/AlbumArtistUITableViewCell.h' |
2308 | --- controls/AlbumArtistUITableViewCell.h 2011-05-05 16:38:37 +0000 |
2309 | +++ controls/AlbumArtistUITableViewCell.h 2012-02-03 20:23:18 +0000 |
2310 | @@ -19,6 +19,8 @@ |
2311 | |
2312 | #import <UIKit/UIKit.h> |
2313 | |
2314 | +@class Album; |
2315 | + |
2316 | @interface AlbumArtistUITableViewCell : UITableViewCell { |
2317 | UIImageView *coverArtView; |
2318 | UILabel *albumNameLabel; |
2319 | @@ -27,4 +29,5 @@ |
2320 | @property (nonatomic, retain) UIImageView *coverArtView; |
2321 | @property (nonatomic, retain) UILabel *albumNameLabel; |
2322 | @property (nonatomic, retain) UILabel *artistNameLabel; |
2323 | +@property (nonatomic, retain) Album *album; |
2324 | @end |
2325 | |
2326 | === modified file 'controls/AlbumArtistUITableViewCell.m' |
2327 | --- controls/AlbumArtistUITableViewCell.m 2011-05-05 16:38:37 +0000 |
2328 | +++ controls/AlbumArtistUITableViewCell.m 2012-02-03 20:23:18 +0000 |
2329 | @@ -20,7 +20,7 @@ |
2330 | #import "AlbumArtistUITableViewCell.h" |
2331 | |
2332 | @implementation AlbumArtistUITableViewCell |
2333 | -@synthesize coverArtView, albumNameLabel, artistNameLabel; |
2334 | +@synthesize coverArtView, albumNameLabel, artistNameLabel, album; |
2335 | |
2336 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier |
2337 | { |
2338 | |
2339 | === modified file 'controls/AlbumUITableViewCell.h' |
2340 | --- controls/AlbumUITableViewCell.h 2011-05-27 18:22:51 +0000 |
2341 | +++ controls/AlbumUITableViewCell.h 2012-02-03 20:23:18 +0000 |
2342 | @@ -30,6 +30,8 @@ |
2343 | |
2344 | #import <UIKit/UIKit.h> |
2345 | |
2346 | +@class Album; |
2347 | + |
2348 | @interface AlbumUITableViewCell : UITableViewCell { |
2349 | UIImageView *coverArtView; |
2350 | UILabel *albumNameLabel; |
2351 | @@ -37,5 +39,6 @@ |
2352 | |
2353 | @property (nonatomic, retain) UIImageView *coverArtView; |
2354 | @property (nonatomic, retain) UILabel *albumNameLabel; |
2355 | +@property (nonatomic, retain) Album *album; |
2356 | |
2357 | @end |
2358 | |
2359 | === modified file 'controls/AlbumUITableViewCell.m' |
2360 | --- controls/AlbumUITableViewCell.m 2011-05-27 18:22:51 +0000 |
2361 | +++ controls/AlbumUITableViewCell.m 2012-02-03 20:23:18 +0000 |
2362 | @@ -32,7 +32,7 @@ |
2363 | |
2364 | @implementation AlbumUITableViewCell |
2365 | |
2366 | -@synthesize coverArtView, albumNameLabel; |
2367 | +@synthesize coverArtView, albumNameLabel, album; |
2368 | |
2369 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { |
2370 | if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) { |
2371 | |
2372 | === added file 'controls/ArtistUITableViewCell.h' |
2373 | --- controls/ArtistUITableViewCell.h 1970-01-01 00:00:00 +0000 |
2374 | +++ controls/ArtistUITableViewCell.h 2012-02-03 20:23:18 +0000 |
2375 | @@ -0,0 +1,24 @@ |
2376 | +// |
2377 | +// Copyright 2012 Canonical Ltd. |
2378 | +// |
2379 | +// This program is free software: you can redistribute it and/or modify it |
2380 | +// under the terms of the GNU Affero General Public License version 3, |
2381 | +// as published by the Free Software Foundation. |
2382 | +// |
2383 | +// This program is distributed in the hope that it will be useful, but |
2384 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
2385 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2386 | +// PURPOSE. See the GNU Affero General Public License for more details. |
2387 | +// |
2388 | +// You should have received a copy of the GNU Affero General Public License |
2389 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
2390 | + |
2391 | +#import <UIKit/UIKit.h> |
2392 | + |
2393 | +@class Artist; |
2394 | + |
2395 | +@interface ArtistUITableViewCell : UITableViewCell {} |
2396 | + |
2397 | +@property (nonatomic, retain) Artist *artist; |
2398 | + |
2399 | +@end |
2400 | |
2401 | === added file 'controls/ArtistUITableViewCell.m' |
2402 | --- controls/ArtistUITableViewCell.m 1970-01-01 00:00:00 +0000 |
2403 | +++ controls/ArtistUITableViewCell.m 2012-02-03 20:23:18 +0000 |
2404 | @@ -0,0 +1,23 @@ |
2405 | +// |
2406 | +// Copyright 2012 Canonical Ltd. |
2407 | +// |
2408 | +// This program is free software: you can redistribute it and/or modify it |
2409 | +// under the terms of the GNU Affero General Public License version 3, |
2410 | +// as published by the Free Software Foundation. |
2411 | +// |
2412 | +// This program is distributed in the hope that it will be useful, but |
2413 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
2414 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2415 | +// PURPOSE. See the GNU Affero General Public License for more details. |
2416 | +// |
2417 | +// You should have received a copy of the GNU Affero General Public License |
2418 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
2419 | + |
2420 | +#import "ArtistUITableViewCell.h" |
2421 | +#import "Artist.h" |
2422 | + |
2423 | +@implementation ArtistUITableViewCell |
2424 | + |
2425 | +@synthesize artist; |
2426 | + |
2427 | +@end |
2428 | |
2429 | === added file 'controls/PlaylistUITableViewCell.h' |
2430 | --- controls/PlaylistUITableViewCell.h 1970-01-01 00:00:00 +0000 |
2431 | +++ controls/PlaylistUITableViewCell.h 2012-02-03 20:23:18 +0000 |
2432 | @@ -0,0 +1,23 @@ |
2433 | +// |
2434 | +// Copyright 2012 Canonical Ltd. |
2435 | +// |
2436 | +// This program is free software: you can redistribute it and/or modify it |
2437 | +// under the terms of the GNU Affero General Public License version 3, |
2438 | +// as published by the Free Software Foundation. |
2439 | +// |
2440 | +// This program is distributed in the hope that it will be useful, but |
2441 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
2442 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2443 | +// PURPOSE. See the GNU Affero General Public License for more details. |
2444 | +// |
2445 | +// You should have received a copy of the GNU Affero General Public License |
2446 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
2447 | + |
2448 | +#import <UIKit/UIKit.h> |
2449 | + |
2450 | +@class Playlist; |
2451 | + |
2452 | +@interface PlaylistUITableViewCell : UITableViewCell {} |
2453 | +@property (nonatomic, retain) Playlist *playlist; |
2454 | + |
2455 | +@end |
2456 | |
2457 | === added file 'controls/PlaylistUITableViewCell.m' |
2458 | --- controls/PlaylistUITableViewCell.m 1970-01-01 00:00:00 +0000 |
2459 | +++ controls/PlaylistUITableViewCell.m 2012-02-03 20:23:18 +0000 |
2460 | @@ -0,0 +1,22 @@ |
2461 | +// |
2462 | +// Copyright 2012 Canonical Ltd. |
2463 | +// |
2464 | +// This program is free software: you can redistribute it and/or modify it |
2465 | +// under the terms of the GNU Affero General Public License version 3, |
2466 | +// as published by the Free Software Foundation. |
2467 | +// |
2468 | +// This program is distributed in the hope that it will be useful, but |
2469 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
2470 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2471 | +// PURPOSE. See the GNU Affero General Public License for more details. |
2472 | +// |
2473 | +// You should have received a copy of the GNU Affero General Public License |
2474 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
2475 | + |
2476 | +#import "PlaylistUITableViewCell.h" |
2477 | + |
2478 | +@implementation PlaylistUITableViewCell |
2479 | + |
2480 | +@synthesize playlist; |
2481 | + |
2482 | +@end |
2483 | |
2484 | === removed directory 'models' |
2485 | === removed file 'models/Album.h' |
2486 | --- models/Album.h 2011-06-14 17:06:21 +0000 |
2487 | +++ models/Album.h 1970-01-01 00:00:00 +0000 |
2488 | @@ -1,58 +0,0 @@ |
2489 | -// |
2490 | -// Album.h |
2491 | -// iSub |
2492 | -// |
2493 | -// Created by Ben Baron on 2/28/10. |
2494 | -// Copyright 2010 Ben Baron. All rights reserved. |
2495 | -// |
2496 | -// Redistribution and use in source and binary forms, with or without modification, |
2497 | -// are permitted provided that the following conditions are met: |
2498 | -// |
2499 | -// * Redistributions of source code must retain the above copyright notice, this |
2500 | -// list of conditions and the following disclaimer. |
2501 | -// * Redistributions in binary form must reproduce the above copyright notice, |
2502 | -// this list of conditions and the following disclaimer in the documentation |
2503 | -// and/or other materials provided with the distribution. |
2504 | -// * Neither the my name nor the names of my contributors may be used to endorse |
2505 | -// or promote products derived from this software without specific prior written |
2506 | -// permission. |
2507 | -// |
2508 | -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY |
2509 | -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
2510 | -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
2511 | -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
2512 | -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
2513 | -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
2514 | -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
2515 | -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
2516 | -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
2517 | -// DAMAGE. |
2518 | - |
2519 | -@class Artist, Song; |
2520 | - |
2521 | -@interface Album : NSManagedObject |
2522 | -{ |
2523 | -} |
2524 | -@property (nonatomic, retain) NSString *title; |
2525 | -@property (nonatomic, retain) NSString *artist; |
2526 | -@property (nonatomic, retain) NSString *albumId; |
2527 | -@property (nonatomic, retain) NSString *coverArtId; |
2528 | -@property (nonatomic, retain) Artist * artistEntity; |
2529 | -@property (nonatomic, retain) NSSet *songs; |
2530 | - |
2531 | -+ (BOOL)albumWithIdExists:(NSString*)anAlbumId; |
2532 | -+ (Album*)albumWithId:(NSString*)anAlbumId; |
2533 | -+ (Album*)albumWithTitle:(NSString*)albumTitle artist:(NSString*)albumArtist; |
2534 | -- (BOOL)matchesSearchQuery:(NSString *)query; |
2535 | -- (NSError*)loadSongs; |
2536 | -- (NSString*)dearticlizedTitle; |
2537 | -- (BOOL)hasCachedSongs; |
2538 | -@end |
2539 | - |
2540 | -// coalesce these into one @interface Album (CoreDataGeneratedAccessors) section |
2541 | -@interface Album (CoreDataGeneratedAccessors) |
2542 | -- (void)addSongsObject:(Song *)value; |
2543 | -- (void)removeSongsObject:(Song *)value; |
2544 | -- (void)addSongs:(NSSet *)value; |
2545 | -- (void)removeSongs:(NSSet *)value; |
2546 | -@end |
2547 | |
2548 | === removed file 'models/Album.m' |
2549 | --- models/Album.m 2011-11-05 00:42:21 +0000 |
2550 | +++ models/Album.m 1970-01-01 00:00:00 +0000 |
2551 | @@ -1,131 +0,0 @@ |
2552 | -// |
2553 | -// Album.m |
2554 | -// iSub |
2555 | -// |
2556 | -// Created by Ben Baron on 2/28/10. |
2557 | -// Copyright 2010 Ben Baron. All rights reserved. |
2558 | -// |
2559 | -// Redistribution and use in source and binary forms, with or without modification, |
2560 | -// are permitted provided that the following conditions are met: |
2561 | -// |
2562 | -// * Redistributions of source code must retain the above copyright notice, this |
2563 | -// list of conditions and the following disclaimer. |
2564 | -// * Redistributions in binary form must reproduce the above copyright notice, |
2565 | -// this list of conditions and the following disclaimer in the documentation |
2566 | -// and/or other materials provided with the distribution. |
2567 | -// * Neither the my name nor the names of my contributors may be used to endorse |
2568 | -// or promote products derived from this software without specific prior written |
2569 | -// permission. |
2570 | -// |
2571 | -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY |
2572 | -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
2573 | -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
2574 | -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
2575 | -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
2576 | -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
2577 | -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
2578 | -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
2579 | -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
2580 | -// DAMAGE. |
2581 | - |
2582 | -#import "Album.h" |
2583 | -#import "Artist.h" |
2584 | -#import "NSMutableArray+Extras.h" |
2585 | -#import "NSString+Extras.h" |
2586 | -#import "AlbumParser.h" |
2587 | -#import "Subsonic.h" |
2588 | - |
2589 | -@interface Album () |
2590 | -+ (Album*)albumMatchingPredicate:(NSPredicate*)predicate; |
2591 | -@end |
2592 | - |
2593 | -@implementation Album |
2594 | -@dynamic title, artist, albumId, coverArtId; |
2595 | -@dynamic artistEntity, songs; |
2596 | - |
2597 | -+ (BOOL)albumWithIdExists:(NSString*)anAlbumId |
2598 | -{ |
2599 | - return (nil != [Album albumWithId:anAlbumId]); |
2600 | -} |
2601 | - |
2602 | -+ (Album*)albumWithId:(NSString*)anAlbumId |
2603 | -{ |
2604 | - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"albumId == %@", anAlbumId]; |
2605 | - return [self albumMatchingPredicate:predicate]; |
2606 | -} |
2607 | - |
2608 | -+ (Album*)albumWithTitle:(NSString*)albumTitle artist:(NSString*)albumArtist; |
2609 | -{ |
2610 | - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"title == %@ AND artist = %@", albumTitle, albumArtist]; |
2611 | - return [self albumMatchingPredicate:predicate]; |
2612 | -} |
2613 | - |
2614 | -+ (Album*)albumMatchingPredicate:(NSPredicate*)predicate; |
2615 | -{ |
2616 | - NSFetchRequest * fetch = [[NSFetchRequest alloc] init]; |
2617 | - NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Album" inManagedObjectContext:PerThreadManagedObjectContext()]; |
2618 | - [fetch setEntity:entityDescription]; |
2619 | - [fetch setPredicate:predicate]; |
2620 | - NSError * error = nil; |
2621 | - NSArray * matches = [PerThreadManagedObjectContext() executeFetchRequest:fetch error:&error]; |
2622 | - [fetch release]; |
2623 | - |
2624 | - return [matches lastObject]; |
2625 | -} |
2626 | - |
2627 | -- (NSString *)dearticlizedTitle |
2628 | -{ |
2629 | - return [self.title dearticlizedString]; |
2630 | -} |
2631 | - |
2632 | -- (NSError*)loadSongs |
2633 | -{ |
2634 | - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
2635 | - NSError *error = nil; |
2636 | - |
2637 | - NSMutableArray *parameters = [NSMutableArray array]; |
2638 | - [parameters addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"id", self.albumId, nil]]; |
2639 | - NSURL *url = [[Subsonic sharedSubsonic] getMetadataURL:@"getAlbum.view" parameters:parameters]; |
2640 | - NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url]; |
2641 | - |
2642 | - AlbumParser *parser = [[AlbumParser alloc] init]; |
2643 | - parser.albumObjectId = [self objectID]; |
2644 | - |
2645 | - [xmlParser setDelegate:parser]; |
2646 | - |
2647 | - if (![xmlParser parse]) |
2648 | - { |
2649 | - error = [[xmlParser parserError] copy]; |
2650 | - } |
2651 | - |
2652 | - [xmlParser release]; |
2653 | - [parser release]; |
2654 | - [pool release]; |
2655 | - |
2656 | - return [error autorelease]; |
2657 | -} |
2658 | - |
2659 | -- (NSString*)description |
2660 | -{ |
2661 | - return [NSString stringWithFormat:@"%@ - %@ (%@) (art: %@) MOC %@",self.artist,self.title,self.albumId,self.coverArtId, [self managedObjectContext]]; |
2662 | -} |
2663 | - |
2664 | -- (BOOL)matchesSearchQuery:(NSString *)query |
2665 | -{ |
2666 | - NSRange titleResultsRange = [self.title rangeOfString:query options:NSCaseInsensitiveSearch]; |
2667 | - return titleResultsRange.length > 0; |
2668 | -} |
2669 | - |
2670 | -- (BOOL)hasCachedSongs; |
2671 | -{ |
2672 | - NSManagedObjectContext *moc = [self managedObjectContext]; |
2673 | - NSEntityDescription *songEntity = [NSEntityDescription entityForName:@"Song" inManagedObjectContext:moc]; |
2674 | - NSFetchRequest *fetch = [[[NSFetchRequest alloc] init] autorelease]; |
2675 | - [fetch setEntity:songEntity]; |
2676 | - [fetch setPredicate:[NSPredicate predicateWithFormat:@"album = %@ and cachedSongPath != NIL", self.title]]; |
2677 | - |
2678 | - NSArray *results = [[self managedObjectContext] executeFetchRequest:fetch error:NULL]; |
2679 | - return [results count] > 0; |
2680 | -} |
2681 | - |
2682 | -@end |
2683 | |
2684 | === removed file 'models/Artist.h' |
2685 | --- models/Artist.h 2011-06-14 17:06:21 +0000 |
2686 | +++ models/Artist.h 1970-01-01 00:00:00 +0000 |
2687 | @@ -1,59 +0,0 @@ |
2688 | -// |
2689 | -// Artist.h |
2690 | -// iSub |
2691 | -// |
2692 | -// Created by Ben Baron on 2/27/10. |
2693 | -// Copyright 2010 Ben Baron. All rights reserved. |
2694 | -// |
2695 | -// Redistribution and use in source and binary forms, with or without modification, |
2696 | -// are permitted provided that the following conditions are met: |
2697 | -// |
2698 | -// * Redistributions of source code must retain the above copyright notice, this |
2699 | -// list of conditions and the following disclaimer. |
2700 | -// * Redistributions in binary form must reproduce the above copyright notice, |
2701 | -// this list of conditions and the following disclaimer in the documentation |
2702 | -// and/or other materials provided with the distribution. |
2703 | -// * Neither the my name nor the names of my contributors may be used to endorse |
2704 | -// or promote products derived from this software without specific prior written |
2705 | -// permission. |
2706 | -// |
2707 | -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY |
2708 | -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
2709 | -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
2710 | -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
2711 | -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
2712 | -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
2713 | -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
2714 | -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
2715 | -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
2716 | -// DAMAGE. |
2717 | - |
2718 | -@class Album, Song; |
2719 | - |
2720 | -@interface Artist : NSManagedObject |
2721 | -{ |
2722 | -} |
2723 | -@property (nonatomic, retain) NSString *name; |
2724 | -@property (nonatomic, retain) NSString *artistId; |
2725 | -@property (nonatomic, retain) NSSet* albums; |
2726 | -@property (nonatomic, retain) NSSet* songs; |
2727 | -+ (Artist*)artistWithId:(NSString*)anArtistId; |
2728 | -+ (BOOL)artistWithIdExists:(NSString*)anArtistId; |
2729 | -+ (Artist*)artistWithName:(NSString*)artistName; |
2730 | -- (BOOL)matchesSearchQuery:(NSString *)query; |
2731 | -- (NSString *)dearticlizedName; |
2732 | -- (NSError*)loadAlbums; |
2733 | -- (BOOL)hasCachedSongs; |
2734 | -@end |
2735 | - |
2736 | -@interface Artist (CoreDataGeneratedAccessors) |
2737 | -- (void)addAlbumsObject:(Album *)value; |
2738 | -- (void)removeAlbumsObject:(Album *)value; |
2739 | -- (void)addAlbums:(NSSet *)value; |
2740 | -- (void)removeAlbums:(NSSet *)value; |
2741 | - |
2742 | -- (void)addSongsObject:(Song *)value; |
2743 | -- (void)removeSongsObject:(Song *)value; |
2744 | -- (void)addSongs:(NSSet *)value; |
2745 | -- (void)removeSongs:(NSSet *)value; |
2746 | -@end |
2747 | |
2748 | === removed file 'models/Artist.m' |
2749 | --- models/Artist.m 2011-11-05 00:42:21 +0000 |
2750 | +++ models/Artist.m 1970-01-01 00:00:00 +0000 |
2751 | @@ -1,135 +0,0 @@ |
2752 | -// |
2753 | -// Artist.m |
2754 | -// iSub |
2755 | -// |
2756 | -// Created by Ben Baron on 2/27/10. |
2757 | -// Copyright 2010 Ben Baron. All rights reserved. |
2758 | -// |
2759 | -// Redistribution and use in source and binary forms, with or without modification, |
2760 | -// are permitted provided that the following conditions are met: |
2761 | -// |
2762 | -// * Redistributions of source code must retain the above copyright notice, this |
2763 | -// list of conditions and the following disclaimer. |
2764 | -// * Redistributions in binary form must reproduce the above copyright notice, |
2765 | -// this list of conditions and the following disclaimer in the documentation |
2766 | -// and/or other materials provided with the distribution. |
2767 | -// * Neither the my name nor the names of my contributors may be used to endorse |
2768 | -// or promote products derived from this software without specific prior written |
2769 | -// permission. |
2770 | -// |
2771 | -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY |
2772 | -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
2773 | -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
2774 | -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
2775 | -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
2776 | -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
2777 | -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
2778 | -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
2779 | -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
2780 | -// DAMAGE. |
2781 | - |
2782 | -#import "Artist.h" |
2783 | -#import "Album.h" |
2784 | -#import "Subsonic.h" |
2785 | -#import "NSMutableArray+Extras.h" |
2786 | -#import "NSString+Extras.h" |
2787 | -#import "ArtistParser.h" |
2788 | - |
2789 | -@interface Artist () |
2790 | -+ (Artist*)artistMatchingPredicate:(NSPredicate*)predicate; |
2791 | -@end |
2792 | - |
2793 | - |
2794 | -@implementation Artist |
2795 | - |
2796 | -@dynamic name; |
2797 | -@dynamic artistId; |
2798 | -@dynamic albums; |
2799 | -@dynamic songs; |
2800 | - |
2801 | -+ (BOOL)artistWithIdExists:(NSString*)anArtistId |
2802 | -{ |
2803 | - return [Artist artistWithId:anArtistId] != nil; |
2804 | -} |
2805 | - |
2806 | -+ (Artist*)artistWithId:(NSString*)anArtistId |
2807 | -{ |
2808 | - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"artistId == %@", anArtistId]; |
2809 | - return [self artistMatchingPredicate:predicate]; |
2810 | -} |
2811 | - |
2812 | -+ (Artist*)artistWithName:(NSString*)artistName; |
2813 | -{ |
2814 | - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == %@", artistName]; |
2815 | - return [self artistMatchingPredicate:predicate]; |
2816 | -} |
2817 | - |
2818 | -+ (Artist*)artistMatchingPredicate:(NSPredicate*)predicate; |
2819 | -{ |
2820 | - NSFetchRequest * fetch = [[NSFetchRequest alloc] init]; |
2821 | - NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Artist" inManagedObjectContext:PerThreadManagedObjectContext()]; |
2822 | - [fetch setEntity:entityDescription]; |
2823 | - [fetch setPredicate:predicate]; |
2824 | - NSError * error = nil; |
2825 | - NSArray * matches = [PerThreadManagedObjectContext() executeFetchRequest:fetch error:&error]; |
2826 | - [fetch release]; |
2827 | - |
2828 | - return [matches lastObject]; |
2829 | -} |
2830 | - |
2831 | -- (NSString*)description |
2832 | -{ |
2833 | - return [NSString stringWithFormat:@"%@ (%@) MOC %@",self.name, self.artistId, [self managedObjectContext]]; |
2834 | -} |
2835 | - |
2836 | -- (BOOL)matchesSearchQuery:(NSString *)query |
2837 | -{ |
2838 | - NSRange titleResultsRange = [self.name rangeOfString:query options:NSCaseInsensitiveSearch]; |
2839 | - return titleResultsRange.length > 0; |
2840 | -} |
2841 | - |
2842 | -- (NSString *)dearticlizedName |
2843 | -{ |
2844 | - return [self.name dearticlizedString]; |
2845 | -} |
2846 | - |
2847 | -// Note: executes synchronously! |
2848 | -- (NSError*)loadAlbums |
2849 | -{ |
2850 | - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
2851 | - NSError *error = nil; |
2852 | - |
2853 | - NSMutableArray *parameters = [NSMutableArray array]; |
2854 | - [parameters addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"id", self.artistId, nil]]; |
2855 | - NSURL *url = [[Subsonic sharedSubsonic] getMetadataURL:@"getMusicDirectory.view" parameters:parameters]; |
2856 | - NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url]; |
2857 | - ArtistParser *parser = [[ArtistParser alloc] init]; |
2858 | - parser.artistManagedObjectID = [self objectID]; |
2859 | - [xmlParser setDelegate:parser]; |
2860 | - |
2861 | - if (![xmlParser parse]) |
2862 | - { |
2863 | - error = [[xmlParser parserError] copy]; |
2864 | - } |
2865 | - |
2866 | - [xmlParser release]; |
2867 | - [parser release]; |
2868 | - [pool release]; |
2869 | - |
2870 | - return [error autorelease]; |
2871 | -} |
2872 | - |
2873 | -- (BOOL)hasCachedSongs; |
2874 | -{ |
2875 | - NSManagedObjectContext *moc = [self managedObjectContext]; |
2876 | - NSEntityDescription *songEntity = [NSEntityDescription entityForName:@"Song" inManagedObjectContext:moc]; |
2877 | - NSFetchRequest *fetch = [[[NSFetchRequest alloc] init] autorelease]; |
2878 | - [fetch setEntity:songEntity]; |
2879 | - [fetch setPredicate:[NSPredicate predicateWithFormat:@"artist = %@ and cachedSongPath != NIL", self.name]]; |
2880 | - |
2881 | - NSError *error = nil; |
2882 | - NSArray *results = [moc executeFetchRequest:fetch error:&error]; |
2883 | - return [results count] > 0; |
2884 | -} |
2885 | - |
2886 | -@end |
2887 | |
2888 | === removed file 'models/Playlist.h' |
2889 | --- models/Playlist.h 2011-06-18 02:04:11 +0000 |
2890 | +++ models/Playlist.h 1970-01-01 00:00:00 +0000 |
2891 | @@ -1,47 +0,0 @@ |
2892 | -// |
2893 | -// Playlist.h |
2894 | -// iSub |
2895 | -// |
2896 | -// Created by Aaron Brethorst on 8/26/10. |
2897 | -// Copyright 2010 Canonical Ltd. |
2898 | -// |
2899 | -// This program is free software: you can redistribute it and/or modify it |
2900 | -// under the terms of the GNU Affero General Public License version 3, |
2901 | -// as published by the Free Software Foundation. |
2902 | -// |
2903 | -// This program is distributed in the hope that it will be useful, but |
2904 | -// WITHOUT ANY WARRANTY; without even the implied warranties of |
2905 | -// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2906 | -// PURPOSE. See the GNU Affero General Public License for more details. |
2907 | -// |
2908 | -// You should have received a copy of the GNU Affero General Public License |
2909 | -// along with this program. If not, see <http://www.gnu.org/licenses/>. |
2910 | - |
2911 | -#import <Foundation/Foundation.h> |
2912 | - |
2913 | -@class Song, PlaylistSongIndex; |
2914 | - |
2915 | -@interface Playlist : NSManagedObject |
2916 | -{ |
2917 | -} |
2918 | -@property(nonatomic,retain) NSString *name; |
2919 | -@property(nonatomic,retain) NSString *playlistId; |
2920 | -@property(nonatomic,retain) NSSet *playlistSongIndexes; |
2921 | -@property(nonatomic,readonly) NSArray *songs; |
2922 | - |
2923 | -+ (BOOL)playlistWithNameExists:(NSString*)aPlaylistName; |
2924 | -+ (Playlist*)playlistWithName:(NSString*)aPlaylistName; |
2925 | -- (BOOL)matchesSearchQuery:(NSString *)query; |
2926 | -- (NSError*)loadSongs; |
2927 | -- (BOOL)isEditable; |
2928 | -- (void)addSong:(Song *)song; |
2929 | -- (void)removeSong:(Song *)song; |
2930 | -@end |
2931 | - |
2932 | -// coalesce these into one @interface Album (CoreDataGeneratedAccessors) section |
2933 | -@interface Playlist (CoreDataGeneratedAccessors) |
2934 | -- (void)addPlaylistSongIndexesObject:(PlaylistSongIndex *)value; |
2935 | -- (void)removePlaylistSongIndexesObject:(PlaylistSongIndex *)value; |
2936 | -- (void)addPlaylistSongIndexes:(NSSet *)value; |
2937 | -- (void)removePlaylistSongIndexes:(NSSet *)value; |
2938 | -@end |
2939 | |
2940 | === removed file 'models/Playlist.m' |
2941 | --- models/Playlist.m 2011-11-05 00:42:21 +0000 |
2942 | +++ models/Playlist.m 1970-01-01 00:00:00 +0000 |
2943 | @@ -1,136 +0,0 @@ |
2944 | -// |
2945 | -// Playlist.m |
2946 | -// iSub |
2947 | -// |
2948 | -// Created by Aaron Brethorst on 8/26/10. |
2949 | -// Copyright 2010 Canonical Ltd. |
2950 | -// |
2951 | -// This program is free software: you can redistribute it and/or modify it |
2952 | -// under the terms of the GNU Affero General Public License version 3, |
2953 | -// as published by the Free Software Foundation. |
2954 | -// |
2955 | -// This program is distributed in the hope that it will be useful, but |
2956 | -// WITHOUT ANY WARRANTY; without even the implied warranties of |
2957 | -// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2958 | -// PURPOSE. See the GNU Affero General Public License for more details. |
2959 | -// |
2960 | -// You should have received a copy of the GNU Affero General Public License |
2961 | -// along with this program. If not, see <http://www.gnu.org/licenses/>. |
2962 | - |
2963 | -#import "Playlist.h" |
2964 | -#import "Subsonic.h" |
2965 | -#import "NSMutableArray+Extras.h" |
2966 | -#import "PlaylistParser.h" |
2967 | -#import "PlaylistSongIndex.h" |
2968 | -#import "Song.h" |
2969 | - |
2970 | -@implementation Playlist |
2971 | - |
2972 | -@dynamic playlistId, name, playlistSongIndexes; |
2973 | - |
2974 | -+ (BOOL)playlistWithNameExists:(NSString *)aPlaylistName |
2975 | -{ |
2976 | - return (nil != [Playlist playlistWithName:aPlaylistName]); |
2977 | -} |
2978 | - |
2979 | -+ (Playlist *)playlistWithName:(NSString *)aPlaylistName |
2980 | -{ |
2981 | - NSFetchRequest * fetch = [[NSFetchRequest alloc] init]; |
2982 | - NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Playlist" inManagedObjectContext:PerThreadManagedObjectContext()]; |
2983 | - [fetch setEntity:entityDescription]; |
2984 | - |
2985 | - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == %@", aPlaylistName]; |
2986 | - [fetch setPredicate:predicate]; |
2987 | - |
2988 | - NSError * error = nil; |
2989 | - NSArray * matches = [PerThreadManagedObjectContext() executeFetchRequest:fetch error:&error]; |
2990 | - [fetch release]; |
2991 | - |
2992 | - if ([matches count] > 0) |
2993 | - { |
2994 | - return [matches objectAtIndex:0]; |
2995 | - } |
2996 | - else |
2997 | - { |
2998 | - return nil; |
2999 | - } |
3000 | -} |
3001 | - |
3002 | -- (NSError*)loadSongs |
3003 | -{ |
3004 | - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
3005 | - NSError *error = nil; |
3006 | - |
3007 | - NSMutableArray *parameters = [NSMutableArray array]; |
3008 | - [parameters addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"id", self.playlistId, nil]]; |
3009 | - NSURL *url = [[Subsonic sharedSubsonic] getMetadataURL:@"getPlaylist.view" parameters:parameters]; |
3010 | - NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url]; |
3011 | - |
3012 | - PlaylistParser *parser = [[PlaylistParser alloc] init]; |
3013 | - parser.playlistObjectId = [self objectID]; |
3014 | - |
3015 | - [xmlParser setDelegate:parser]; |
3016 | - |
3017 | - if (![xmlParser parse]) |
3018 | - { |
3019 | - error = [[xmlParser parserError] copy]; |
3020 | - } |
3021 | - |
3022 | - [xmlParser release]; |
3023 | - [parser release]; |
3024 | - [pool release]; |
3025 | - |
3026 | - return [error autorelease]; |
3027 | -} |
3028 | - |
3029 | -- (NSArray *)songs |
3030 | -{ |
3031 | - // return playlistSongIndexes sorted by index |
3032 | - NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"index" ascending:YES]; |
3033 | - NSArray *results = [[self.playlistSongIndexes sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]] valueForKey:@"songEntity"]; |
3034 | - return results; |
3035 | -} |
3036 | - |
3037 | -// Do the crazy PlaylistSongIndex lookup/clobber dance inside these methods |
3038 | -- (void)addSong:(Song *)song |
3039 | -{ |
3040 | - PlaylistSongIndex *playlistSongIndex = [NSEntityDescription insertNewObjectForEntityForName:@"PlaylistSongIndex" inManagedObjectContext:PerThreadManagedObjectContext()]; |
3041 | - playlistSongIndex.playlistEntity = self; |
3042 | - playlistSongIndex.songEntity = song; |
3043 | - playlistSongIndex.index = [NSNumber numberWithUnsignedInt:[self.playlistSongIndexes count]]; |
3044 | - SaveContext(); |
3045 | -} |
3046 | - |
3047 | -- (void)removeSong:(Song *)song |
3048 | -{ |
3049 | - // Look up (potentially) all records where playlistEntity is self, and songEntity is song, and blow them away |
3050 | - NSSet *condemned = [self.playlistSongIndexes filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"songEntity = %@", song]]; |
3051 | - for (PlaylistSongIndex *playlistSongIndex in condemned) |
3052 | - { |
3053 | - [PerThreadManagedObjectContext() deleteObject:playlistSongIndex]; |
3054 | - } |
3055 | - SaveContext(); |
3056 | - |
3057 | - [[self.playlistSongIndexes sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"index" ascending:YES]]] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { |
3058 | - ((PlaylistSongIndex *)obj).index = [NSNumber numberWithUnsignedInt:idx]; |
3059 | - }]; |
3060 | - SaveContext(); |
3061 | -} |
3062 | - |
3063 | -- (NSString*)description |
3064 | -{ |
3065 | - return [NSString stringWithFormat:@"%@ (%@) MOC %@", self.name, self.playlistId, [self managedObjectContext]]; |
3066 | -} |
3067 | - |
3068 | -- (BOOL)matchesSearchQuery:(NSString *)query |
3069 | -{ |
3070 | - NSRange titleResultsRange = [self.name rangeOfString:query options:NSCaseInsensitiveSearch]; |
3071 | - return titleResultsRange.length > 0; |
3072 | -} |
3073 | - |
3074 | -- (BOOL)isEditable; |
3075 | -{ |
3076 | - return YES; |
3077 | -} |
3078 | - |
3079 | -@end |
3080 | |
3081 | === removed file 'models/PlaylistSongIndex.h' |
3082 | --- models/PlaylistSongIndex.h 2011-06-21 15:27:36 +0000 |
3083 | +++ models/PlaylistSongIndex.h 1970-01-01 00:00:00 +0000 |
3084 | @@ -1,32 +0,0 @@ |
3085 | -// |
3086 | -// PlaylistSongIndex.h |
3087 | -// iSub |
3088 | -// |
3089 | -// Created by Zachery Bir on 6/17/11. |
3090 | -// Copyright 2011 Canonical Ltd. |
3091 | -// |
3092 | -// This program is free software: you can redistribute it and/or modify it |
3093 | -// under the terms of the GNU Affero General Public License version 3, |
3094 | -// as published by the Free Software Foundation. |
3095 | -// |
3096 | -// This program is distributed in the hope that it will be useful, but |
3097 | -// WITHOUT ANY WARRANTY; without even the implied warranties of |
3098 | -// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3099 | -// PURPOSE. See the GNU Affero General Public License for more details. |
3100 | -// |
3101 | -// You should have received a copy of the GNU Affero General Public License |
3102 | -// along with this program. If not, see <http://www.gnu.org/licenses/>. |
3103 | - |
3104 | -#import <Foundation/Foundation.h> |
3105 | - |
3106 | -@class Playlist, Song; |
3107 | - |
3108 | -@interface PlaylistSongIndex : NSManagedObject { |
3109 | -@private |
3110 | - |
3111 | -} |
3112 | -@property (nonatomic, retain) NSNumber *index; |
3113 | - |
3114 | -@property (nonatomic, retain) Playlist *playlistEntity; |
3115 | -@property (nonatomic, retain) Song *songEntity; |
3116 | -@end |
3117 | |
3118 | === removed file 'models/PlaylistSongIndex.m' |
3119 | --- models/PlaylistSongIndex.m 2011-06-21 15:27:36 +0000 |
3120 | +++ models/PlaylistSongIndex.m 1970-01-01 00:00:00 +0000 |
3121 | @@ -1,27 +0,0 @@ |
3122 | -// |
3123 | -// PlaylistSongIndex.m |
3124 | -// iSub |
3125 | -// |
3126 | -// Created by Zachery Bir on 6/17/11. |
3127 | -// Copyright 2011 Canonical Ltd. |
3128 | -// |
3129 | -// This program is free software: you can redistribute it and/or modify it |
3130 | -// under the terms of the GNU Affero General Public License version 3, |
3131 | -// as published by the Free Software Foundation. |
3132 | -// |
3133 | -// This program is distributed in the hope that it will be useful, but |
3134 | -// WITHOUT ANY WARRANTY; without even the implied warranties of |
3135 | -// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3136 | -// PURPOSE. See the GNU Affero General Public License for more details. |
3137 | -// |
3138 | -// You should have received a copy of the GNU Affero General Public License |
3139 | -// along with this program. If not, see <http://www.gnu.org/licenses/>. |
3140 | - |
3141 | -#import "PlaylistSongIndex.h" |
3142 | - |
3143 | - |
3144 | -@implementation PlaylistSongIndex |
3145 | - |
3146 | -@dynamic index, playlistEntity, songEntity; |
3147 | - |
3148 | -@end |
3149 | |
3150 | === removed file 'models/Song.h' |
3151 | --- models/Song.h 2011-06-21 15:29:37 +0000 |
3152 | +++ models/Song.h 1970-01-01 00:00:00 +0000 |
3153 | @@ -1,67 +0,0 @@ |
3154 | -// |
3155 | -// Song.h |
3156 | -// iSub |
3157 | -// |
3158 | -// Created by Ben Baron on 2/28/10. |
3159 | -// Copyright 2010 Ben Baron. All rights reserved. |
3160 | -// |
3161 | -// Redistribution and use in source and binary forms, with or without modification, |
3162 | -// are permitted provided that the following conditions are met: |
3163 | -// |
3164 | -// * Redistributions of source code must retain the above copyright notice, this |
3165 | -// list of conditions and the following disclaimer. |
3166 | -// * Redistributions in binary form must reproduce the above copyright notice, |
3167 | -// this list of conditions and the following disclaimer in the documentation |
3168 | -// and/or other materials provided with the distribution. |
3169 | -// * Neither the my name nor the names of my contributors may be used to endorse |
3170 | -// or promote products derived from this software without specific prior written |
3171 | -// permission. |
3172 | -// |
3173 | -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY |
3174 | -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
3175 | -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
3176 | -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
3177 | -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
3178 | -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
3179 | -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
3180 | -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
3181 | -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
3182 | -// DAMAGE. |
3183 | - |
3184 | -@class Artist, Album, PlaylistSongIndex; |
3185 | - |
3186 | -@interface Song : NSManagedObject |
3187 | -{ |
3188 | -} |
3189 | -@property (nonatomic, retain) NSString *title; |
3190 | -@property (nonatomic, retain) NSString *songId; |
3191 | -@property (nonatomic, retain) NSString *artist; |
3192 | -@property (nonatomic, retain) NSString *album; |
3193 | -@property (nonatomic, retain) NSString *genre; |
3194 | -@property (nonatomic, retain) NSString *coverArtId; |
3195 | -@property (nonatomic, retain) NSString *path; |
3196 | -@property (nonatomic, retain) NSNumber *duration; |
3197 | -@property (nonatomic, retain) NSNumber *bitRate; |
3198 | -@property (nonatomic, retain) NSNumber *track; |
3199 | -@property (nonatomic, retain) NSNumber *discNumber; |
3200 | -@property (nonatomic, retain) NSNumber *year; |
3201 | -@property (nonatomic, retain) NSNumber *size; |
3202 | -@property (nonatomic, retain) Artist *artistEntity; |
3203 | -@property (nonatomic, retain) Album *albumEntity; |
3204 | -@property (nonatomic, retain) NSSet *playlistSongIndexes; |
3205 | -@property (nonatomic, retain) NSString *cachedSongPath; |
3206 | - |
3207 | -+ (BOOL)songWithIdExists:(NSString*)aSongId; |
3208 | -+ (Song*)songWithId:(NSString*)aSongId; |
3209 | -- (BOOL)matchesSearchQuery:(NSString *)query; |
3210 | -- (NSString *)dearticlizedTitle; |
3211 | -- (BOOL)cachedSongExists; |
3212 | -- (NSURL*)cachedSongURL; |
3213 | -@end |
3214 | - |
3215 | -@interface Song (CoreDataGeneratedAccessors) |
3216 | -- (void)addPlaylistSongIndexesObject:(PlaylistSongIndex *)value; |
3217 | -- (void)removePlaylistSongIndexesObject:(PlaylistSongIndex *)value; |
3218 | -- (void)addPlaylistSongIndexes:(NSSet *)value; |
3219 | -- (void)removePlaylistSongIndexes:(NSSet *)value; |
3220 | -@end |
3221 | |
3222 | === removed file 'models/Song.m' |
3223 | --- models/Song.m 2011-06-21 17:04:19 +0000 |
3224 | +++ models/Song.m 1970-01-01 00:00:00 +0000 |
3225 | @@ -1,113 +0,0 @@ |
3226 | -// |
3227 | -// Song.m |
3228 | -// iSub |
3229 | -// |
3230 | -// Created by Ben Baron on 2/28/10. |
3231 | -// Copyright 2010 Ben Baron. All rights reserved. |
3232 | -// |
3233 | -// Redistribution and use in source and binary forms, with or without modification, |
3234 | -// are permitted provided that the following conditions are met: |
3235 | -// |
3236 | -// * Redistributions of source code must retain the above copyright notice, this |
3237 | -// list of conditions and the following disclaimer. |
3238 | -// * Redistributions in binary form must reproduce the above copyright notice, |
3239 | -// this list of conditions and the following disclaimer in the documentation |
3240 | -// and/or other materials provided with the distribution. |
3241 | -// * Neither the my name nor the names of my contributors may be used to endorse |
3242 | -// or promote products derived from this software without specific prior written |
3243 | -// permission. |
3244 | -// |
3245 | -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY |
3246 | -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
3247 | -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
3248 | -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
3249 | -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
3250 | -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
3251 | -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
3252 | -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
3253 | -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
3254 | -// DAMAGE. |
3255 | - |
3256 | -#import "Song.h" |
3257 | -#import "Artist.h" |
3258 | -#import "Album.h" |
3259 | -#import "NSString+Extras.h" |
3260 | - |
3261 | -@implementation Song |
3262 | -@dynamic title, songId, artist, album, genre, coverArtId, path, duration, bitRate, track, discNumber, year, size; |
3263 | -@dynamic artistEntity, albumEntity, playlistSongIndexes, cachedSongPath; |
3264 | - |
3265 | -+ (BOOL)songWithIdExists:(NSString*)aSongId |
3266 | -{ |
3267 | - return (nil != [Song songWithId:aSongId]); |
3268 | -} |
3269 | - |
3270 | -+ (Song*)songWithId:(NSString*)aSongId |
3271 | -{ |
3272 | - NSFetchRequest * fetch = [[NSFetchRequest alloc] init]; |
3273 | - NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Song" inManagedObjectContext:PerThreadManagedObjectContext()]; |
3274 | - [fetch setEntity:entityDescription]; |
3275 | - |
3276 | - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"songId == %@", aSongId]; |
3277 | - [fetch setPredicate:predicate]; |
3278 | - |
3279 | - NSError * error = nil; |
3280 | - NSArray * matches = [PerThreadManagedObjectContext() executeFetchRequest:fetch error:&error]; |
3281 | - [fetch release]; |
3282 | - |
3283 | - if ([matches count] > 0) |
3284 | - { |
3285 | - return [matches objectAtIndex:0]; |
3286 | - } |
3287 | - else |
3288 | - { |
3289 | - return nil; |
3290 | - } |
3291 | -} |
3292 | - |
3293 | -- (NSURL*)cachedSongURL |
3294 | -{ |
3295 | - return [CachedMusicDirectory() URLByAppendingPathComponent:self.songId]; |
3296 | -} |
3297 | - |
3298 | -- (BOOL)cachedSongExists |
3299 | -{ |
3300 | - return self.cachedSongPath != nil; |
3301 | -} |
3302 | - |
3303 | -- (NSComparisonResult)compare:(Song*)s |
3304 | -{ |
3305 | - NSUInteger selfPathArray[] = {[self.discNumber integerValue], [self.track integerValue]}; |
3306 | - NSUInteger otherPathArray[] = {[s.discNumber integerValue], [s.track integerValue]}; |
3307 | - |
3308 | - NSIndexPath *selfPath = [NSIndexPath indexPathWithIndexes:selfPathArray length:2]; |
3309 | - NSIndexPath *otherPath = [NSIndexPath indexPathWithIndexes:otherPathArray length:2]; |
3310 | - |
3311 | - return [selfPath compare:otherPath]; |
3312 | -} |
3313 | - |
3314 | -- (NSString*)description |
3315 | -{ |
3316 | - NSArray *keys = [NSArray arrayWithObjects:@"title", @"songId", @"artist", @"album", @"genre", @"coverArtId", @"path", @"duration", @"bitRate", @"track", @"year", @"size", nil]; |
3317 | - |
3318 | - NSMutableString *desc = [NSMutableString string]; |
3319 | - |
3320 | - for (NSString *k in keys) |
3321 | - { |
3322 | - [desc appendFormat:@"%@:%@ :: ",k, [self valueForKey:k]]; |
3323 | - } |
3324 | - return desc; |
3325 | -} |
3326 | - |
3327 | -- (BOOL)matchesSearchQuery:(NSString *)query |
3328 | -{ |
3329 | - NSRange titleResultsRange = [self.title rangeOfString:query options:NSCaseInsensitiveSearch]; |
3330 | - return titleResultsRange.length > 0; |
3331 | -} |
3332 | - |
3333 | -- (NSString *)dearticlizedTitle |
3334 | -{ |
3335 | - return [self.title dearticlizedString]; |
3336 | -} |
3337 | - |
3338 | -@end |
3339 | |
3340 | === modified file 'music.xcdatamodeld/.xccurrentversion' |
3341 | --- music.xcdatamodeld/.xccurrentversion 2011-04-19 08:05:04 +0000 |
3342 | +++ music.xcdatamodeld/.xccurrentversion 2012-02-03 20:23:18 +0000 |
3343 | @@ -3,6 +3,6 @@ |
3344 | <plist version="1.0"> |
3345 | <dict> |
3346 | <key>_XCCurrentVersionName</key> |
3347 | - <string>music.xcdatamodel</string> |
3348 | + <string>U1Music 2.2-31.xcdatamodel</string> |
3349 | </dict> |
3350 | </plist> |
3351 | |
3352 | === added directory 'music.xcdatamodeld/U1Music 2.2-31.xcdatamodel' |
3353 | === added file 'music.xcdatamodeld/U1Music 2.2-31.xcdatamodel/elements' |
3354 | Binary files music.xcdatamodeld/U1Music 2.2-31.xcdatamodel/elements 1970-01-01 00:00:00 +0000 and music.xcdatamodeld/U1Music 2.2-31.xcdatamodel/elements 2012-02-03 20:23:18 +0000 differ |
3355 | === added file 'music.xcdatamodeld/U1Music 2.2-31.xcdatamodel/layout' |
3356 | Binary files music.xcdatamodeld/U1Music 2.2-31.xcdatamodel/layout 1970-01-01 00:00:00 +0000 and music.xcdatamodeld/U1Music 2.2-31.xcdatamodel/layout 2012-02-03 20:23:18 +0000 differ |
3357 | === modified file 'utilities/AlbumParser.m' |
3358 | --- utilities/AlbumParser.m 2011-06-21 15:29:37 +0000 |
3359 | +++ utilities/AlbumParser.m 2012-02-03 20:23:18 +0000 |
3360 | @@ -97,7 +97,7 @@ |
3361 | |
3362 | - (void)setAlbumObjectId:(NSManagedObjectID *)oid |
3363 | { |
3364 | - Album *anAlbum = [[PerThreadManagedObjectContext() objectWithID:oid] retain]; |
3365 | + Album *anAlbum = (Album *)[[PerThreadManagedObjectContext() objectWithID:oid] retain]; |
3366 | [album release]; |
3367 | album = anAlbum; |
3368 | } |
3369 | |
3370 | === modified file 'utilities/ArtistParser.m' |
3371 | --- utilities/ArtistParser.m 2011-05-27 18:23:44 +0000 |
3372 | +++ utilities/ArtistParser.m 2012-02-03 20:23:18 +0000 |
3373 | @@ -37,7 +37,7 @@ |
3374 | |
3375 | - (void)setArtistManagedObjectID:(NSManagedObjectID *)moid |
3376 | { |
3377 | - Artist *anArtist = [[PerThreadManagedObjectContext() objectWithID:moid] retain]; |
3378 | + Artist *anArtist = (Artist*)[[PerThreadManagedObjectContext() objectWithID:moid] retain]; |
3379 | [artist release]; |
3380 | artist = anArtist; |
3381 | } |
3382 | |
3383 | === modified file 'utilities/Globals.h' |
3384 | --- utilities/Globals.h 2011-06-21 15:29:37 +0000 |
3385 | +++ utilities/Globals.h 2012-02-03 20:23:18 +0000 |
3386 | @@ -21,6 +21,7 @@ |
3387 | |
3388 | NSURL* ApplicationDocumentsDirectory( void ); |
3389 | NSURL* DatabaseFile( void ); |
3390 | +NSURL* TemporaryDownloadsDirectory( void ); |
3391 | BOOL CacheContainsFile(NSString *aFilePath); |
3392 | NSURL* CachedMusicDirectory( void ); |
3393 | NSString* CachedMusicPathForFilename(NSString *aFileName); |
3394 | |
3395 | === modified file 'utilities/Globals.m' |
3396 | --- utilities/Globals.m 2011-06-21 15:29:37 +0000 |
3397 | +++ utilities/Globals.m 2012-02-03 20:23:18 +0000 |
3398 | @@ -30,6 +30,12 @@ |
3399 | return [docs URLByAppendingPathComponent:@"music.sqlite"]; |
3400 | } |
3401 | |
3402 | +NSURL* TemporaryDownloadsDirectory( void ) |
3403 | +{ |
3404 | + NSURL* docs = ApplicationDocumentsDirectory(); |
3405 | + return [docs URLByAppendingPathComponent:@"tmp"]; |
3406 | +} |
3407 | + |
3408 | BOOL CacheContainsFile(NSString *aFilePath) |
3409 | { |
3410 | return [[NSFileManager defaultManager] fileExistsAtPath:aFilePath]; |
3411 | |
3412 | === modified file 'utilities/PlaylistParser.m' |
3413 | --- utilities/PlaylistParser.m 2011-06-18 02:04:11 +0000 |
3414 | +++ utilities/PlaylistParser.m 2012-02-03 20:23:18 +0000 |
3415 | @@ -100,7 +100,7 @@ |
3416 | |
3417 | - (void)setPlaylistObjectId:(NSManagedObjectID *)oid |
3418 | { |
3419 | - Playlist *aPlaylist = [[PerThreadManagedObjectContext() objectWithID:oid] retain]; |
3420 | + Playlist *aPlaylist = (Playlist *)[[PerThreadManagedObjectContext() objectWithID:oid] retain]; |
3421 | [playlist release]; |
3422 | playlist = aPlaylist; |
3423 | } |
3424 | |
3425 | === modified file 'utilities/operations/Downloader.m' |
3426 | --- utilities/operations/Downloader.m 2011-06-21 15:29:37 +0000 |
3427 | +++ utilities/operations/Downloader.m 2012-02-03 20:23:18 +0000 |
3428 | @@ -24,6 +24,8 @@ |
3429 | #import "Album.h" |
3430 | #import "Song.h" |
3431 | #import "Subsonic.h" |
3432 | +#import "U1ChunkDownloadOperation.h" |
3433 | +#import "U1SerializedDownloadOperation.h" |
3434 | |
3435 | static const NSUInteger kMaxConcurrentDownloads = 4; |
3436 | |
3437 | @@ -35,6 +37,7 @@ |
3438 | |
3439 | - (void)startAlbumEnqueueing:(Album*)anAlbum; |
3440 | - (void)completeAlbumEnqueueing:(Album*)anAlbum; |
3441 | +- (void)downloadFile:(NSURL*)url withName:(NSString*)fileName completionBlock:(void(^)(NSString *path))completionBlock chunked:(BOOL)inChunks; |
3442 | @end |
3443 | |
3444 | @implementation Downloader |
3445 | @@ -85,38 +88,126 @@ |
3446 | |
3447 | - (void)downloadFile:(NSURL*)url withName:(NSString*)fileName |
3448 | { |
3449 | - [self downloadFile:url withName:fileName completionBlock:NULL]; |
3450 | + [self downloadFile:url withName:fileName completionBlock:NULL chunked:NO]; |
3451 | +} |
3452 | + |
3453 | +- (void)downloadFile:(NSURL *)url withName:(NSString *)fileName completionBlock:(void (^)(NSString *))completionBlock; |
3454 | +{ |
3455 | + [self downloadFile:url withName:fileName completionBlock:completionBlock chunked:NO]; |
3456 | } |
3457 | |
3458 | - (void)downloadFile:(NSURL*)url withName:(NSString*)fileName completionBlock:(void(^)(NSString *path))completionBlock |
3459 | + chunked:(BOOL)inChunks; |
3460 | { |
3461 | @synchronized(self) |
3462 | { |
3463 | - if ([downloads containsObject:fileName]) |
3464 | - { |
3465 | - return; |
3466 | - } |
3467 | - |
3468 | - NSString *path = CachedMusicPathForFilename(fileName); |
3469 | - |
3470 | - if (CacheContainsFile(path)) |
3471 | - { |
3472 | - // Partially downloaded file, delete and try again |
3473 | - [[NSFileManager defaultManager] removeItemAtPath:path error:NULL]; |
3474 | - } |
3475 | - |
3476 | - [downloads addObject:fileName]; |
3477 | - // Disable idle timer sleep while downloading |
3478 | - [[UIApplication sharedApplication] setIdleTimerDisabled:YES]; |
3479 | - |
3480 | - DownloadOperation *download = [DownloadOperation downloadOperationWithURL:url |
3481 | - filePath:path]; |
3482 | - download.delegate = self; |
3483 | - [download setCompletionBlock:^(void) { |
3484 | - if (completionBlock) |
3485 | - completionBlock(path); |
3486 | - }]; |
3487 | - [queue addOperation:download]; |
3488 | + if (inChunks) |
3489 | + { |
3490 | + NSURL* tmpDir = [TemporaryDownloadsDirectory() URLByAppendingPathComponent:fileName]; |
3491 | + |
3492 | + if ([downloads containsObject:fileName] || [[NSFileManager defaultManager] fileExistsAtPath:[tmpDir path]]) |
3493 | + { |
3494 | + return; |
3495 | + } |
3496 | + |
3497 | + NSError *error = nil; |
3498 | + BOOL yup = [[NSFileManager defaultManager] createDirectoryAtURL:tmpDir withIntermediateDirectories:YES attributes:nil error:&error]; |
3499 | + |
3500 | + NSString *path = CachedMusicPathForFilename(fileName); |
3501 | + |
3502 | + [downloads addObject:fileName]; |
3503 | + // Disable idle timer sleep while downloading |
3504 | + [[UIApplication sharedApplication] setIdleTimerDisabled:YES]; |
3505 | + |
3506 | + U1SerializedDownloadOperation *serializer = [[U1SerializedDownloadOperation alloc] initWithPath:path andChunkDirectoryPath:[tmpDir path]]; |
3507 | + |
3508 | + [serializer setCompletionBlock:^(void) { |
3509 | + dispatch_async(dispatch_get_main_queue(), ^{ |
3510 | + [downloads removeObject:[path lastPathComponent]]; |
3511 | + if ([downloads count] == 0) |
3512 | + { |
3513 | + // If downloads is empty, go back to idle timing for sleep |
3514 | + [[UIApplication sharedApplication] setIdleTimerDisabled:NO]; |
3515 | + } |
3516 | + // Coarse-grained, blanket notification that any download has completed. |
3517 | + [[NSNotificationCenter defaultCenter] postNotificationName:NOTIF_downloadComplete object:nil]; |
3518 | + |
3519 | + if (completionBlock) |
3520 | + completionBlock(path); |
3521 | + }); |
3522 | + }]; |
3523 | + |
3524 | + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ |
3525 | + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; |
3526 | + [request setHTTPMethod:@"HEAD"]; |
3527 | + NSError *error = nil; |
3528 | + NSHTTPURLResponse *response = nil; |
3529 | + [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; |
3530 | + |
3531 | + NSString *contentLengthString = [[response allHeaderFields] objectForKey:@"Content-Length"]; |
3532 | + NSNumberFormatter *nf = [[NSNumberFormatter alloc] init]; |
3533 | + NSNumber *contentLength = [nf numberFromString:contentLengthString]; |
3534 | + |
3535 | + static NSUInteger minChunkSize = 100000; |
3536 | + static NSUInteger chunkSize = 500000; |
3537 | + NSUInteger remaining = [contentLength unsignedIntegerValue]; |
3538 | + NSUInteger offset = 0; |
3539 | + |
3540 | + NSMutableArray *chunkRanges = [NSMutableArray array]; |
3541 | + |
3542 | + while (remaining > 0) |
3543 | + { |
3544 | + // If remaining is between chunkSize and (chunkSize + minChunkSize), just make this chunkSize that much more. |
3545 | + if ((remaining - chunkSize) < minChunkSize) |
3546 | + { |
3547 | + chunkSize = remaining; |
3548 | + } |
3549 | + NSRange chunkRange = NSMakeRange(offset, MIN(remaining, chunkSize)); |
3550 | + [chunkRanges addObject:[NSValue valueWithRange:chunkRange]]; |
3551 | + offset += chunkRange.length; |
3552 | + remaining -= chunkRange.length; |
3553 | + } |
3554 | + |
3555 | + [chunkRanges enumerateObjectsUsingBlock:^(id rangeValue, NSUInteger idx, BOOL *stop) { |
3556 | + NSRange range = [rangeValue rangeValue]; |
3557 | + |
3558 | + NSString *path = [[tmpDir path] stringByAppendingPathComponent:[NSString stringWithFormat:@"%lu.chunk", idx]]; |
3559 | + |
3560 | + U1ChunkDownloadOperation *chunk = [[U1ChunkDownloadOperation alloc] initWithUrl:url path:path andRange:range]; |
3561 | + |
3562 | + [queue addOperation:chunk]; |
3563 | + [serializer addDependency:chunk]; |
3564 | + }]; |
3565 | + |
3566 | + [queue addOperation:serializer]; |
3567 | + }); |
3568 | + } |
3569 | + else |
3570 | + { |
3571 | + if ([downloads containsObject:fileName]) |
3572 | + { |
3573 | + return; |
3574 | + } |
3575 | + NSString *path = CachedMusicPathForFilename(fileName); |
3576 | + if (CacheContainsFile(path)) |
3577 | + { |
3578 | + // Partially downloaded file, delete and try again |
3579 | + [[NSFileManager defaultManager] removeItemAtPath:path error:NULL]; |
3580 | + } |
3581 | + |
3582 | + [downloads addObject:fileName]; |
3583 | + // Disable idle timer sleep while downloading |
3584 | + [[UIApplication sharedApplication] setIdleTimerDisabled:YES]; |
3585 | + |
3586 | + DownloadOperation *download = [DownloadOperation downloadOperationWithURL:url |
3587 | + filePath:path]; |
3588 | + download.delegate = self; |
3589 | + [download setCompletionBlock:^(void) { |
3590 | + if (completionBlock) |
3591 | + completionBlock(path); |
3592 | + }]; |
3593 | + [queue addOperation:download]; |
3594 | + } |
3595 | } |
3596 | } |
3597 | |
3598 | |
3599 | === added file 'utilities/operations/U1ChunkDownloadOperation.h' |
3600 | --- utilities/operations/U1ChunkDownloadOperation.h 1970-01-01 00:00:00 +0000 |
3601 | +++ utilities/operations/U1ChunkDownloadOperation.h 2012-02-03 20:23:18 +0000 |
3602 | @@ -0,0 +1,24 @@ |
3603 | +// |
3604 | +// Copyright 2012 Canonical Ltd. |
3605 | +// |
3606 | +// This program is free software: you can redistribute it and/or modify it |
3607 | +// under the terms of the GNU Affero General Public License version 3, |
3608 | +// as published by the Free Software Foundation. |
3609 | +// |
3610 | +// This program is distributed in the hope that it will be useful, but |
3611 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
3612 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3613 | +// PURPOSE. See the GNU Affero General Public License for more details. |
3614 | +// |
3615 | +// You should have received a copy of the GNU Affero General Public License |
3616 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
3617 | + |
3618 | +#import "AbstractNetworkOperation.h" |
3619 | + |
3620 | +@interface U1ChunkDownloadOperation : AbstractNetworkOperation |
3621 | +@property (retain, nonatomic) NSString *path; |
3622 | +@property (retain, nonatomic) NSFileHandle *fileHandle; |
3623 | +@property (assign) NSRange range; |
3624 | + |
3625 | +- (id)initWithUrl:(NSURL*)url path:(NSString*)path andRange:(NSRange)aRange; |
3626 | +@end |
3627 | |
3628 | === added file 'utilities/operations/U1ChunkDownloadOperation.m' |
3629 | --- utilities/operations/U1ChunkDownloadOperation.m 1970-01-01 00:00:00 +0000 |
3630 | +++ utilities/operations/U1ChunkDownloadOperation.m 2012-02-03 20:23:18 +0000 |
3631 | @@ -0,0 +1,68 @@ |
3632 | +// |
3633 | +// Copyright 2012 Canonical Ltd. |
3634 | +// |
3635 | +// This program is free software: you can redistribute it and/or modify it |
3636 | +// under the terms of the GNU Affero General Public License version 3, |
3637 | +// as published by the Free Software Foundation. |
3638 | +// |
3639 | +// This program is distributed in the hope that it will be useful, but |
3640 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
3641 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3642 | +// PURPOSE. See the GNU Affero General Public License for more details. |
3643 | +// |
3644 | +// You should have received a copy of the GNU Affero General Public License |
3645 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
3646 | + |
3647 | +#import "U1ChunkDownloadOperation.h" |
3648 | + |
3649 | +@implementation U1ChunkDownloadOperation |
3650 | + |
3651 | +@synthesize path, fileHandle, range; |
3652 | + |
3653 | +- (id)initWithUrl:(NSURL *)url path:(NSString *)aPath andRange:(NSRange)aRange; |
3654 | +{ |
3655 | + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; |
3656 | + NSString *requestRange = [NSString stringWithFormat:@"bytes=%lu-%lu", aRange.location, NSMaxRange(aRange) - 1]; |
3657 | + [request setValue:requestRange forHTTPHeaderField:@"Range"]; |
3658 | + |
3659 | + self = [super initWithRequest:request]; |
3660 | + if (self == nil) |
3661 | + { |
3662 | + return nil; |
3663 | + } |
3664 | + |
3665 | + self.range = aRange; |
3666 | + self.path = aPath; |
3667 | + [[NSFileManager defaultManager] createFileAtPath:self.path contents:[NSData data] attributes:nil]; |
3668 | + fileHandle = [[NSFileHandle fileHandleForWritingAtPath:self.path] retain]; |
3669 | + |
3670 | + return self; |
3671 | +} |
3672 | + |
3673 | +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response |
3674 | +{ |
3675 | + [super connection:connection didReceiveResponse:response]; |
3676 | +} |
3677 | + |
3678 | +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data |
3679 | +{ |
3680 | + [super connection:connection didReceiveData:data]; |
3681 | + |
3682 | + [fileHandle writeData:data]; |
3683 | +} |
3684 | + |
3685 | +- (void)connectionDidFinishLoading:(NSURLConnection *)connection |
3686 | +{ |
3687 | + [fileHandle closeFile]; |
3688 | + |
3689 | + [super connectionDidFinishLoading:connection]; |
3690 | +} |
3691 | + |
3692 | +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error |
3693 | +{ |
3694 | + [fileHandle closeFile]; |
3695 | + [[NSFileManager defaultManager] removeItemAtPath:self.path error:nil]; |
3696 | + |
3697 | + [super connection:connection didFailWithError:error]; |
3698 | +} |
3699 | +@end |
3700 | |
3701 | === added file 'utilities/operations/U1SerializedDownloadOperation.h' |
3702 | --- utilities/operations/U1SerializedDownloadOperation.h 1970-01-01 00:00:00 +0000 |
3703 | +++ utilities/operations/U1SerializedDownloadOperation.h 2012-02-03 20:23:18 +0000 |
3704 | @@ -0,0 +1,22 @@ |
3705 | +// |
3706 | +// Copyright 2012 Canonical Ltd. |
3707 | +// |
3708 | +// This program is free software: you can redistribute it and/or modify it |
3709 | +// under the terms of the GNU Affero General Public License version 3, |
3710 | +// as published by the Free Software Foundation. |
3711 | +// |
3712 | +// This program is distributed in the hope that it will be useful, but |
3713 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
3714 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3715 | +// PURPOSE. See the GNU Affero General Public License for more details. |
3716 | +// |
3717 | +// You should have received a copy of the GNU Affero General Public License |
3718 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
3719 | + |
3720 | +#import <Foundation/Foundation.h> |
3721 | + |
3722 | +@interface U1SerializedDownloadOperation : NSOperation |
3723 | +@property (retain, nonatomic) NSString *path; |
3724 | +@property (retain, nonatomic) NSString *chunkDirectoryPath; |
3725 | +- (id)initWithPath:(NSString*)aPath andChunkDirectoryPath:(NSString*)aChunkDirectoryPath; |
3726 | +@end |
3727 | |
3728 | === added file 'utilities/operations/U1SerializedDownloadOperation.m' |
3729 | --- utilities/operations/U1SerializedDownloadOperation.m 1970-01-01 00:00:00 +0000 |
3730 | +++ utilities/operations/U1SerializedDownloadOperation.m 2012-02-03 20:23:18 +0000 |
3731 | @@ -0,0 +1,57 @@ |
3732 | +// |
3733 | +// Copyright 2012 Canonical Ltd. |
3734 | +// |
3735 | +// This program is free software: you can redistribute it and/or modify it |
3736 | +// under the terms of the GNU Affero General Public License version 3, |
3737 | +// as published by the Free Software Foundation. |
3738 | +// |
3739 | +// This program is distributed in the hope that it will be useful, but |
3740 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
3741 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3742 | +// PURPOSE. See the GNU Affero General Public License for more details. |
3743 | +// |
3744 | +// You should have received a copy of the GNU Affero General Public License |
3745 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
3746 | + |
3747 | +#import "U1SerializedDownloadOperation.h" |
3748 | + |
3749 | +@implementation U1SerializedDownloadOperation |
3750 | + |
3751 | +@synthesize path, chunkDirectoryPath; |
3752 | + |
3753 | +- (id)initWithPath:(NSString *)aPath andChunkDirectoryPath:(NSString *)aChunkDirectoryPath; |
3754 | +{ |
3755 | + self = [super init]; |
3756 | + if (self == nil) |
3757 | + { |
3758 | + return nil; |
3759 | + } |
3760 | + |
3761 | + self.path = aPath; |
3762 | + self.chunkDirectoryPath = aChunkDirectoryPath; |
3763 | + |
3764 | + return self; |
3765 | +} |
3766 | + |
3767 | +- (void)main; |
3768 | +{ |
3769 | + [[NSFileManager defaultManager] createFileAtPath:self.path contents:[NSData data] attributes:nil]; |
3770 | + NSFileHandle *fileHandle = [[NSFileHandle fileHandleForWritingAtPath:self.path] retain]; |
3771 | + |
3772 | + NSError *error = nil; |
3773 | + NSArray *filenames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.chunkDirectoryPath error:&error]; |
3774 | + |
3775 | + filenames = [filenames sortedArrayUsingSelector:@selector(localizedStandardCompare:)]; |
3776 | + |
3777 | + [filenames enumerateObjectsUsingBlock:^(id filename, NSUInteger idx, BOOL *stop) { |
3778 | + NSString *filePath = [NSString pathWithComponents:[NSArray arrayWithObjects:self.chunkDirectoryPath, filename, nil]]; |
3779 | + NSData *fileData = [[NSFileManager defaultManager] contentsAtPath:filePath]; |
3780 | + [fileHandle writeData:fileData]; |
3781 | + }]; |
3782 | + |
3783 | + [fileHandle closeFile]; |
3784 | + |
3785 | + error = nil; |
3786 | + [[NSFileManager defaultManager] removeItemAtPath:self.chunkDirectoryPath error:&error]; |
3787 | +} |
3788 | +@end |
3789 | |
3790 | === modified file 'view_controllers/AlbumListViewController.m' |
3791 | --- view_controllers/AlbumListViewController.m 2011-06-16 19:12:54 +0000 |
3792 | +++ view_controllers/AlbumListViewController.m 2012-02-03 20:23:18 +0000 |
3793 | @@ -22,10 +22,12 @@ |
3794 | #import "AlbumArtistUITableViewCell.h" |
3795 | #import "Album.h" |
3796 | #import "AlbumViewController.h" |
3797 | +#import "Downloader.h" |
3798 | #import "NSString+Extras.h" |
3799 | |
3800 | @interface AlbumListViewController () |
3801 | - (void)configureCell:(AlbumArtistUITableViewCell*)cell forTableView:(UITableView*)tableView indexPath:(NSIndexPath*)indexPath; |
3802 | +- (void)downloadAlbum:(UILongPressGestureRecognizer*)sender; |
3803 | @end |
3804 | |
3805 | @implementation AlbumListViewController |
3806 | @@ -62,6 +64,30 @@ |
3807 | [loader release], loader = nil; |
3808 | } |
3809 | |
3810 | +- (void)downloadAlbum:(UILongPressGestureRecognizer *)sender; |
3811 | +{ |
3812 | + if ((sender.state == UIGestureRecognizerStateBegan) && canCache) |
3813 | + { |
3814 | + Album *album = ((AlbumArtistUITableViewCell *)sender.view).album; |
3815 | + dispatch_queue_t dispatch_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); |
3816 | + dispatch_async(dispatch_queue, ^{ |
3817 | + [album loadSongs]; |
3818 | + for (Song *song in [album songs]) |
3819 | + { |
3820 | + if (![song cachedSongExists]) |
3821 | + { |
3822 | + [[Downloader sharedDownloader] downloadFile:[[Subsonic sharedSubsonic] getStreamingURLForSongId:song.songId] withName:song.songId completionBlock:^(NSString *path) { |
3823 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
3824 | + song.cachedSongPath = path; |
3825 | + SaveContext(); |
3826 | + }); |
3827 | + }]; |
3828 | + } |
3829 | + } |
3830 | + }); |
3831 | + } |
3832 | +} |
3833 | + |
3834 | #pragma mark - Data Loading |
3835 | |
3836 | - (void)loadLocalData |
3837 | @@ -147,6 +173,7 @@ |
3838 | album = [self.tableData objectAtIndex:indexPath.row]; |
3839 | } |
3840 | } |
3841 | + cell.album = album; |
3842 | |
3843 | cell.albumNameLabel.text = album.title; |
3844 | cell.artistNameLabel.text = album.artist; |
3845 | @@ -170,6 +197,12 @@ |
3846 | cell.albumNameLabel.textColor = [UIColor lightGrayColor]; |
3847 | cell.accessoryType = UITableViewCellAccessoryNone; |
3848 | } |
3849 | + |
3850 | +// UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(downloadAlbum:)]; |
3851 | +// longPressGesture.minimumPressDuration = 1.0f; |
3852 | +// longPressGesture.numberOfTouchesRequired = 1; |
3853 | +// [cell addGestureRecognizer:longPressGesture]; |
3854 | +// [longPressGesture release]; |
3855 | } |
3856 | |
3857 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath |
3858 | |
3859 | === modified file 'view_controllers/AlbumViewController.m' |
3860 | --- view_controllers/AlbumViewController.m 2011-06-22 20:11:03 +0000 |
3861 | +++ view_controllers/AlbumViewController.m 2012-02-03 20:23:18 +0000 |
3862 | @@ -138,63 +138,6 @@ |
3863 | return cell; |
3864 | } |
3865 | |
3866 | -- (void)configureCell:(SongUITableViewCell*)cell forSongAtIndexPath:(NSIndexPath*)indexPath |
3867 | -{ |
3868 | - Song *song = [self.songs objectAtIndex:indexPath.row]; |
3869 | - |
3870 | - // explicitly re-set the default state of the button/spinner |
3871 | - [cell.cacheButton setImage:(canCache ? [UIImage imageNamed:@"uncached"] : [UIImage imageNamed:@"uncached-disabled"]) forState:UIControlStateNormal]; |
3872 | - [cell.spinner stopAnimating]; |
3873 | - |
3874 | - cell.cacheButton.tag = indexPath.row; |
3875 | - [cell.cacheButton addTarget:self action:@selector(toggleCacheForSong:) forControlEvents:UIControlEventTouchUpInside]; |
3876 | - |
3877 | - if ([[Downloader sharedDownloader] isDownloading:song.songId]) |
3878 | - { |
3879 | - [cell.spinner startAnimating]; |
3880 | - } |
3881 | - else if ([song cachedSongExists]) |
3882 | - { |
3883 | - [cell.cacheButton setImage:[UIImage imageNamed:@"cached"] forState:UIControlStateNormal]; |
3884 | - } |
3885 | - |
3886 | - cell.songNameLabel.text = song.title; |
3887 | - |
3888 | - cell.positionLabel.text = [NSString stringWithFormat:@"%@", [song.track intValue] > 0 ? [song.track stringValue] : @""]; |
3889 | - |
3890 | - if (song.duration && [song.duration intValue] > 0) |
3891 | - { |
3892 | - cell.durationLabel.text = [NSDate stringFromDuration:song.duration]; |
3893 | - } |
3894 | - else |
3895 | - { |
3896 | - cell.durationLabel.text = @""; |
3897 | - } |
3898 | - |
3899 | - if ([StreamingPlayer sharedStreamingPlayer].currentSong && [song.songId isEqual:[StreamingPlayer sharedStreamingPlayer].currentSong.songId]) |
3900 | - { |
3901 | - cell.nowPlaying.hidden = NO; |
3902 | - } |
3903 | - else |
3904 | - { |
3905 | - cell.nowPlaying.hidden = YES; |
3906 | - } |
3907 | - |
3908 | - cell.evenRow = (0 == indexPath.row % 2); |
3909 | - if (song.cachedSongPath == nil && !canStream) |
3910 | - { |
3911 | - cell.songNameLabel.textColor = [UIColor lightGrayColor]; |
3912 | - cell.positionLabel.textColor = [UIColor lightGrayColor]; |
3913 | - cell.durationLabel.textColor = [UIColor lightGrayColor]; |
3914 | - } |
3915 | - else |
3916 | - { |
3917 | - cell.songNameLabel.textColor = [UIColor blackColor]; |
3918 | - cell.positionLabel.textColor = [UIColor blackColor]; |
3919 | - cell.durationLabel.textColor = [UIColor blackColor]; |
3920 | - } |
3921 | -} |
3922 | - |
3923 | |
3924 | #pragma mark - |
3925 | #pragma mark Table view delegate |
3926 | @@ -268,6 +211,63 @@ |
3927 | |
3928 | @implementation AlbumViewController (Private) |
3929 | |
3930 | +- (void)configureCell:(SongUITableViewCell*)cell forSongAtIndexPath:(NSIndexPath*)indexPath |
3931 | +{ |
3932 | + Song *song = [self.songs objectAtIndex:indexPath.row]; |
3933 | + |
3934 | + // explicitly re-set the default state of the button/spinner |
3935 | + [cell.cacheButton setImage:(canCache ? [UIImage imageNamed:@"uncached"] : [UIImage imageNamed:@"uncached-disabled"]) forState:UIControlStateNormal]; |
3936 | + [cell.spinner stopAnimating]; |
3937 | + |
3938 | + cell.cacheButton.tag = indexPath.row; |
3939 | + [cell.cacheButton addTarget:self action:@selector(toggleCacheForSong:) forControlEvents:UIControlEventTouchUpInside]; |
3940 | + |
3941 | + if ([[Downloader sharedDownloader] isDownloading:song.songId]) |
3942 | + { |
3943 | + [cell.spinner startAnimating]; |
3944 | + } |
3945 | + else if ([song cachedSongExists]) |
3946 | + { |
3947 | + [cell.cacheButton setImage:[UIImage imageNamed:@"cached"] forState:UIControlStateNormal]; |
3948 | + } |
3949 | + |
3950 | + cell.songNameLabel.text = song.title; |
3951 | + |
3952 | + cell.positionLabel.text = [NSString stringWithFormat:@"%@", [song.track intValue] > 0 ? [song.track stringValue] : @""]; |
3953 | + |
3954 | + if (song.duration && [song.duration intValue] > 0) |
3955 | + { |
3956 | + cell.durationLabel.text = [NSDate stringFromDuration:song.duration]; |
3957 | + } |
3958 | + else |
3959 | + { |
3960 | + cell.durationLabel.text = @""; |
3961 | + } |
3962 | + |
3963 | + if ([StreamingPlayer sharedStreamingPlayer].currentSong && [song.songId isEqual:[StreamingPlayer sharedStreamingPlayer].currentSong.songId]) |
3964 | + { |
3965 | + cell.nowPlaying.hidden = NO; |
3966 | + } |
3967 | + else |
3968 | + { |
3969 | + cell.nowPlaying.hidden = YES; |
3970 | + } |
3971 | + |
3972 | + cell.evenRow = (0 == indexPath.row % 2); |
3973 | + if (song.cachedSongPath == nil && !canStream) |
3974 | + { |
3975 | + cell.songNameLabel.textColor = [UIColor lightGrayColor]; |
3976 | + cell.positionLabel.textColor = [UIColor lightGrayColor]; |
3977 | + cell.durationLabel.textColor = [UIColor lightGrayColor]; |
3978 | + } |
3979 | + else |
3980 | + { |
3981 | + cell.songNameLabel.textColor = [UIColor blackColor]; |
3982 | + cell.positionLabel.textColor = [UIColor blackColor]; |
3983 | + cell.durationLabel.textColor = [UIColor blackColor]; |
3984 | + } |
3985 | +} |
3986 | + |
3987 | - (void)toggleCacheForSong:(id)sender |
3988 | { |
3989 | // This is a binary toggle, and right now, we don't bother trying to cancel a download in progress. |
3990 | @@ -320,8 +320,8 @@ |
3991 | [defaults setBool:YES forKey:@"acknowledged-no-cache-on-3g"]; |
3992 | }; |
3993 | |
3994 | - UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Caching Disabled", @"") |
3995 | - message:NSLocalizedString(@"Caching songs can only be done on WiFi networks.", @"") |
3996 | + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Downloading Disabled", @"") |
3997 | + message:NSLocalizedString(@"Downloading songs for offline use can only be done on WiFi networks.", @"") |
3998 | cancelButtonItem:cancelButton otherButtonItems:dismissButton, nil]; |
3999 | [alertView show]; |
4000 | [alertView release]; |
4001 | |
4002 | === modified file 'view_controllers/ArtistListViewController.m' |
4003 | --- view_controllers/ArtistListViewController.m 2011-06-16 19:12:54 +0000 |
4004 | +++ view_controllers/ArtistListViewController.m 2012-02-03 20:23:18 +0000 |
4005 | @@ -30,13 +30,17 @@ |
4006 | |
4007 | #import "ArtistListViewController.h" |
4008 | |
4009 | +#import "Album.h" |
4010 | +#import "ArtistUITableViewCell.h" |
4011 | #import "ArtistViewController.h" |
4012 | #import "Artist.h" |
4013 | #import "ArtistListParser.h" |
4014 | +#import "Downloader.h" |
4015 | #import "NSString+Extras.h" |
4016 | |
4017 | @interface ArtistListViewController () |
4018 | -- (void)configureCell:(UITableViewCell*)cell forTableView:(UITableView*)tableView indexPath:(NSIndexPath*)indexPath; |
4019 | +- (void)configureCell:(ArtistUITableViewCell*)cell forTableView:(UITableView*)tableView indexPath:(NSIndexPath*)indexPath; |
4020 | +- (void)downloadArtist:(UILongPressGestureRecognizer*)sender; |
4021 | @end |
4022 | |
4023 | @implementation ArtistListViewController |
4024 | @@ -54,6 +58,36 @@ |
4025 | return nav; |
4026 | } |
4027 | |
4028 | +- (void)downloadArtist:(UILongPressGestureRecognizer *)sender; |
4029 | +{ |
4030 | + if ((sender.state == UIGestureRecognizerStateBegan) && canCache) |
4031 | + { |
4032 | + Artist *artist = ((ArtistUITableViewCell *)sender.view).artist; |
4033 | + dispatch_queue_t dispatch_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); |
4034 | + dispatch_async(dispatch_queue, ^{ |
4035 | + [artist loadAlbums]; |
4036 | + for (Album *album in [artist albums]) |
4037 | + { |
4038 | + dispatch_async(dispatch_get_main_queue(), ^{ |
4039 | + [album loadSongs]; |
4040 | + for (Song *song in [album songs]) |
4041 | + { |
4042 | + if (![song cachedSongExists]) |
4043 | + { |
4044 | + [[Downloader sharedDownloader] downloadFile:[[Subsonic sharedSubsonic] getStreamingURLForSongId:song.songId] withName:song.songId completionBlock:^(NSString *path) { |
4045 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
4046 | + song.cachedSongPath = path; |
4047 | + SaveContext(); |
4048 | + }); |
4049 | + }]; |
4050 | + } |
4051 | + } |
4052 | + }); |
4053 | + } |
4054 | + }); |
4055 | + } |
4056 | +} |
4057 | + |
4058 | #pragma mark - Data Loading |
4059 | |
4060 | - (void)loadLocalData |
4061 | @@ -94,7 +128,7 @@ |
4062 | { |
4063 | [super updateReachability:reachability]; |
4064 | |
4065 | - for (UITableViewCell *cell in [self.tableView visibleCells]) |
4066 | + for (ArtistUITableViewCell *cell in [self.tableView visibleCells]) |
4067 | { |
4068 | [self configureCell:cell forTableView:self.tableView indexPath:[self.tableView indexPathForCell:cell]]; |
4069 | } |
4070 | @@ -106,16 +140,16 @@ |
4071 | { |
4072 | static NSString *CellIdentifier = @"Cell"; |
4073 | |
4074 | - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; |
4075 | + ArtistUITableViewCell *cell = (ArtistUITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; |
4076 | if (nil == cell) |
4077 | { |
4078 | - cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; |
4079 | + cell = [[[ArtistUITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; |
4080 | } |
4081 | [self configureCell:cell forTableView:tableView indexPath:indexPath]; |
4082 | return cell; |
4083 | } |
4084 | |
4085 | -- (void)configureCell:(UITableViewCell*)cell forTableView:(UITableView*)tableView indexPath:(NSIndexPath*)indexPath |
4086 | +- (void)configureCell:(ArtistUITableViewCell*)cell forTableView:(UITableView*)tableView indexPath:(NSIndexPath*)indexPath |
4087 | { |
4088 | Artist *artist = nil; |
4089 | if (self.searchDisplayController.searchResultsTableView == tableView) |
4090 | @@ -137,6 +171,7 @@ |
4091 | cell.accessoryType = (canStream || [artist hasCachedSongs]) ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone; |
4092 | } |
4093 | } |
4094 | + cell.artist = artist; |
4095 | |
4096 | cell.textLabel.text = artist.name; |
4097 | if (canStream || [artist hasCachedSongs]) |
4098 | @@ -147,6 +182,12 @@ |
4099 | { |
4100 | cell.textLabel.textColor = [UIColor lightGrayColor]; |
4101 | } |
4102 | + |
4103 | +// UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(downloadArtist:)]; |
4104 | +// longPressGesture.minimumPressDuration = 1.0f; |
4105 | +// longPressGesture.numberOfTouchesRequired = 1; |
4106 | +// [cell addGestureRecognizer:longPressGesture]; |
4107 | +// [longPressGesture release]; |
4108 | } |
4109 | |
4110 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath |
4111 | |
4112 | === modified file 'view_controllers/ArtistViewController.m' |
4113 | --- view_controllers/ArtistViewController.m 2011-06-21 17:04:19 +0000 |
4114 | +++ view_controllers/ArtistViewController.m 2012-02-03 20:23:18 +0000 |
4115 | @@ -33,11 +33,13 @@ |
4116 | #import "AlbumUITableViewCell.h" |
4117 | #import "Artist.h" |
4118 | #import "Album.h" |
4119 | +#import "Downloader.h" |
4120 | #import "Song.h" |
4121 | |
4122 | |
4123 | @interface ArtistViewController () |
4124 | - (void)configureCell:(UITableViewCell*)cell forAlbumAtIndexPath:(NSIndexPath*)indexPath; |
4125 | +- (void)downloadAlbum:(UILongPressGestureRecognizer*)sender; |
4126 | @end |
4127 | |
4128 | |
4129 | @@ -60,7 +62,7 @@ |
4130 | [super viewDidLoad]; |
4131 | self.tableView.rowHeight = 60.0f; |
4132 | self.title = self.artist.name; |
4133 | - |
4134 | + |
4135 | loader = [[AlbumArtLoader alloc] init]; |
4136 | loader.delegate = self; |
4137 | loader.imageSize = 120; |
4138 | @@ -100,6 +102,30 @@ |
4139 | [self.tableView reloadData]; |
4140 | } |
4141 | |
4142 | +- (void)downloadAlbum:(UILongPressGestureRecognizer *)sender; |
4143 | +{ |
4144 | + if ((sender.state == UIGestureRecognizerStateBegan) && canCache) |
4145 | + { |
4146 | + Album *album = ((AlbumUITableViewCell *)sender.view).album; |
4147 | + dispatch_queue_t dispatch_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); |
4148 | + dispatch_async(dispatch_queue, ^{ |
4149 | + [album loadSongs]; |
4150 | + for (Song *song in [album songs]) |
4151 | + { |
4152 | + if (![song cachedSongExists]) |
4153 | + { |
4154 | + [[Downloader sharedDownloader] downloadFile:[[Subsonic sharedSubsonic] getStreamingURLForSongId:song.songId] withName:song.songId completionBlock:^(NSString *path) { |
4155 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
4156 | + song.cachedSongPath = path; |
4157 | + SaveContext(); |
4158 | + }); |
4159 | + }]; |
4160 | + } |
4161 | + } |
4162 | + }); |
4163 | + } |
4164 | +} |
4165 | + |
4166 | - (void)beginLoadingRemoteData:(NSString*)force |
4167 | { |
4168 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
4169 | @@ -199,6 +225,7 @@ |
4170 | if (0 == indexPath.section) |
4171 | { |
4172 | Album *album = [self.albums objectAtIndex:indexPath.row]; |
4173 | + cell.album = album; |
4174 | cell.albumNameLabel.text = album.title; |
4175 | |
4176 | NSError *error = nil; |
4177 | @@ -226,6 +253,12 @@ |
4178 | Song *song = [self.songs objectAtIndex:indexPath.row]; |
4179 | cell.textLabel.text = song.title; |
4180 | } |
4181 | + |
4182 | + UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(downloadAlbum:)]; |
4183 | + longPressGesture.minimumPressDuration = 1.0f; |
4184 | + longPressGesture.numberOfTouchesRequired = 1; |
4185 | +// [cell addGestureRecognizer:longPressGesture]; |
4186 | + [longPressGesture release]; |
4187 | } |
4188 | |
4189 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath |
4190 | |
4191 | === modified file 'view_controllers/PlaylistListViewController.m' |
4192 | --- view_controllers/PlaylistListViewController.m 2011-06-21 17:04:19 +0000 |
4193 | +++ view_controllers/PlaylistListViewController.m 2012-02-03 20:23:18 +0000 |
4194 | @@ -18,13 +18,20 @@ |
4195 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
4196 | |
4197 | #import "PlaylistListViewController.h" |
4198 | + |
4199 | +#import "Downloader.h" |
4200 | #import "PlaylistViewController.h" |
4201 | #import "PlaylistEditViewController.h" |
4202 | #import "PlaylistListParser.h" |
4203 | +#import "PlaylistUITableViewCell.h" |
4204 | #import "Playlist.h" |
4205 | #import "CachedSongsPlaylist.h" |
4206 | #import "AlertPrompt.h" |
4207 | |
4208 | +@interface PlaylistListViewController () |
4209 | +- (void)downloadPlaylist:(UILongPressGestureRecognizer*)sender; |
4210 | +@end |
4211 | + |
4212 | @implementation PlaylistListViewController |
4213 | |
4214 | + (UINavigationController *)navigableViewController |
4215 | @@ -61,6 +68,30 @@ |
4216 | return self; |
4217 | } |
4218 | |
4219 | +- (void)downloadPlaylist:(UILongPressGestureRecognizer *)sender; |
4220 | +{ |
4221 | + if ((sender.state == UIGestureRecognizerStateBegan) && canCache) |
4222 | + { |
4223 | + Playlist *playlist = ((PlaylistUITableViewCell *)sender.view).playlist; |
4224 | + dispatch_queue_t dispatch_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); |
4225 | + dispatch_async(dispatch_queue, ^{ |
4226 | + [playlist loadSongs]; |
4227 | + for (Song *song in [playlist songs]) |
4228 | + { |
4229 | + if (![song cachedSongExists]) |
4230 | + { |
4231 | + [[Downloader sharedDownloader] downloadFile:[[Subsonic sharedSubsonic] getStreamingURLForSongId:song.songId] withName:song.songId completionBlock:^(NSString *path) { |
4232 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
4233 | + song.cachedSongPath = path; |
4234 | + SaveContext(); |
4235 | + }); |
4236 | + }]; |
4237 | + } |
4238 | + } |
4239 | + }); |
4240 | + } |
4241 | +} |
4242 | + |
4243 | #pragma mark - Data Loading |
4244 | |
4245 | - (void)loadLocalData |
4246 | @@ -93,10 +124,10 @@ |
4247 | { |
4248 | static NSString *CellIdentifier = @"Cell"; |
4249 | |
4250 | - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; |
4251 | + PlaylistUITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; |
4252 | if (nil == cell) |
4253 | { |
4254 | - cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; |
4255 | + cell = [[[PlaylistUITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; |
4256 | } |
4257 | |
4258 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; |
4259 | @@ -111,7 +142,17 @@ |
4260 | p = [self.tableData objectAtIndex:indexPath.row]; |
4261 | } |
4262 | |
4263 | + cell.playlist = p; |
4264 | cell.textLabel.text = p.name; |
4265 | + |
4266 | +// if (p.playlistId != nil) |
4267 | +// { |
4268 | +// UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(downloadPlaylist:)]; |
4269 | +// longPressGesture.minimumPressDuration = 1.0f; |
4270 | +// longPressGesture.numberOfTouchesRequired = 1; |
4271 | +// [cell addGestureRecognizer:longPressGesture]; |
4272 | +// [longPressGesture release]; |
4273 | +// } |
4274 | return cell; |
4275 | } |
4276 | |
4277 | |
4278 | === modified file 'view_controllers/PlaylistViewController.m' |
4279 | --- view_controllers/PlaylistViewController.m 2011-11-05 00:42:21 +0000 |
4280 | +++ view_controllers/PlaylistViewController.m 2012-02-03 20:23:18 +0000 |
4281 | @@ -86,7 +86,7 @@ |
4282 | [self.songs removeAllObjects]; |
4283 | if ([self.playlist isKindOfClass:[NSManagedObject class]]) |
4284 | [PerThreadManagedObjectContext() refreshObject:self.playlist mergeChanges:YES]; //force the playlist to reload its set of songs from the persistent store. |
4285 | - [self.songs addObjectsFromArray:self.playlist.songs]; |
4286 | + [self.songs addObjectsFromArray:[self.playlist songs]]; |
4287 | // this should sort based on something else (like the index on the playlist or something) |
4288 | // [self.songs sortUsingSelector:@selector(compare:)]; |
4289 | } |
4290 | |
4291 | === modified file 'xibs/MainWindow.xib' |
4292 | --- xibs/MainWindow.xib 2011-11-01 15:14:34 +0000 |
4293 | +++ xibs/MainWindow.xib 2012-02-03 20:23:18 +0000 |
4294 | @@ -47,7 +47,6 @@ |
4295 | <object class="NSPSMatrix" key="NSFrameMatrix"/> |
4296 | <string key="NSFrameSize">{320, 480}</string> |
4297 | <reference key="NSSuperview"/> |
4298 | - <reference key="NSNextKeyView"/> |
4299 | <object class="NSColor" key="IBUIBackgroundColor"> |
4300 | <int key="NSColorSpace">1</int> |
4301 | <bytes key="NSRGB">MSAxIDEAA</bytes> |
4302 | @@ -169,7 +168,6 @@ |
4303 | <int key="NSvFlags">266</int> |
4304 | <string key="NSFrame">{{0, 431}, {320, 49}}</string> |
4305 | <reference key="NSSuperview"/> |
4306 | - <reference key="NSNextKeyView"/> |
4307 | <object class="NSColor" key="IBUIBackgroundColor"> |
4308 | <int key="NSColorSpace">3</int> |
4309 | <bytes key="NSWhite">MCAwAA</bytes> |
In an effort to allow this branch to land, it includes the single request code path as well, and uses it by default.