Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Basic queueing is functional

  • Loading branch information...
commit d1197aa3fa7b71d6edda27f9b80acbe7a1582114 1 parent 78a89cc
Indragie Karunaratne authored August 29, 2012
2  Audio Players/SMKAVQueuePlayer.m
@@ -30,7 +30,7 @@ @implementation SMKAVQueuePlayer {
30 30
 - (id)init
31 31
 {
32 32
     if ((self = [super init])) {
33  
-        self.audioPlayer = [AVQueuePlayer queuePlayerWithItems:nil];
  33
+        self.audioPlayer = [AVQueuePlayer queuePlayerWithItems:[NSArray array]];
34 34
         __weak SMKAVQueuePlayer *weakSelf = self;
35 35
         _timeObserver = [self.audioPlayer addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(1.f, 1.f) queue:NULL usingBlock:^(CMTime time) {
36 36
             SMKAVQueuePlayer *strongSelf = weakSelf;
3  Audio Players/SMKMPMusicPlayer.m
@@ -8,6 +8,8 @@
8 8
 
9 9
 #import "SMKMPMusicPlayer.h"
10 10
 #import "SMKMPMediaTrack.h"
  11
+
  12
+#import "SMKErrorCodes.h"
11 13
 #import "NSError+SMKAdditions.h"
12 14
 
13 15
 @interface SMKMPMusicPlayer ()
@@ -29,6 +31,7 @@ - (id)init
29 31
         [self.audioPlayer beginGeneratingPlaybackNotifications];
30 32
         self.audioPlayer.repeatMode = MPMusicRepeatModeNone;
31 33
         self.audioPlayer.shuffleMode = MPMusicShuffleModeOff;
  34
+        self.seekTimeInterval = SMKPlayerDefaultSeekTimeInterval;
32 35
     }
33 36
     return self;
34 37
 }
6  Audio Players/SMKSpotifyPlayer.m
@@ -43,6 +43,9 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
43 43
             if (self.finishedTrackBlock)
44 44
                 self.finishedTrackBlock(self, self.oldCurrentTrack, nil);
45 45
             self.oldCurrentTrack = nil;
  46
+            if (self.preloadedTrack) {
  47
+                [self skipToPreloadedTrack];
  48
+            }
46 49
         } else {
47 50
             self.preloadedTrack = nil;
48 51
         }
@@ -124,7 +127,8 @@ - (void)preloadTrack:(id<SMKTrack>)track completionHandler:(void(^)(NSError *err
124 127
 
125 128
 - (void)skipToPreloadedTrack
126 129
 {
127  
-    [self playTrack:self.preloadedTrack completionHandler:nil];
  130
+    if (self.preloadedTrack) 
  131
+        [self playTrack:self.preloadedTrack completionHandler:nil];
128 132
 }
129 133
 
130 134
 #pragma mark - Accessors
1  Common Headers/SMKErrorCodes.h
@@ -9,7 +9,6 @@
9 9
 extern NSInteger const SMKPlayerErrorFailedToCreateInputSource;
10 10
 extern NSInteger const SMKPlayerErrorFailedToCreateDecoder;
11 11
 extern NSInteger const SMKPlayerErrorFailedToEnqueueTrack;
12  
-extern NSInteger const SMKPlayerErrorTrackAlreadyPreloaded;
13 12
 extern NSInteger const SMKPlayerErrorItemAlreadyExists;
14 13
 
15 14
 extern NSInteger const SMKCoreDataErrorDataStoreNotAFolder;
1  Common Headers/SMKErrorCodes.m
@@ -11,6 +11,7 @@
11 11
 NSInteger const SMKPlayerErrorFailedToCreateInputSource     = 0;
12 12
 NSInteger const SMKPlayerErrorFailedToCreateDecoder         = 1;
13 13
 NSInteger const SMKPlayerErrorItemAlreadyExists             = 2;
  14
+NSInteger const SMKPlayerErrorFailedToEnqueueTrack          = 3;
14 15
 
15 16
 NSInteger const SMKCoreDataErrorDataStoreNotAFolder         = 4;
16 17
 NSInteger const SMKCoreDataErrorFailedToInitializeStore     = 5;
4  Content Sources/MPMediaLibrary/Data Model/SMKMPMediaTrack.m
@@ -9,6 +9,8 @@
9 9
 #import "SMKMPMediaTrack.h"
10 10
 #import "SMKMPMediaAlbum.h"
11 11
 #import "SMKMPMediaHelpers.h"
  12
+#import "SMKAVQueuePlayer.h"
  13
+#import "SMKMPMusicPlayer.h"
12 14
 
13 15
 @interface SMKMPMediaAlbum (SMKInternal)
14 16
 - (id)initWithRepresentedObject:(MPMediaItem*)object contentSource:(id<SMKContentSource>)contentSource;
@@ -44,7 +46,7 @@ + (NSSet *)supportedSortKeys
44 46
 
45 47
 - (Class)playerClass
46 48
 {
47  
-    return NSClassFromString((self.playbackURL != nil) ? @"SMKAVQueuePlayer" : @"SMKMPMusicPlayer");
  49
+    return (self.playbackURL != nil) ? [SMKAVQueuePlayer class] : [SMKMPMusicPlayer class];
48 50
 }
49 51
 
50 52
 #pragma mark - SMKTrack
1  Example Apps/MPMediaLibraryExample/DetailViewController.h
@@ -13,4 +13,5 @@
13 13
 @property (strong, nonatomic) id detailItem;
14 14
 
15 15
 @property (weak, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
  16
+- (IBAction)seekForward:(id)sender;
16 17
 @end
18  Example Apps/MPMediaLibraryExample/DetailViewController.m
@@ -10,6 +10,7 @@
10 10
 #import "SNRMusicKitiOS.h"
11 11
 #import "SMKMPMediaContentSource.h"
12 12
 #import "SMKMPMusicPlayer.h"
  13
+#import "SMKQueueController.h"
13 14
 
14 15
 @interface DetailViewController ()
15 16
 @property (strong, nonatomic) UIPopoverController *masterPopoverController;
@@ -18,7 +19,7 @@ - (void)configureView;
18 19
 @end
19 20
 
20 21
 @implementation DetailViewController {
21  
-    SMKMPMusicPlayer *_player;
  22
+    SMKQueueController *_controller;
22 23
 }
23 24
 
24 25
 #pragma mark - Managing the detail item
@@ -42,7 +43,6 @@ - (void)configureView
42 43
         strongSelf.tracks = tracks;
43 44
         [self.tableView reloadData];
44 45
     }];
45  
-    _player = [SMKMPMusicPlayer new];
46 46
 }
47 47
 
48 48
 - (void)viewDidLoad
@@ -74,11 +74,10 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
74 74
 
75 75
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
76 76
 {
77  
-    SMKMPMediaTrack *object = self.tracks[indexPath.row];
78  
-    NSLog(@"%@", [object playbackURL]);
79  
-    [_player playTrack:object completionHandler:^(NSError *error) {
80  
-        NSLog(@"%@", error);
81  
-    }];
  77
+    NSArray *array = [self.tracks subarrayWithRange:NSMakeRange(indexPath.row, [self.tracks count] - indexPath.row)];
  78
+    NSLog(@"%@", array);
  79
+    _controller = [SMKQueueController queueControllerWithTracks:array];
  80
+    [_controller play:nil];
82 81
 }
83 82
 
84 83
 #pragma mark - Split view
@@ -97,4 +96,9 @@ - (void)splitViewController:(UISplitViewController *)splitController willShowVie
97 96
     self.masterPopoverController = nil;
98 97
 }
99 98
 
  99
+- (IBAction)seekForward:(id)sender
  100
+{
  101
+    [_controller seekForward:nil];
  102
+}
  103
+
100 104
 @end
9  Example Apps/MPMediaLibraryExample/en.lproj/MainStoryboard_iPad.storyboard
@@ -56,7 +56,13 @@
56 56
                             <outlet property="delegate" destination="k1S-Fw-fPT" id="NJm-jj-izg"/>
57 57
                         </connections>
58 58
                     </tableView>
59  
-                    <navigationItem key="navigationItem" title="Tracks" id="xYw-DX-WhN"/>
  59
+                    <navigationItem key="navigationItem" title="Tracks" id="xYw-DX-WhN">
  60
+                        <barButtonItem key="rightBarButtonItem" title="Seek Forward" id="df0-Kk-nhT">
  61
+                            <connections>
  62
+                                <action selector="seekForward:" destination="k1S-Fw-fPT" id="HfE-WB-NFW"/>
  63
+                            </connections>
  64
+                        </barButtonItem>
  65
+                    </navigationItem>
60 66
                     <connections>
61 67
                         <outlet property="view" destination="jqB-za-Asj" id="yMr-mm-BhV"/>
62 68
                     </connections>
@@ -143,6 +149,7 @@
143 149
         <class className="DetailViewController" superclassName="UITableViewController">
144 150
             <source key="sourceIdentifier" type="project" relativePath="./Classes/DetailViewController.h"/>
145 151
             <relationships>
  152
+                <relationship kind="action" name="seekForward:"/>
146 153
                 <relationship kind="outlet" name="detailDescriptionLabel" candidateClass="UILabel"/>
147 154
             </relationships>
148 155
         </class>
52  Master API/SMKQueueController.m
@@ -15,10 +15,10 @@ @interface SMKQueueItem : NSObject
15 15
 @interface SMKQueueController ()
16 16
 @property (nonatomic, strong) NSMutableArray *items;
17 17
 @property (nonatomic, strong, readwrite) id<SMKPlayer> currentPlayer;
  18
+@property (nonatomic, assign, readwrite) NSUInteger indexOfCurrentTrack;
18 19
 @end
19 20
 
20 21
 @implementation SMKQueueController
21  
-
22 22
 - (id)init
23 23
 {
24 24
     if ((self = [super init])) {
@@ -73,16 +73,6 @@ - (void)removeTrack:(id<SMKTrack>)track
73 73
 
74 74
 #pragma mark - Accessors
75 75
 
76  
-- (NSUInteger)indexOfCurrentTrack
77  
-{
78  
-    return [self.items indexOfObject:self.currentTrack];
79  
-}
80  
-
81  
-+ (NSSet *)keyPathsForValuesAffectingIndexOfCurrentTrack
82  
-{
83  
-    return [NSSet setWithObject:@"currentTrack"];
84  
-}
85  
-
86 76
 - (NSTimeInterval)playbackTime
87 77
 {
88 78
     return [self.currentPlayer playbackTime];
@@ -177,7 +167,15 @@ - (IBAction)playPause:(id)sender
177 167
 
178 168
 - (IBAction)next:(id)sender
179 169
 {
180  
-    
  170
+    if ([[self.currentPlayer class] supportsPreloading] && [self.currentPlayer preloadedTrack]) {
  171
+        [self.currentPlayer skipToPreloadedTrack];
  172
+        self.indexOfCurrentTrack++;
  173
+    } else {
  174
+        NSUInteger nextIndex = self.indexOfCurrentTrack + 1;
  175
+        if (nextIndex < [self countOfItems])
  176
+            [self _beginPlayingItemAtIndex:nextIndex];
  177
+    }
  178
+    [self _recalculateIndexOfCurrentTrack];
181 179
 }
182 180
 
183 181
 - (IBAction)previous:(id)sender
@@ -187,12 +185,12 @@ - (IBAction)previous:(id)sender
187 185
 
188 186
 - (IBAction)seekForward:(id)sender
189 187
 {
190  
-    
  188
+    [self.currentPlayer seekForward];
191 189
 }
192 190
 
193 191
 - (IBAction)seekBackward:(id)sender
194 192
 {
195  
-    
  193
+    [self.currentPlayer seekBackward];
196 194
 }
197 195
 
198 196
 #pragma mark - Private
@@ -223,17 +221,33 @@ - (NSUInteger)_indexOfTrack:(id<SMKTrack>)track
223 221
 - (void)_beginPlayingItemAtIndex:(NSUInteger)index
224 222
 {
225 223
     id<SMKTrack> track = [[self.items objectAtIndex:index] track];
226  
-    self.currentPlayer = [[track playerClass] new];
  224
+    id<SMKPlayer> player = [[track playerClass] new];
  225
+    NSLog(@"now playing %@ with %@", [track name], player);
  226
+    self.currentPlayer = player;
227 227
     __weak SMKQueueController *weakSelf = self;
228  
-    [self.currentPlayer playTrack:track completionHandler:^(NSError *error) {
  228
+    [player playTrack:track completionHandler:^(NSError *error) {
  229
+        SMKQueueController *strongSelf = weakSelf;
229 230
         if (error) {
230  
-            SMKQueueController *strongSelf = weakSelf;
231 231
             SMKGenericErrorLog([NSString stringWithFormat:@"Error playing track %@", track], error);
232 232
             [strongSelf removeObjectFromItemsAtIndex:index];
233 233
             strongSelf.currentPlayer = nil;
234  
-            if (index < [self.items count])
235  
-                [self _beginPlayingItemAtIndex:index];
  234
+            if (index < [strongSelf countOfItems])
  235
+                [strongSelf _beginPlayingItemAtIndex:index];
  236
+        } else {
  237
+            [strongSelf _recalculateIndexOfCurrentTrack];
236 238
         }
237 239
     }];
  240
+    [player setFinishedTrackBlock:^(id<SMKPlayer> player, id<SMKTrack> track, NSError *error) {
  241
+        SMKQueueController *strongSelf = weakSelf;
  242
+        [strongSelf next:nil];
  243
+    }];
238 244
 }
  245
+
  246
+- (void)_recalculateIndexOfCurrentTrack
  247
+{
  248
+    self.indexOfCurrentTrack = [self _indexOfTrack:self.currentTrack];
  249
+}
  250
+@end
  251
+
  252
+@implementation SMKQueueItem
239 253
 @end
4  SNRMusicKit.xcodeproj/project.pbxproj
@@ -118,6 +118,8 @@
118 118
 		036994CF15E3F3EB003BCCBE /* UIImageView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 036994A615E3F3EB003BCCBE /* UIImageView+AFNetworking.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
119 119
 		036994D015E3F461003BCCBE /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 036991F615E3EAE1003BCCBE /* CoreData.framework */; };
120 120
 		036994D215E3F475003BCCBE /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 036994D115E3F475003BCCBE /* CoreData.framework */; };
  121
+		036F857515EEC45100DF72B9 /* SMKQueueController.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0371CF9915EDECF200B304CC /* SMKQueueController.h */; };
  122
+		036F857615EEC54500DF72B9 /* SMKAVQueuePlayer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 03FBEC9D15E6E0C100A67DEE /* SMKAVQueuePlayer.h */; };
121 123
 		0370109C15E5535500FEAF6F /* SMKiTunesSyncOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0370109A15E5535500FEAF6F /* SMKiTunesSyncOperation.h */; };
122 124
 		0370109D15E5535500FEAF6F /* SMKiTunesSyncOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0370109B15E5535500FEAF6F /* SMKiTunesSyncOperation.m */; };
123 125
 		037010A015E5630000FEAF6F /* SMKiTunesConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 0370109E15E5630000FEAF6F /* SMKiTunesConstants.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -403,6 +405,8 @@
403 405
 				0306DB6B15EC199800D6409B /* SMKMPMediaTrack.h in CopyFiles */,
404 406
 				0371CF9515EDE47700B304CC /* SMKMPMediaAlbum.h in CopyFiles */,
405 407
 				0371CF9315EDE44C00B304CC /* SMKMPMusicPlayer.h in CopyFiles */,
  408
+				036F857515EEC45100DF72B9 /* SMKQueueController.h in CopyFiles */,
  409
+				036F857615EEC54500DF72B9 /* SMKAVQueuePlayer.h in CopyFiles */,
406 410
 			);
407 411
 			runOnlyForDeploymentPostprocessing = 0;
408 412
 		};
BIN  SNRMusicKit.xcodeproj/project.xcworkspace/xcuserdata/indragie.xcuserdatad/UserInterfaceState.xcuserstate
Binary file not shown

0 notes on commit d1197aa

Please sign in to comment.
Something went wrong with that request. Please try again.