static void HandleMediaTimeChanged(const libvlc_event_t * event, void * self)
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- [[VLCEventManager sharedManager] callOnMainThreadObject:self
- withMethod:@selector(mediaPlayerTimeChanged:)
+ [[VLCEventManager sharedManager] callOnMainThreadObject:self
+ withMethod:@selector(mediaPlayerTimeChanged:)
withArgumentAsObject:[NSNumber numberWithLongLong:event->u.media_player_time_changed.new_time]];
[[VLCEventManager sharedManager] callOnMainThreadDelegateOfObject:self
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- [[VLCEventManager sharedManager] callOnMainThreadObject:self
- withMethod:@selector(mediaPlayerPositionChanged:)
+ [[VLCEventManager sharedManager] callOnMainThreadObject:self
+ withMethod:@selector(mediaPlayerPositionChanged:)
withArgumentAsObject:[NSNumber numberWithFloat:event->u.media_player_position_changed.new_position]];
[pool release];
}
static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * self)
{
VLCMediaPlayerState newState;
-
+
if( event->type == libvlc_MediaPlayerPlaying )
newState = VLCMediaPlayerStatePlaying;
else if( event->type == libvlc_MediaPlayerPaused )
NSLog(@"%s: Unknown event", __FUNCTION__);
return;
}
-
+
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
-
- [[VLCEventManager sharedManager] callOnMainThreadObject:self
- withMethod:@selector(mediaPlayerStateChanged:)
+
+ [[VLCEventManager sharedManager] callOnMainThreadObject:self
+ withMethod:@selector(mediaPlayerStateChanged:)
withArgumentAsObject:[NSNumber numberWithInt:newState]];
-
+
[[VLCEventManager sharedManager] callOnMainThreadDelegateOfObject:self
withDelegateMethod:@selector(mediaPlayerStateChanged:)
withNotificationName:VLCMediaPlayerStateChanged];
-
+
[pool release];
-
+
}
static void HandleMediaPlayerMediaChanged(const libvlc_event_t * event, void * self)
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
-
- [[VLCEventManager sharedManager] callOnMainThreadObject:self
- withMethod:@selector(mediaPlayerMediaChanged:)
+
+ [[VLCEventManager sharedManager] callOnMainThreadObject:self
+ withMethod:@selector(mediaPlayerMediaChanged:)
withArgumentAsObject:[VLCMedia mediaWithLibVLCMediaDescriptor:event->u.media_player_media_changed.new_media]];
-
+
[pool release];
-
+
}
- (void)dealloc
{
- NSAssert(libvlc_media_player_get_state(instance, NULL) == libvlc_Stopped, @"You released the media player before ensuring that it is stopped");
+ NSAssert(libvlc_media_player_get_state(instance) == libvlc_Stopped, @"You released the media player before ensuring that it is stopped");
// Always get rid of the delegate first so we can stop sending messages to it
// TODO: Should we tell the delegate that we're shutting down?
// Clear our drawable as we are going to release it, we don't
// want the core to use it from this point. This won't happen as
// the media player must be stopped.
- libvlc_media_player_set_nsobject(instance, nil, NULL);
+ libvlc_media_player_set_nsobject(instance, nil);
libvlc_media_player_release(instance);
-
+
// Get rid of everything else
[media release];
[cachedTime release];
+ [cachedRemainingTime release];
[drawable release];
[super dealloc];
}
- (void)setVideoView:(VLCVideoView *)aVideoView
-{
+{
[self setDrawable: aVideoView];
}
- (void)setDrawable:(id)aDrawable
{
// Make sure that this instance has been associated with the drawing canvas.
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- libvlc_media_player_set_nsobject(instance, aDrawable, &ex);
- catch_exception( &ex );
+ libvlc_media_player_set_nsobject(instance, aDrawable);
}
- (id)drawable
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- id ret = libvlc_media_player_get_nsobject(instance);
- catch_exception( &ex );
- return ret;
+ return libvlc_media_player_get_nsobject(instance);
}
- (VLCAudio *)audio
{
libvlc_exception_t ex;
libvlc_exception_init( &ex );
- int count = libvlc_video_get_spu_count( instance, &ex );
- catch_exception( &ex );
+ NSInteger count = libvlc_video_get_spu_count( instance, &ex );
+ if (libvlc_exception_raised( &ex ))
+ {
+ libvlc_exception_clear( &ex );
+ return NSNotFound;
+ }
if (count <= 0)
return NSNotFound;
NSUInteger result = libvlc_video_get_spu( instance, &ex );
- catch_exception( &ex );
- return result;
+ if (libvlc_exception_raised( &ex ))
+ {
+ libvlc_exception_clear( &ex );
+ return NSNotFound;
+ }
+ else
+ return result;
}
- (BOOL)openVideoSubTitlesFromFile:(NSString *)path
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- BOOL result = libvlc_video_set_subtitle_file( instance, [path UTF8String], &ex );
- catch_exception( &ex );
- return result;
+ return libvlc_video_set_subtitle_file(instance, [path UTF8String]);
}
- (NSArray *)videoSubTitles
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- int count = libvlc_video_get_spu_count( instance, &ex );
- catch_exception( &ex );
+ libvlc_track_description_t *currentTrack = libvlc_video_get_spu_description(instance);
- libvlc_track_description_t *tracks = libvlc_video_get_spu_description( instance, &ex );
NSMutableArray *tempArray = [NSMutableArray array];
- NSInteger i;
- for (i = 0; i < count; i++)
- {
- [tempArray addObject:[NSString stringWithUTF8String: tracks->psz_name]];
- tracks = tracks->p_next;
+ while (currentTrack) {
+ [tempArray addObject:[NSString stringWithUTF8String:currentTrack->psz_name]];
+ currentTrack = currentTrack->p_next;
}
+ libvlc_track_description_release(currentTrack);
return [NSArray arrayWithArray: tempArray];
}
return result;
}
-- (void)setVideoTeleText:(int)value
-{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- libvlc_video_set_teletext( instance, value, &ex );
- catch_exception( &ex );
-}
-
-- (int)videoTeleText
-{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- int result = libvlc_video_get_teletext( instance, &ex );
- catch_exception( &ex );
- return result;
-}
-
- (void)saveVideoSnapshotAt: (NSString *)path withWidth:(NSUInteger)width andHeight:(NSUInteger)height
{
libvlc_exception_t ex;
- (void)setRate:(float)value
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- libvlc_media_player_set_rate( instance, value, &ex );
- catch_exception( &ex );
+ libvlc_media_player_set_rate(instance, value);
}
- (float)rate
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- float result = libvlc_media_player_get_rate( instance, &ex );
- catch_exception( &ex );
- return result;
+ return libvlc_media_player_get_rate(instance);
}
- (NSSize)videoSize
- (BOOL)hasVideoOut
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- BOOL result = libvlc_media_player_has_vout((libvlc_media_player_t *)instance, &ex);
- if (libvlc_exception_raised( &ex ))
- {
- libvlc_exception_clear( &ex );
- return NO;
- }
- else
- return result;
+ return libvlc_media_player_has_vout(instance);
}
- (float)framesPerSecond
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- float result = libvlc_media_player_get_fps( (libvlc_media_player_t *)instance, &ex );
- catch_exception( &ex );
- return result;
+ return libvlc_media_player_get_fps(instance);
}
- (void)setTime:(VLCTime *)value
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
// Time is managed in seconds, while duration is managed in microseconds
// TODO: Redo VLCTime to provide value numberAsMilliseconds, numberAsMicroseconds, numberAsSeconds, numberAsMinutes, numberAsHours
- libvlc_media_player_set_time( (libvlc_media_player_t *)instance,
- (value ? [[value numberValue] longLongValue] / 1000 : 0),
- &ex );
- catch_exception( &ex );
+ libvlc_media_player_set_time(instance, value ? [[value numberValue] longLongValue] : 0);
}
- (VLCTime *)time
- (VLCTime *)remainingTime
{
- double currentTime = [[cachedTime numberValue] doubleValue];
- double remaining = currentTime / position * (1 - position);
- return [VLCTime timeWithNumber:[NSNumber numberWithDouble:-remaining]];
+ return cachedRemainingTime;
}
-- (int)fps
+- (NSUInteger)fps
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- int result = libvlc_media_player_get_fps( instance, &ex );
- catch_exception( &ex );
- return result;
+ return libvlc_media_player_get_fps(instance);
}
#pragma mark -
#pragma mark Chapters
- (void)setCurrentChapterIndex:(NSUInteger)value;
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- libvlc_media_player_set_chapter( instance, value, &ex );
- catch_exception( &ex );
+ libvlc_media_player_set_chapter(instance, value);
}
- (NSUInteger)currentChapterIndex
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- int count = libvlc_media_player_get_chapter_count( instance, &ex );
- catch_exception( &ex );
+ NSInteger count = libvlc_media_player_get_chapter_count(instance);
if (count <= 0)
return NSNotFound;
- NSUInteger result = libvlc_media_player_get_chapter( instance, &ex );
- catch_exception( &ex );
+ NSUInteger result = libvlc_media_player_get_chapter(instance);
return result;
}
- (void)nextChapter
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- libvlc_media_player_next_chapter( instance, &ex );
- catch_exception( &ex );
+ libvlc_media_player_next_chapter(instance);
}
- (void)previousChapter
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- libvlc_media_player_previous_chapter( instance, &ex );
- catch_exception( &ex );
+ libvlc_media_player_previous_chapter(instance);
}
- (NSArray *)chaptersForTitleIndex:(NSUInteger)title
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- int count = libvlc_media_player_get_chapter_count(instance, &ex);
+ NSInteger count = libvlc_media_player_get_chapter_count(instance);
if (count <= 0)
return [NSArray array];
- libvlc_track_description_t *tracks = libvlc_video_get_chapter_description( instance, title, &ex );
+ libvlc_track_description_t *tracks = libvlc_video_get_chapter_description(instance, title);
NSMutableArray *tempArray = [NSMutableArray array];
NSInteger i;
for (i = 0; i < count ; i++)
{
- [tempArray addObject:[NSString stringWithUTF8String: tracks->psz_name]];
+ [tempArray addObject:[NSString stringWithUTF8String:tracks->psz_name]];
tracks = tracks->p_next;
}
- return [NSArray arrayWithArray: tempArray];
+ libvlc_track_description_release(tracks);
+ return [NSArray arrayWithArray:tempArray];
}
#pragma mark -
- (void)setCurrentTitleIndex:(NSUInteger)value
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- libvlc_media_player_set_title( instance, value, &ex );
- catch_exception( &ex );
+ libvlc_media_player_set_title(instance, value);
}
- (NSUInteger)currentTitleIndex
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
-
- int count = libvlc_media_player_get_title_count( instance, &ex );
- catch_exception( &ex );
+ NSInteger count = libvlc_media_player_get_title_count(instance);
if (count <= 0)
return NSNotFound;
-
- NSUInteger result = libvlc_media_player_get_title( instance, &ex );
- catch_exception( &ex );
- return result;
+
+ return libvlc_media_player_get_title(instance);
}
-- (int)countOfTitles
+- (NSUInteger)countOfTitles
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- int result = libvlc_media_player_get_title_count( instance, &ex );
- catch_exception( &ex );
+ NSUInteger result = libvlc_media_player_get_title_count(instance);
return result;
}
- (NSArray *)titles
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- libvlc_track_description_t *tracks = libvlc_video_get_title_description( instance, &ex );
+ libvlc_track_description_t *tracks = libvlc_video_get_title_description(instance);
NSMutableArray *tempArray = [NSMutableArray array];
NSInteger i;
for (i = 0; i < [self countOfTitles] ; i++)
[tempArray addObject:[NSString stringWithUTF8String: tracks->psz_name]];
tracks = tracks->p_next;
}
+ libvlc_track_description_release(tracks);
return [NSArray arrayWithArray: tempArray];
}
#pragma mark Audio tracks
- (void)setCurrentAudioTrackIndex:(NSUInteger)value
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- libvlc_audio_set_track( instance, (int)value, &ex );
- catch_exception( &ex );
+ libvlc_audio_set_track( instance, (int)value);
}
- (NSUInteger)currentAudioTrackIndex
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- int count = libvlc_audio_get_track_count( instance, &ex );
- catch_exception( &ex );
+ NSInteger count = libvlc_audio_get_track_count(instance);
if (count <= 0)
return NSNotFound;
-
- NSUInteger result = libvlc_audio_get_track( instance, &ex );
- catch_exception( &ex );
+
+ NSUInteger result = libvlc_audio_get_track(instance);
return result;
}
- (NSArray *)audioTracks
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- int count = libvlc_audio_get_track_count( instance, &ex );
- catch_exception( &ex );
+ NSInteger count = libvlc_audio_get_track_count(instance);
if (count <= 0)
return [NSArray array];
- libvlc_track_description_t *tracks = libvlc_audio_get_track_description( instance, &ex );
+ libvlc_track_description_t *tracks = libvlc_audio_get_track_description(instance);
NSMutableArray *tempArray = [NSMutableArray array];
- NSInteger i;
+ NSUInteger i;
for (i = 0; i < count ; i++)
{
[tempArray addObject:[NSString stringWithUTF8String: tracks->psz_name]];
tracks = tracks->p_next;
}
+ libvlc_track_description_release(tracks);
return [NSArray arrayWithArray: tempArray];
}
-- (void)setAudioChannel:(int)value
+- (void)setAudioChannel:(NSInteger)value
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- libvlc_audio_set_channel( instance, value, &ex );
- catch_exception( &ex );
+ libvlc_audio_set_channel(instance, value);
}
-- (int)audioChannel
+- (NSInteger)audioChannel
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- int result = libvlc_audio_get_channel( instance, &ex );
- catch_exception( &ex );
- return result;
+ return libvlc_audio_get_channel(instance);
}
- (void)setMedia:(VLCMedia *)value
{
if (media && [media compare:value] == NSOrderedSame)
return;
-
+
[media release];
media = [value retain];
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- libvlc_media_player_set_media( instance, [media libVLCMediaDescriptor], &ex );
- catch_exception( &ex );
+ libvlc_media_player_set_media(instance, [media libVLCMediaDescriptor]);
}
}
}
- (BOOL)play
-{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- libvlc_media_player_play( (libvlc_media_player_t *)instance, &ex );
- catch_exception( &ex );
+{
+ libvlc_media_player_play(instance);
return YES;
}
{
/* Hack because we create a dead lock here, when the vout is stopped
* and tries to recontact us on the main thread */
- /* FIXME: to do this properly we need to do some locking. We may want
+ /* FIXME: to do this properly we need to do some locking. We may want
* to move that to libvlc */
[self performSelectorInBackground:@selector(pause) withObject:nil];
return;
}
// Pause the stream
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- libvlc_media_player_pause( (libvlc_media_player_t *)instance, &ex );
-
- // fail gracefully
- // in most cases, it's just EOF so let's stop
- if (libvlc_exception_raised(&ex))
- [self stop];
-
- libvlc_exception_clear(&ex);
+ libvlc_media_player_pause(instance);
}
- (void)stop
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- libvlc_media_player_stop((libvlc_media_player_t *)instance, &ex);
- catch_exception( &ex );
+ libvlc_media_player_stop(instance);
+}
+
+- (void)gotoNextFrame
+{
+ libvlc_media_player_next_frame(instance);
+
}
- (void)fastForward
{
if( [self isSeekable] )
{
- interval = interval * 1000000;
+ interval = interval * 1000;
[self setTime: [VLCTime timeWithInt: ([[self time] intValue] - interval)]];
}
}
{
if( [self isSeekable] )
{
- interval = interval * 1000000;
+ interval = interval * 1000;
[self setTime: [VLCTime timeWithInt: ([[self time] intValue] + interval)]];
}
}
- (BOOL)willPlay
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- BOOL ret = libvlc_media_player_will_play( (libvlc_media_player_t *)instance, &ex );
- if (libvlc_exception_raised(&ex))
- {
- libvlc_exception_clear(&ex);
- return NO;
- }
- else
- return ret;
+ return libvlc_media_player_will_play(instance);
}
static const VLCMediaPlayerState libvlc_to_local_state[] =
- (void)setPosition:(float)newPosition
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- libvlc_media_player_set_position( instance, newPosition, &ex );
- catch_exception( &ex );
+ libvlc_media_player_set_position(instance, newPosition);
}
- (BOOL)isSeekable
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- BOOL ret = libvlc_media_player_is_seekable( instance, &ex );
- catch_exception( &ex );
- return ret;
+ return libvlc_media_player_is_seekable(instance);
}
- (BOOL)canPause
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
- BOOL ret = libvlc_media_player_can_pause( instance, &ex );
- catch_exception( &ex );
- return ret;
+ return libvlc_media_player_can_pause(instance);
}
- (void *)libVLCMediaPlayer
delegate = nil;
media = nil;
cachedTime = [[VLCTime nullTime] retain];
+ cachedRemainingTime = [[VLCTime nullTime] retain];
position = 0.0f;
cachedState = VLCMediaPlayerStateStopped;
// instance
libvlc_exception_t ex;
libvlc_exception_init( &ex );
- instance = (void *)libvlc_media_player_new([VLCLibrary sharedInstance], &ex);
+ instance = libvlc_media_player_new([VLCLibrary sharedInstance]);
catch_exception( &ex );
-
+
[self registerObservers];
-
+
[self setDrawable:aDrawable];
}
return self;
- (void)registerObservers
{
- libvlc_exception_t ex;
- libvlc_exception_init( &ex );
-
// Attach event observers into the media instance
- libvlc_event_manager_t * p_em = libvlc_media_player_event_manager( instance, &ex );
- libvlc_event_attach( p_em, libvlc_MediaPlayerPlaying, HandleMediaInstanceStateChanged, self, &ex );
- libvlc_event_attach( p_em, libvlc_MediaPlayerPaused, HandleMediaInstanceStateChanged, self, &ex );
- libvlc_event_attach( p_em, libvlc_MediaPlayerEncounteredError, HandleMediaInstanceStateChanged, self, &ex );
- libvlc_event_attach( p_em, libvlc_MediaPlayerEndReached, HandleMediaInstanceStateChanged, self, &ex );
+ libvlc_event_manager_t * p_em = libvlc_media_player_event_manager(instance);
+ libvlc_event_attach(p_em, libvlc_MediaPlayerPlaying, HandleMediaInstanceStateChanged, self);
+ libvlc_event_attach(p_em, libvlc_MediaPlayerPaused, HandleMediaInstanceStateChanged, self);
+ libvlc_event_attach(p_em, libvlc_MediaPlayerEncounteredError, HandleMediaInstanceStateChanged, self);
+ libvlc_event_attach(p_em, libvlc_MediaPlayerEndReached, HandleMediaInstanceStateChanged, self);
/* FIXME: We may want to turn that off when none is interested by that */
- libvlc_event_attach( p_em, libvlc_MediaPlayerPositionChanged, HandleMediaPositionChanged, self, &ex );
- libvlc_event_attach( p_em, libvlc_MediaPlayerTimeChanged, HandleMediaTimeChanged, self, &ex );
- libvlc_event_attach( p_em, libvlc_MediaPlayerMediaChanged, HandleMediaPlayerMediaChanged, self, &ex );
- catch_exception( &ex );
+ libvlc_event_attach(p_em, libvlc_MediaPlayerPositionChanged, HandleMediaPositionChanged, self);
+ libvlc_event_attach(p_em, libvlc_MediaPlayerTimeChanged, HandleMediaTimeChanged, self);
+ libvlc_event_attach(p_em, libvlc_MediaPlayerMediaChanged, HandleMediaPlayerMediaChanged, self);
}
- (void)unregisterObservers
{
- libvlc_event_manager_t * p_em = libvlc_media_player_event_manager( instance, NULL );
- libvlc_event_detach( p_em, libvlc_MediaPlayerPlaying, HandleMediaInstanceStateChanged, self, NULL );
- libvlc_event_detach( p_em, libvlc_MediaPlayerPaused, HandleMediaInstanceStateChanged, self, NULL );
- libvlc_event_detach( p_em, libvlc_MediaPlayerEncounteredError, HandleMediaInstanceStateChanged, self, NULL );
- libvlc_event_detach( p_em, libvlc_MediaPlayerEndReached, HandleMediaInstanceStateChanged, self, NULL );
- libvlc_event_detach( p_em, libvlc_MediaPlayerPositionChanged, HandleMediaPositionChanged, self, NULL );
- libvlc_event_detach( p_em, libvlc_MediaPlayerTimeChanged, HandleMediaTimeChanged, self, NULL );
- libvlc_event_attach( p_em, libvlc_MediaPlayerMediaChanged, HandleMediaPlayerMediaChanged, self, NULL );
+ libvlc_event_manager_t * p_em = libvlc_media_player_event_manager(instance);
+ libvlc_event_detach(p_em, libvlc_MediaPlayerPlaying, HandleMediaInstanceStateChanged, self);
+ libvlc_event_detach(p_em, libvlc_MediaPlayerPaused, HandleMediaInstanceStateChanged, self);
+ libvlc_event_detach(p_em, libvlc_MediaPlayerEncounteredError, HandleMediaInstanceStateChanged, self);
+ libvlc_event_detach(p_em, libvlc_MediaPlayerEndReached, HandleMediaInstanceStateChanged, self);
+ libvlc_event_detach(p_em, libvlc_MediaPlayerPositionChanged, HandleMediaPositionChanged, self);
+ libvlc_event_detach(p_em, libvlc_MediaPlayerTimeChanged, HandleMediaTimeChanged, self);
+ libvlc_event_detach(p_em, libvlc_MediaPlayerMediaChanged, HandleMediaPlayerMediaChanged, self);
}
- (void)mediaPlayerTimeChanged:(NSNumber *)newTime
[self willChangeValueForKey:@"remainingTime"];
[cachedTime release];
cachedTime = [[VLCTime timeWithNumber:newTime] retain];
-
+ [cachedRemainingTime release];
+ double currentTime = [[cachedTime numberValue] doubleValue];
+ double remaining = currentTime / position * (1 - position);
+ cachedRemainingTime = [[VLCTime timeWithNumber:[NSNumber numberWithDouble:-remaining]] retain];
[self didChangeValueForKey:@"remainingTime"];
[self didChangeValueForKey:@"time"];
}