With some help from stackoverflow, I managed to implement a timer that checks the currentPlaybackTime
variable in a mediaplayer video every 1/10th of a second.
I also have an NSArray
of Cue objects that have a time attribute (NSNumber
). I want some code that simply checks if the currentPlaybackTime
matches one of the time attributes in the cue array and returns the cue object.
My progress so far:
- (void) PollPlayerTimer_tick:(NSObject *)sender {
if (self.movieController.playbackState == MPMoviePlaybackStatePlaying)
self.lastRecordedPlaybackTime = self.movieController.currentPlaybackTime;
if (decidingStatement) {
// Do something
}
}
The decidingStatement has to be something like:
[NSNumber numberWithDouble:self.movieController.currentPlaybackTime] doubleValue]
is equal to one of the time attributes in cues. It doesn’t seem to work using [NSNumber numberWithDouble:self.movieController.currentPlaybackTime] doubleValue] == 3.9
(for example) because currentPlaybackTime
could be 3.99585 which is not exactly 3.9. It works if I check if currentPlaybackTime
is within plus or minus 0.1 seconds of 3.9.
The second problem is that I have to search the cues array to get the cue time. I could iterate through the array to get the time attribute. But iterating over an array ten times a second doesn’t seem like the best practise.
There must be a better way!
Update
danh has a great solution below, the code currently looks like:
- (void) PollPlayerTimer_tick:(NSObject *)sender {
if (self.movieController.playbackState == MPMoviePlaybackStatePlaying)
self.lastRecordedPlaybackTime = self.movieController.currentPlaybackTime;
NSInteger *decidingStatement = [self indexOfCueMatching:[[NSNumber numberWithDouble:self.movieController.currentPlaybackTime] doubleValue] in:self.video.cues];
if (decidingStatement) {
}
}
- (NSComparisonResult)number:(NSNumber *)nA nearlyEquals:(NSNumber *)nB within:(double)epsilon {
double dNa = [nA doubleValue];
double dNb = [nB doubleValue];
if (fabs(dNa - dNb) < epsilon) return NSOrderedSame;
if (dNa < dNb) return NSOrderedAscending;
return NSOrderedDescending;
}
- (NSInteger)indexOfCueMatching:(NSNumber *)playbackTime in:(NSArray *)cues {
NSInteger index = self.lastCheckedIndex+1;
if (index >= cues.count) return NSNotFound;
NSComparisonResult compResult = [self number:[cues[index] time] nearlyEquals:playbackTime within:0.1];
while (index<cues.count && compResult == NSOrderedAscending) {
compResult = [self number:[cues[++index] time] nearlyEquals:playbackTime within:0.1];
}
self.lastCheckedIndex = index;
return (compResult == NSOrderedSame)? index : NSNotFound;
}