Changeset 1025

Show
Ignore:
Timestamp:
10/21/07 22:02:51 (15 months ago)
Author:
stephen_booth
Message:

Initial FLAC cue sheet implementation

Location:
trunk
Files:
19 modified

Legend:

Unmodified
Added
Removed
  • trunk/Audio/AudioPlayer.m

    r1014 r1025  
    300300        } 
    301301         
     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 
    302315        // Schedule the region for playback, and start scheduling audio slices 
    303         [[self scheduler] scheduleAudioRegion:[ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder]]; 
     316        [[self scheduler] scheduleAudioRegion:region]; 
    304317        [[self scheduler] startScheduling]; 
    305318 
     
    333346                return NO; 
    334347         
    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]; 
    337363 
    338364        return YES; 
  • trunk/Audio/Metadata/Readers/AudioMetadataReader.h

    r895 r1025  
    2424// Error Codes 
    2525// ======================================== 
    26 extern NSString * const                 AudioMetadataReaderErrorDomain; 
     26extern NSString * const         AudioMetadataReaderErrorDomain; 
    2727 
    2828enum { 
     
    4141- (BOOL)                                                        readMetadata:(NSError **)error; 
    4242 
     43- (NSDictionary *)                                      metadata; 
     44 
    4345@end 
  • trunk/Audio/Metadata/Readers/AudioMetadataReader.m

    r829 r1025  
    133133- (BOOL)                        readMetadata:(NSError **)error                  { return YES; } 
    134134 
     135- (NSDictionary *)      metadata                                                                { return [[_metadata retain] autorelease]; } 
     136 
    135137@end 
  • trunk/Audio/Metadata/Writers/AudioMetadataWriter.h

    r895 r1025  
    2424// Error Codes 
    2525// ======================================== 
    26 extern NSString * const                 AudioMetadataWriterErrorDomain; 
     26extern NSString * const         AudioMetadataWriterErrorDomain; 
    2727 
    2828enum { 
  • trunk/Audio/Properties/AudioPropertiesReader.h

    r895 r1025  
    2222 
    2323// ======================================== 
     24// KVC key names 
     25// ======================================== 
     26extern NSString * const         AudioPropertiesCueSheetKey; 
     27extern NSString * const         AudioPropertiesCueSheetTracksKey; 
     28 
     29// ======================================== 
    2430// Error Codes 
    2531// ======================================== 
    26 extern NSString * const                 AudioPropertiesReaderErrorDomain; 
     32extern NSString * const         AudioPropertiesReaderErrorDomain; 
    2733 
    2834enum { 
     
    4248- (BOOL)                                                        readProperties:(NSError **)error; 
    4349 
     50- (NSDictionary *)                                      properties; 
     51- (NSDictionary *)                                      cueSheet; 
     52 
    4453@end 
  • trunk/Audio/Properties/AudioPropertiesReader.m

    r973 r1025  
    3232#import "UtilityFunctions.h" 
    3333 
    34 NSString *const AudioPropertiesReaderErrorDomain = @"org.sbooth.Play.ErrorDomain.AudioPropertiesReader"; 
     34NSString *const AudioPropertiesCueSheetKey                      = @"org.sbooth.Play.AudioPropertiesReader.CueSheet"; 
     35NSString *const AudioPropertiesCueSheetTracksKey        = @"org.sbooth.Play.AudioPropertiesReader.CueSheet.Tracks"; 
     36NSString *const AudioPropertiesReaderErrorDomain        = @"org.sbooth.Play.ErrorDomain.AudioPropertiesReader"; 
    3537 
    3638@implementation AudioPropertiesReader 
     
    142144- (BOOL)                        readProperties:(NSError **)error                { return YES; } 
    143145 
     146- (NSDictionary *)      properties                                                              { return [[_properties retain] autorelease]; } 
     147- (NSDictionary *)      cueSheet                                                                { return [_properties valueForKey:AudioPropertiesCueSheetKey]; } 
     148 
    144149@end 
  • trunk/Audio/Properties/FLACPropertiesReader.m

    r868 r1025  
    2727- (BOOL) readProperties:(NSError **)error 
    2828{ 
    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; 
    3433                                 
    3534        chain = FLAC__metadata_chain_new(); 
     
    3736         
    3837        if(NO == FLAC__metadata_chain_read(chain, [path fileSystemRepresentation])) { 
    39                  
    4038                if(nil != error) { 
    4139                        NSMutableDictionary *errorDictionary = [NSMutableDictionary dictionary]; 
     
    7674        FLAC__metadata_iterator_init(iterator, chain); 
    7775         
     76        unsigned i; 
     77        NSMutableDictionary             *propertiesDictionary   = [NSMutableDictionary dictionary]; 
     78        NSMutableDictionary             *cueSheetDictionary             = nil; 
     79        NSMutableArray                  *cueSheetTracks                 = nil; 
     80 
    7881        do { 
    7982                block = FLAC__metadata_iterator_get_block(iterator); 
     
    8487                switch(block->type) {                                    
    8588                        case FLAC__METADATA_TYPE_STREAMINFO: 
    86                                 propertiesDictionary = [NSMutableDictionary dictionary]; 
    87                                  
    8889                                [propertiesDictionary setValue:NSLocalizedStringFromTable(@"FLAC", @"Formats", @"") forKey:PropertiesFileTypeKey]; 
    8990                                [propertiesDictionary setValue:NSLocalizedStringFromTable(@"FLAC", @"Formats", @"") forKey:PropertiesDataFormatKey]; 
     
    9495                                [propertiesDictionary setValue:[NSNumber numberWithUnsignedInt:block->data.stream_info.sample_rate] forKey:PropertiesSampleRateKey];                             
    9596                                [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"]; 
    9897                                break; 
    9998                                 
     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 
    100169                        case FLAC__METADATA_TYPE_VORBIS_COMMENT:                                break; 
    101170                        case FLAC__METADATA_TYPE_PICTURE:                                               break; 
     
    103172                        case FLAC__METADATA_TYPE_APPLICATION:                                   break; 
    104173                        case FLAC__METADATA_TYPE_SEEKTABLE:                                             break; 
    105                         case FLAC__METADATA_TYPE_CUESHEET:                                              break; 
    106174                        case FLAC__METADATA_TYPE_UNDEFINED:                                             break; 
    107175                        default:                                                                                                break; 
     
    112180        FLAC__metadata_chain_delete(chain); 
    113181         
     182        [self setValue:propertiesDictionary forKey:@"properties"]; 
     183 
    114184        return YES; 
    115185} 
  • trunk/Audio/ScheduledAudioRegion.h

    r913 r1025  
    3333        AudioTimeStamp                  _startTime; 
    3434        SInt64                                  _startingFrame; 
    35         UInt32                                  _framesToPlay; 
     35        UInt32                                  _frameCount; 
    3636        unsigned                                _loopCount; 
    3737         
     
    5959 
    6060+ (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startingFrame:(SInt64)startingFrame; 
    61 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startingFrame:(SInt64)startingFrame framesToPlay:(unsigned)framesToPlay; 
    62 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startingFrame:(SInt64)startingFrame framesToPlay:(unsigned)framesToPlay loopCount:(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; 
    6363 
    6464+ (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime; 
    6565+ (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime startingFrame:(SInt64)startingFrame; 
    66 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime startingFrame:(SInt64)startingFrame framesToPlay:(unsigned)framesToPlay; 
    67 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime startingFrame:(SInt64)startingFrame framesToPlay:(unsigned)framesToPlay loopCount:(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; 
    6868 
    6969// ======================================== 
     
    7979- (void) setStartingFrame:(SInt64)startingFrame; 
    8080 
    81 - (UInt32) framesToPlay; 
    82 - (void) setFramesToPlay:(UInt32)fframesToPlay; 
     81- (UInt32) frameCount; 
     82- (void) setFrameCount:(UInt32)frameCount; 
    8383 
    8484- (unsigned) loopCount; 
  • trunk/Audio/ScheduledAudioRegion.m

    r1016 r1025  
    137137        startTime.mSampleTime   = 0; 
    138138         
    139         return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:0 framesToPlay:[decoder totalFrames] loopCount:0]; 
     139        return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:0 frameCount:[decoder totalFrames] loopCount:0]; 
    140140} 
    141141 
     
    147147        startTime.mSampleTime   = 0; 
    148148         
    149         return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:startingFrame framesToPlay:([decoder totalFrames] - startingFrame) loopCount:0]; 
    150 } 
    151  
    152 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startingFrame:(SInt64)startingFrame framesToPlay:(unsigned)framesToPlay 
     149        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 
    153153{ 
    154154        AudioTimeStamp startTime = { 0 }; 
     
    157157        startTime.mSampleTime   = 0; 
    158158         
    159         return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:startingFrame framesToPlay:framesToPlay loopCount:0]; 
    160 } 
    161  
    162 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startingFrame:(SInt64)startingFrame framesToPlay:(unsigned)framesToPlay loopCount:(unsigned)loopCount 
     159        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 
    163163{ 
    164164        AudioTimeStamp startTime = { 0 }; 
     
    167167        startTime.mSampleTime   = 0; 
    168168         
    169         return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:startingFrame framesToPlay:framesToPlay loopCount:loopCount]; 
     169        return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:startingFrame frameCount:frameCount loopCount:loopCount]; 
    170170} 
    171171 
    172172+ (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime 
    173173{ 
    174         return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:0 framesToPlay:[decoder totalFrames] loopCount:0]; 
     174        return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:0 frameCount:[decoder totalFrames] loopCount:0]; 
    175175} 
    176176 
    177177+ (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime startingFrame:(SInt64)startingFrame 
    178178{ 
    179         return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:startingFrame framesToPlay:([decoder totalFrames] - startingFrame) loopCount:0]; 
    180 } 
    181  
    182 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime startingFrame:(SInt64)startingFrame framesToPlay:(unsigned)framesToPlay 
    183 { 
    184         return [ScheduledAudioRegion scheduledAudioRegionForDecoder:decoder startTime:startTime startingFrame:startingFrame framesToPlay:framesToPlay loopCount:0]; 
    185 } 
    186  
    187 + (ScheduledAudioRegion *) scheduledAudioRegionForDecoder:(AudioDecoder *)decoder startTime:(AudioTimeStamp)startTime startingFrame:(SInt64)startingFrame framesToPlay:(unsigned)framesToPlay loopCount:(unsigned)loopCount 
     179        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 
    188188{ 
    189189        ScheduledAudioRegion *result = [[ScheduledAudioRegion alloc] init]; 
     
    192192        [result setStartTime:startTime]; 
    193193        [result setStartingFrame:startingFrame]; 
    194         [result setFramesToPlay:framesToPlay]; 
     194        [result setFrameCount:frameCount]; 
    195195        [result setLoopCount:loopCount]; 
     196         
     197        if(0 != [result startingFrame]) 
     198                [result reset]; 
    196199         
    197200        return [result autorelease]; 
     
    242245} 
    243246 
    244 - (UInt32)                      framesToPlay                                                    { return _framesToPlay; } 
    245  
    246 - (void) setFramesToPlay:(UInt32)framesToPlay 
    247 { 
    248         NSParameterAssert(0 < framesToPlay); 
    249  
    250         _framesToPlay = framesToPlay; 
     247- (UInt32)                      frameCount                                                      { return _frameCount; } 
     248 
     249- (void) setFrameCount:(UInt32)frameCount 
     250{ 
     251        NSParameterAssert(0 < frameCount); 
     252 
     253        _frameCount = frameCount; 
    251254} 
    252255 
     
    255258- (unsigned)            completedLoops                                                  { return _completedLoops; } 
    256259 
    257 - (SInt64)                      totalFrames                                                             { return (([self loopCount] + 1) * [self framesToPlay]); } 
     260- (SInt64)                      totalFrames                                                             { return (([self loopCount] + 1) * [self frameCount]); } 
    258261- (SInt64)                      currentFrame                                                    { return _totalFramesRead; } 
    259262- (SInt64)                      framesRemaining                                                 { return ([self totalFrames] - [self currentFrame]); } 
     
    265268        NSParameterAssert(0 <= frame && frame < [self totalFrames]); 
    266269         
    267         _completedLoops                         = frame / [self framesToPlay]; 
    268         _framesReadInCurrentLoop        = frame % [self framesToPlay]; 
     270        _completedLoops                         = frame / [self frameCount]; 
     271        _framesReadInCurrentLoop        = frame % [self frameCount]; 
    269272        _totalFramesRead                        = frame; 
    270273        _atEnd                                          = NO; 
     
    344347                return 0; 
    345348 
    346         UInt32  framesRemaining         = [self startingFrame] + [self framesToPlay] - [[self decoder] currentFrame]; 
     349        UInt32  framesRemaining         = [self startingFrame] + [self frameCount] - [[self decoder] currentFrame]; 
    347350        UInt32  framesToRead            = (frameCount < framesRemaining ? frameCount : framesRemaining); 
    348351        UInt32  framesRead                      = 0; 
     
    354357        _totalFramesRead                        += framesRead; 
    355358         
    356         if([self framesToPlay] == _framesReadInCurrentLoop || (0 == framesRead && 0 != framesToRead)) { 
     359        if([self frameCount] == _framesReadInCurrentLoop || (0 == framesRead && 0 != framesToRead)) { 
    357360                ++_completedLoops; 
    358361                _framesReadInCurrentLoop = 0; 
  • trunk/AudioLibrary/AudioLibrary.m

    r1014 r1025  
    193193 
    194194- (void) addRandomTracksFromLibraryToPlayQueue:(unsigned)count; 
     195 
     196- (BOOL) addStreamsFromExternalCueSheet:(NSString*)filename; 
    195197 
    196198- (void) updatePlayQueueHistory; 
     
    805807        NSError *error = nil; 
    806808         
    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 
    813813        AudioPropertiesReader *propertiesReader = [AudioPropertiesReader propertiesReaderForURL:[NSURL fileURLWithPath:filename] error:&error]; 
    814814        if(nil == propertiesReader) 
     
    819819                return NO; 
    820820         
    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