Changeset 1025
- Timestamp:
- 10/21/07 22:02:51 (15 months ago)
- Location:
- trunk
- Files:
-
- 19 modified
-
Audio/AudioPlayer.m (modified) (2 diffs)
-
Audio/Metadata/Readers/AudioMetadataReader.h (modified) (2 diffs)
-
Audio/Metadata/Readers/AudioMetadataReader.m (modified) (1 diff)
-
Audio/Metadata/Writers/AudioMetadataWriter.h (modified) (1 diff)
-
Audio/Properties/AudioPropertiesReader.h (modified) (2 diffs)
-
Audio/Properties/AudioPropertiesReader.m (modified) (2 diffs)
-
Audio/Properties/FLACPropertiesReader.m (modified) (7 diffs)
-
Audio/ScheduledAudioRegion.h (modified) (3 diffs)
-
Audio/ScheduledAudioRegion.m (modified) (10 diffs)
-
AudioLibrary/AudioLibrary.m (modified) (4 diffs)
-
Database/AudioStream.h (modified) (3 diffs)
-
Database/AudioStream.m (modified) (6 diffs)
-
Database/AudioStreamManager.h (modified) (1 diff)
-
Database/AudioStreamManager.m (modified) (20 diffs)
-
Info.plist (modified) (1 diff)
-
SQL/create_stream_table.sql (modified) (3 diffs)
-
SQL/insert_stream.sql (modified) (5 diffs)
-
SQL/select_stream_by_url.sql (modified) (1 diff)
-
SQL/update_stream.sql (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Audio/AudioPlayer.m
r1014 r1025 300 300 } 301 301 302 // Determine the subrange of the stream to play, if any 303 NSNumber *streamStartingFrame = [stream valueForKey:StreamStartingFrameKey]; 304 NSNumber *streamFrameCount = [stream valueForKey:StreamFrameCountKey]; 305 ScheduledAudioRegion *region = nil; 306 307 // For reasons related to SQLite (see http://sqlite.org/nulls.html), -1 is used instead of NULL 308 if(-1 == [streamStartingFrame intValue] && -1 == [streamFrameCount intValue]) 309 region = [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder]; 310 else if(-1 == [streamFrameCount intValue]) 311 region = [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startingFrame:[streamStartingFrame longLongValue]]; 312 else 313 region = [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startingFrame:[streamStartingFrame longLongValue] frameCount:[streamFrameCount unsignedIntValue]]; 314 302 315 // Schedule the region for playback, and start scheduling audio slices 303 [[self scheduler] scheduleAudioRegion: [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder]];316 [[self scheduler] scheduleAudioRegion:region]; 304 317 [[self scheduler] startScheduling]; 305 318 … … 333 346 return NO; 334 347 335 // They match, so schedule the region for playback 336 [[self scheduler] scheduleAudioRegion:[ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder]]; 348 // Determine the subrange of the stream to play, if any 349 NSNumber *streamStartingFrame = [stream valueForKey:StreamStartingFrameKey]; 350 NSNumber *streamFrameCount = [stream valueForKey:StreamFrameCountKey]; 351 ScheduledAudioRegion *region = nil; 352 353 // For reasons related to SQLite (see http://sqlite.org/nulls.html), -1 is used instead of NULL 354 if(-1 == [streamStartingFrame intValue] && -1 == [streamFrameCount intValue]) 355 region = [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder]; 356 else if(-1 == [streamFrameCount intValue]) 357 region = [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startingFrame:[streamStartingFrame longLongValue]]; 358 else 359 region = [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startingFrame:[streamStartingFrame longLongValue] frameCount:[streamFrameCount unsignedIntValue]]; 360 361 // The formats and channel layouts match, so schedule the region for playback 362 [[self scheduler] scheduleAudioRegion:region]; 337 363 338 364 return YES; -
trunk/Audio/Metadata/Readers/AudioMetadataReader.h
r895 r1025 24 24 // Error Codes 25 25 // ======================================== 26 extern NSString * const AudioMetadataReaderErrorDomain;26 extern NSString * const AudioMetadataReaderErrorDomain; 27 27 28 28 enum { … … 41 41 - (BOOL) readMetadata:(NSError **)error; 42 42 43 - (NSDictionary *) metadata; 44 43 45 @end -
trunk/Audio/Metadata/Readers/AudioMetadataReader.m
r829 r1025 133 133 - (BOOL) readMetadata:(NSError **)error { return YES; } 134 134 135 - (NSDictionary *) metadata { return [[_metadata retain] autorelease]; } 136 135 137 @end -
trunk/Audio/Metadata/Writers/AudioMetadataWriter.h
r895 r1025 24 24 // Error Codes 25 25 // ======================================== 26 extern NSString * const AudioMetadataWriterErrorDomain;26 extern NSString * const AudioMetadataWriterErrorDomain; 27 27 28 28 enum { -
trunk/Audio/Properties/AudioPropertiesReader.h
r895 r1025 22 22 23 23 // ======================================== 24 // KVC key names 25 // ======================================== 26 extern NSString * const AudioPropertiesCueSheetKey; 27 extern NSString * const AudioPropertiesCueSheetTracksKey; 28 29 // ======================================== 24 30 // Error Codes 25 31 // ======================================== 26 extern NSString * const AudioPropertiesReaderErrorDomain;32 extern NSString * const AudioPropertiesReaderErrorDomain; 27 33 28 34 enum { … … 42 48 - (BOOL) readProperties:(NSError **)error; 43 49 50 - (NSDictionary *) properties; 51 - (NSDictionary *) cueSheet; 52 44 53 @end -
trunk/Audio/Properties/AudioPropertiesReader.m
r973 r1025 32 32 #import "UtilityFunctions.h" 33 33 34 NSString *const AudioPropertiesReaderErrorDomain = @"org.sbooth.Play.ErrorDomain.AudioPropertiesReader"; 34 NSString *const AudioPropertiesCueSheetKey = @"org.sbooth.Play.AudioPropertiesReader.CueSheet"; 35 NSString *const AudioPropertiesCueSheetTracksKey = @"org.sbooth.Play.AudioPropertiesReader.CueSheet.Tracks"; 36 NSString *const AudioPropertiesReaderErrorDomain = @"org.sbooth.Play.ErrorDomain.AudioPropertiesReader"; 35 37 36 38 @implementation AudioPropertiesReader … … 142 144 - (BOOL) readProperties:(NSError **)error { return YES; } 143 145 146 - (NSDictionary *) properties { return [[_properties retain] autorelease]; } 147 - (NSDictionary *) cueSheet { return [_properties valueForKey:AudioPropertiesCueSheetKey]; } 148 144 149 @end -
trunk/Audio/Properties/FLACPropertiesReader.m
r868 r1025 27 27 - (BOOL) readProperties:(NSError **)error 28 28 { 29 NSString *path = [_url path]; 30 FLAC__Metadata_Chain *chain = NULL; 31 FLAC__Metadata_Iterator *iterator = NULL; 32 FLAC__StreamMetadata *block = NULL; 33 NSMutableDictionary *propertiesDictionary; 29 NSString *path = [_url path]; 30 FLAC__Metadata_Chain *chain = NULL; 31 FLAC__Metadata_Iterator *iterator = NULL; 32 FLAC__StreamMetadata *block = NULL; 34 33 35 34 chain = FLAC__metadata_chain_new(); … … 37 36 38 37 if(NO == FLAC__metadata_chain_read(chain, [path fileSystemRepresentation])) { 39 40 38 if(nil != error) { 41 39 NSMutableDictionary *errorDictionary = [NSMutableDictionary dictionary]; … … 76 74 FLAC__metadata_iterator_init(iterator, chain); 77 75 76 unsigned i; 77 NSMutableDictionary *propertiesDictionary = [NSMutableDictionary dictionary]; 78 NSMutableDictionary *cueSheetDictionary = nil; 79 NSMutableArray *cueSheetTracks = nil; 80 78 81 do { 79 82 block = FLAC__metadata_iterator_get_block(iterator); … … 84 87 switch(block->type) { 85 88 case FLAC__METADATA_TYPE_STREAMINFO: 86 propertiesDictionary = [NSMutableDictionary dictionary];87 88 89 [propertiesDictionary setValue:NSLocalizedStringFromTable(@"FLAC", @"Formats", @"") forKey:PropertiesFileTypeKey]; 89 90 [propertiesDictionary setValue:NSLocalizedStringFromTable(@"FLAC", @"Formats", @"") forKey:PropertiesDataFormatKey]; … … 94 95 [propertiesDictionary setValue:[NSNumber numberWithUnsignedInt:block->data.stream_info.sample_rate] forKey:PropertiesSampleRateKey]; 95 96 [propertiesDictionary setValue:[NSNumber numberWithDouble:(double)block->data.stream_info.total_samples / block->data.stream_info.sample_rate] forKey:PropertiesDurationKey]; 96 97 [self setValue:propertiesDictionary forKey:@"properties"];98 97 break; 99 98 99 case FLAC__METADATA_TYPE_CUESHEET: 100 #if DEBUG 101 NSLog(@"FLAC cue sheet"); 102 NSLog(@" media_catalog_number : %s", block->data.cue_sheet.media_catalog_number); 103 NSLog(@" lead_in : %i", block->data.cue_sheet.lead_in); 104 NSLog(@" is_cd : %i", block->data.cue_sheet.is_cd); 105 NSLog(@" num_tracks : %i", block->data.cue_sheet.num_tracks); 106 #endif 107 108 cueSheetDictionary = [NSMutableDictionary dictionary]; 109 cueSheetTracks = [NSMutableArray array]; 110 111 [cueSheetDictionary setValue:[NSString stringWithUTF8String:block->data.cue_sheet.media_catalog_number] forKey:MetadataMCNKey]; 112 113 // Iterate through each track in the cue sheet and process each one 114 for(i = 0; i < block->data.cue_sheet.num_tracks; ++i) { 115 #if DEBUG 116 NSLog(@" Track %i", i); 117 NSLog(@" offset : %qi", block->data.cue_sheet.tracks[i].offset); 118 NSLog(@" number : %i", block->data.cue_sheet.tracks[i].number); 119 NSLog(@" isrc : %s", block->data.cue_sheet.tracks[i].isrc); 120 NSLog(@" type : %i", block->data.cue_sheet.tracks[i].type); 121 NSLog(@" pre_emphasis : %i", block->data.cue_sheet.tracks[i].pre_emphasis); 122 NSLog(@" num_indices : %i", block->data.cue_sheet.tracks[i].num_indices); 123 124 // Index points are unused for now 125 unsigned j; 126 for(j = 0; j < block->data.cue_sheet.tracks[i].num_indices; ++j) { 127 NSLog(@" Index %i", j); 128 NSLog(@" offset : %qi", block->data.cue_sheet.tracks[i].indices[j].offset); 129 NSLog(@" number : %i", block->data.cue_sheet.tracks[i].indices[j].number); 130 } 131 #endif 132 133 // Only process audio tracks 134 // 0 is audio, 1 is non-audio 135 if(0 == block->data.cue_sheet.tracks[i].type) { 136 NSMutableDictionary *trackDictionary = [NSMutableDictionary dictionary]; 137 138 [trackDictionary setValue:[NSString stringWithUTF8String:block->data.cue_sheet.tracks[i].isrc] forKey:MetadataISRCKey]; 139 [trackDictionary setValue:[NSNumber numberWithInt:block->data.cue_sheet.tracks[i].number] forKey:MetadataTrackNumberKey]; 140 [trackDictionary setValue:[NSNumber numberWithUnsignedLongLong:block->data.cue_sheet.tracks[i].offset] forKey:StreamStartingFrameKey]; 141 142 // Fill in frame counts and duration 143 if(0 < i) { 144 unsigned frameCount = (block->data.cue_sheet.tracks[i].offset - 1) - block->data.cue_sheet.tracks[i - 1].offset; 145 146 [[cueSheetTracks objectAtIndex:(i - 1)] setValue:[NSNumber numberWithUnsignedInt:frameCount] forKey:StreamFrameCountKey]; 147 [[cueSheetTracks objectAtIndex:(i - 1)] setValue:[NSNumber numberWithUnsignedInt:frameCount] forKey:PropertiesTotalFramesKey]; 148 [[cueSheetTracks objectAtIndex:(i - 1)] setValue:[NSNumber numberWithDouble:(double)frameCount / [[propertiesDictionary valueForKey:PropertiesSampleRateKey] floatValue]] forKey:PropertiesDurationKey]; 149 } 150 151 // Special handling for the last audio track 152 // FIXME: Is it safe the assume the lead out will always be the final track in the cue sheet? 153 if(i == block->data.cue_sheet.num_tracks - 1 - 1) { 154 unsigned frameCount = [[propertiesDictionary valueForKey:PropertiesTotalFramesKey] unsignedLongLongValue] - block->data.cue_sheet.tracks[i].offset + 1; 155 156 [trackDictionary setValue:[NSNumber numberWithUnsignedInt:frameCount] forKey:StreamFrameCountKey]; 157 [trackDictionary setValue:[NSNumber numberWithUnsignedInt:frameCount] forKey:PropertiesTotalFramesKey]; 158 [trackDictionary setValue:[NSNumber numberWithDouble:(double)frameCount / [[propertiesDictionary valueForKey:PropertiesSampleRateKey] floatValue]] forKey:PropertiesDurationKey]; 159 } 160 161 [cueSheetTracks addObject:trackDictionary]; 162 } 163 } 164 165 [cueSheetDictionary setValue:cueSheetTracks forKey:AudioPropertiesCueSheetTracksKey]; 166 [propertiesDictionary setValue:cueSheetDictionary forKey:AudioPropertiesCueSheetKey]; 167 break; 168 100 169 case FLAC__METADATA_TYPE_VORBIS_COMMENT: break; 101 170 case FLAC__METADATA_TYPE_PICTURE: break; … … 103 172 case FLAC__METADATA_TYPE_APPLICATION: break; 104 173 case FLAC__METADATA_TYPE_SEEKTABLE: break; 105 case FLAC__METADATA_TYPE_CUESHEET: break;106 174 case FLAC__METADATA_TYPE_UNDEFINED: break; 107 175 default: break; … … 112 180 FLAC__metadata_chain_delete(chain); 113 181 182 [self setValue:propertiesDictionary forKey:@"properties"]; 183 114 184 return YES; 115 185 } -
trunk/Audio/ScheduledAudioRegion.h
r913 r1025 33 33 AudioTimeStamp _startTime; 34 34 SInt64 _startingFrame; 35 UInt32 _frame sToPlay;35 UInt32 _frameCount; 36 36 unsigned _loopCount; 37 37 … … 59 59 60 60 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startingFrame:(SInt64)startingFrame; 61 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startingFrame:(SInt64)startingFrame frame sToPlay:(unsigned)framesToPlay;62 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startingFrame:(SInt64)startingFrame frame sToPlay:(unsigned)framesToPlayloopCount:(unsigned)loopCount;61 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startingFrame:(SInt64)startingFrame frameCount:(unsigned)frameCount; 62 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startingFrame:(SInt64)startingFrame frameCount:(unsigned)frameCount loopCount:(unsigned)loopCount; 63 63 64 64 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime; 65 65 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime startingFrame:(SInt64)startingFrame; 66 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime startingFrame:(SInt64)startingFrame frame sToPlay:(unsigned)framesToPlay;67 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime startingFrame:(SInt64)startingFrame frame sToPlay:(unsigned)framesToPlayloopCount:(unsigned)loopCount;66 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime startingFrame:(SInt64)startingFrame frameCount:(unsigned)frameCount; 67 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime startingFrame:(SInt64)startingFrame frameCount:(unsigned)frameCount loopCount:(unsigned)loopCount; 68 68 69 69 // ======================================== … … 79 79 - (void) setStartingFrame:(SInt64)startingFrame; 80 80 81 - (UInt32) frame sToPlay;82 - (void) setFrame sToPlay:(UInt32)fframesToPlay;81 - (UInt32) frameCount; 82 - (void) setFrameCount:(UInt32)frameCount; 83 83 84 84 - (unsigned) loopCount; -
trunk/Audio/ScheduledAudioRegion.m
r1016 r1025 137 137 startTime.mSampleTime = 0; 138 138 139 return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:0 frame sToPlay:[decoder totalFrames] loopCount:0];139 return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:0 frameCount:[decoder totalFrames] loopCount:0]; 140 140 } 141 141 … … 147 147 startTime.mSampleTime = 0; 148 148 149 return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:startingFrame frame sToPlay:([decoder totalFrames] - startingFrame) loopCount:0];150 } 151 152 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startingFrame:(SInt64)startingFrame frame sToPlay:(unsigned)framesToPlay149 return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:startingFrame frameCount:([decoder totalFrames] - startingFrame) loopCount:0]; 150 } 151 152 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startingFrame:(SInt64)startingFrame frameCount:(unsigned)frameCount 153 153 { 154 154 AudioTimeStamp startTime = { 0 }; … … 157 157 startTime.mSampleTime = 0; 158 158 159 return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:startingFrame frame sToPlay:framesToPlayloopCount:0];160 } 161 162 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startingFrame:(SInt64)startingFrame frame sToPlay:(unsigned)framesToPlayloopCount:(unsigned)loopCount159 return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:startingFrame frameCount:frameCount loopCount:0]; 160 } 161 162 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startingFrame:(SInt64)startingFrame frameCount:(unsigned)frameCount loopCount:(unsigned)loopCount 163 163 { 164 164 AudioTimeStamp startTime = { 0 }; … … 167 167 startTime.mSampleTime = 0; 168 168 169 return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:startingFrame frame sToPlay:framesToPlayloopCount:loopCount];169 return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:startingFrame frameCount:frameCount loopCount:loopCount]; 170 170 } 171 171 172 172 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime 173 173 { 174 return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:0 frame sToPlay:[decoder totalFrames] loopCount:0];174 return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:0 frameCount:[decoder totalFrames] loopCount:0]; 175 175 } 176 176 177 177 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime startingFrame:(SInt64)startingFrame 178 178 { 179 return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:startingFrame frame sToPlay:([decoder totalFrames] - startingFrame) loopCount:0];180 } 181 182 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime startingFrame:(SInt64)startingFrame frame sToPlay:(unsigned)framesToPlay183 { 184 return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:startingFrame frame sToPlay:framesToPlayloopCount:0];185 } 186 187 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime startingFrame:(SInt64)startingFrame frame sToPlay:(unsigned)framesToPlayloopCount:(unsigned)loopCount179 return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:startingFrame frameCount:([decoder totalFrames] - startingFrame) loopCount:0]; 180 } 181 182 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime startingFrame:(SInt64)startingFrame frameCount:(unsigned)frameCount 183 { 184 return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:startingFrame frameCount:frameCount loopCount:0]; 185 } 186 187 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime startingFrame:(SInt64)startingFrame frameCount:(unsigned)frameCount loopCount:(unsigned)loopCount 188 188 { 189 189 ScheduledAudioRegion *result = [[ScheduledAudioRegion alloc] init]; … … 192 192 [result setStartTime:startTime]; 193 193 [result setStartingFrame:startingFrame]; 194 [result setFrame sToPlay:framesToPlay];194 [result setFrameCount:frameCount]; 195 195 [result setLoopCount:loopCount]; 196 197 if(0 != [result startingFrame]) 198 [result reset]; 196 199 197 200 return [result autorelease]; … … 242 245 } 243 246 244 - (UInt32) frame sToPlay { return _framesToPlay; }245 246 - (void) setFrame sToPlay:(UInt32)framesToPlay247 { 248 NSParameterAssert(0 < frame sToPlay);249 250 _frame sToPlay = framesToPlay;247 - (UInt32) frameCount { return _frameCount; } 248 249 - (void) setFrameCount:(UInt32)frameCount 250 { 251 NSParameterAssert(0 < frameCount); 252 253 _frameCount = frameCount; 251 254 } 252 255 … … 255 258 - (unsigned) completedLoops { return _completedLoops; } 256 259 257 - (SInt64) totalFrames { return (([self loopCount] + 1) * [self frame sToPlay]); }260 - (SInt64) totalFrames { return (([self loopCount] + 1) * [self frameCount]); } 258 261 - (SInt64) currentFrame { return _totalFramesRead; } 259 262 - (SInt64) framesRemaining { return ([self totalFrames] - [self currentFrame]); } … … 265 268 NSParameterAssert(0 <= frame && frame < [self totalFrames]); 266 269 267 _completedLoops = frame / [self frame sToPlay];268 _framesReadInCurrentLoop = frame % [self frame sToPlay];270 _completedLoops = frame / [self frameCount]; 271 _framesReadInCurrentLoop = frame % [self frameCount]; 269 272 _totalFramesRead = frame; 270 273 _atEnd = NO; … … 344 347 return 0; 345 348 346 UInt32 framesRemaining = [self startingFrame] + [self frame sToPlay] - [[self decoder] currentFrame];349 UInt32 framesRemaining = [self startingFrame] + [self frameCount] - [[self decoder] currentFrame]; 347 350 UInt32 framesToRead = (frameCount < framesRemaining ? frameCount : framesRemaining); 348 351 UInt32 framesRead = 0; … … 354 357 _totalFramesRead += framesRead; 355 358 356 if([self frame sToPlay] == _framesReadInCurrentLoop || (0 == framesRead && 0 != framesToRead)) {359 if([self frameCount] == _framesReadInCurrentLoop || (0 == framesRead && 0 != framesToRead)) { 357 360 ++_completedLoops; 358 361 _framesReadInCurrentLoop = 0; -
trunk/AudioLibrary/AudioLibrary.m
r1014 r1025 193 193 194 194 - (void) addRandomTracksFromLibraryToPlayQueue:(unsigned)count; 195 196 - (BOOL) addStreamsFromExternalCueSheet:(NSString*)filename; 195 197 196 198 - (void) updatePlayQueueHistory; … … 805 807 NSError *error = nil; 806 808 807 // If the stream already exists in the library, do nothing 808 AudioStream *stream = [[[CollectionManager manager] streamManager] streamForURL:[NSURL fileURLWithPath:filename]]; 809 if(nil != stream) 810 return YES; 811 812 // First read the properties 809 if([[filename pathExtension] isEqualToString:@"cue"]) 810 return [self addStreamsFromExternalCueSheet:filename]; 811 812 // First read the properties to determine if the file contains a cuesheet 813 813 AudioPropertiesReader *propertiesReader = [AudioPropertiesReader propertiesReaderForURL:[NSURL fileURLWithPath:filename] error:&error]; 814 814 if(nil == propertiesReader) … … 819 819 return NO; 820 820 821 // Now read the metadata 822 AudioMetadataReader *metadataReader = [AudioMetadataReader metadataReaderForURL:[NSURL fileURLWithPath:filename] error:&error]; 823 if(nil == metadataReader) 824 return NO; 825 826 result = [metadataReader readMetadata:&error]; 827 if(NO == result) 828  
