X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=projects%2Fmacosx%2Fframework%2FSources%2FVLCMediaPlayer.m;h=2359600a22c7849144d1efc153b684acb13994e3;hb=858057c2e0e928129bea1605fe361e9a4f64b15c;hp=73b720883b52ee72ce5d31b09bd01f3fe53dbbac;hpb=9a3c550857a385c87c6f8bacbb0cfed052b2d8ff;p=vlc diff --git a/projects/macosx/framework/Sources/VLCMediaPlayer.m b/projects/macosx/framework/Sources/VLCMediaPlayer.m index 73b720883b..2359600a22 100644 --- a/projects/macosx/framework/Sources/VLCMediaPlayer.m +++ b/projects/macosx/framework/Sources/VLCMediaPlayer.m @@ -1,12 +1,14 @@ /***************************************************************************** * VLCMediaPlayer.m: VLCKit.framework VLCMediaPlayer implementation ***************************************************************************** - * Copyright (C) 2007 Pierre d'Herbemont - * Copyright (C) 2007 the VideoLAN team + * Copyright (C) 2007-2009 Pierre d'Herbemont + * Copyright (C) 2007-2009 the VideoLAN team + * Partial Copyright (C) 2009 Felix Paul Kühne * $Id$ * * Authors: Pierre d'Herbemont * Faustion Osuna + * Felix Paul Kühne * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,6 +34,13 @@ # include "config.h" #endif +/* prevent system sleep */ +#import +/* FIXME: Ugly hack! */ +#ifdef __x86_64__ +#import +#endif + #include /* Notification Messages */ @@ -63,8 +72,8 @@ static void HandleMediaInstanceVolumeChanged(const libvlc_event_t * event, void 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 @@ -77,8 +86,8 @@ static void HandleMediaPositionChanged(const libvlc_event_t * event, void * 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]; } @@ -103,8 +112,8 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * 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 @@ -115,6 +124,18 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * } +static void HandleMediaPlayerMediaChanged(const libvlc_event_t * event, void * self) +{ + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + [[VLCEventManager sharedManager] callOnMainThreadObject:self + withMethod:@selector(mediaPlayerMediaChanged:) + withArgumentAsObject:[VLCMedia mediaWithLibVLCMediaDescriptor:event->u.media_player_media_changed.new_media]]; + + [pool release]; + +} + // TODO: Documentation @interface VLCMediaPlayer (Private) @@ -125,6 +146,7 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * - (void)mediaPlayerTimeChanged:(NSNumber *)newTime; - (void)mediaPlayerPositionChanged:(NSNumber *)newTime; - (void)mediaPlayerStateChanged:(NSNumber *)newState; +- (void)mediaPlayerMediaChanged:(VLCMedia *)media; @end @implementation VLCMediaPlayer @@ -185,15 +207,24 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * - (void)dealloc { + 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? delegate = nil; - libvlc_media_player_release((libvlc_media_player_t *)instance); - + // 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); + + libvlc_media_player_release(instance); + // Get rid of everything else [media release]; [cachedTime release]; + [cachedRemainingTime release]; + [drawable release]; [super dealloc]; } @@ -209,7 +240,7 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * } - (void)setVideoView:(VLCVideoView *)aVideoView -{ +{ [self setDrawable: aVideoView]; } @@ -221,19 +252,12 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * - (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 @@ -241,119 +265,114 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * return [[VLCLibrary sharedLibrary] audio]; } -- (void)setVideoAspectRatio:(char *)value +#pragma mark - +#pragma mark Subtitles + +- (void)setCurrentVideoSubTitleIndex:(NSUInteger)index { - libvlc_video_set_aspect_ratio( instance, value, NULL ); + libvlc_video_set_spu(instance, (int)index); } -- (char *)videoAspectRatio +- (NSUInteger)currentVideoSubTitleIndex { - libvlc_exception_t ex; - libvlc_exception_init( &ex ); - char * result = libvlc_video_get_aspect_ratio( instance, &ex ); - catch_exception( &ex ); - return result; + NSInteger count = libvlc_video_get_spu_count(instance); + + if (count <= 0) + return NSNotFound; + + return libvlc_video_get_spu(instance); } -- (void)setVideoSubTitles:(int)value +- (BOOL)openVideoSubTitlesFromFile:(NSString *)path { - libvlc_video_set_spu( instance, value, NULL ); + return libvlc_video_set_subtitle_file(instance, [path UTF8String]); } -- (int)videoSubTitles +- (NSArray *)videoSubTitles { - libvlc_exception_t ex; - libvlc_exception_init( &ex ); - int result = libvlc_video_get_spu( instance, &ex ); - catch_exception( &ex ); - return result; + libvlc_track_description_t *currentTrack = libvlc_video_get_spu_description(instance); + + NSMutableArray *tempArray = [NSMutableArray array]; + while (currentTrack) { + [tempArray addObject:[NSString stringWithUTF8String:currentTrack->psz_name]]; + currentTrack = currentTrack->p_next; + } + libvlc_track_description_release(currentTrack); + return [NSArray arrayWithArray: tempArray]; } + +#pragma mark - +#pragma mark Video Crop geometry + - (void)setVideoCropGeometry:(char *)value { - libvlc_video_set_crop_geometry( instance, value, NULL ); + libvlc_video_set_crop_geometry(instance, value); } - (char *)videoCropGeometry { - libvlc_exception_t ex; - libvlc_exception_init( &ex ); - char * result = libvlc_video_get_crop_geometry( instance, &ex ); - catch_exception( &ex ); + char * result = libvlc_video_get_crop_geometry(instance); return result; } -- (void)setVideoTeleText:(int)value +- (void)setVideoAspectRatio:(char *)value { - libvlc_video_set_teletext( instance, value, NULL ); + libvlc_video_set_aspect_ratio( instance, value ); } -- (int)videoTeleText +- (char *)videoAspectRatio { - libvlc_exception_t ex; - libvlc_exception_init( &ex ); - int result = libvlc_video_get_teletext( instance, &ex ); - catch_exception( &ex ); + char * result = libvlc_video_get_aspect_ratio( instance ); return result; } +- (void)saveVideoSnapshotAt:(NSString *)path withWidth:(NSUInteger)width andHeight:(NSUInteger)height +{ + int failure = libvlc_video_take_snapshot(instance, 0, [path UTF8String], width, height); + if (failure) + [[NSException exceptionWithName:@"Can't take a video snapshot" reason:@"No video output" userInfo:nil] raise]; +} + +- (void)setDeinterlaceFilter:(NSString *)name +{ + libvlc_video_set_deinterlace(instance, [name UTF8String]); +} + - (void)setRate:(float)value { - libvlc_media_player_set_rate( instance, value, NULL ); + 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 { - libvlc_exception_t ex; - libvlc_exception_init( &ex ); - NSSize result = NSMakeSize(libvlc_video_get_height((libvlc_media_player_t *)instance, &ex), - libvlc_video_get_width((libvlc_media_player_t *)instance, &ex)); - catch_exception( &ex ); - return result; + unsigned height = 0, width = 0; + int failure = libvlc_video_get_size(instance, 0, &width, &height); + if (failure) + [[NSException exceptionWithName:@"Can't get video size" reason:@"No video output" userInfo:nil] raise]; + return NSMakeSize(width, height); } - (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 @@ -361,80 +380,154 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * return cachedTime; } -- (void)setChapter:(int)value; +- (VLCTime *)remainingTime { - libvlc_media_player_set_chapter( instance, value, NULL ); + return cachedRemainingTime; } -- (int)chapter +- (NSUInteger)fps { - libvlc_exception_t ex; - libvlc_exception_init( &ex ); - int result = libvlc_media_player_get_chapter( instance, &ex ); - catch_exception( &ex ); - return result; + return libvlc_media_player_get_fps(instance); } -- (int)countOfChapters +#pragma mark - +#pragma mark Chapters +- (void)setCurrentChapterIndex:(NSUInteger)value; { - libvlc_exception_t ex; - libvlc_exception_init( &ex ); - int result = libvlc_media_player_get_chapter_count( instance, &ex ); - catch_exception( &ex ); + libvlc_media_player_set_chapter(instance, value); +} + +- (NSUInteger)currentChapterIndex +{ + NSInteger count = libvlc_media_player_get_chapter_count(instance); + if (count <= 0) + return NSNotFound; + NSUInteger result = libvlc_media_player_get_chapter(instance); return result; } -- (void)setAudioTrack:(int)value +- (void)nextChapter { - libvlc_audio_set_track( instance, value, NULL ); + libvlc_media_player_next_chapter(instance); } -- (int)audioTrack +- (void)previousChapter { - libvlc_exception_t ex; - libvlc_exception_init( &ex ); - int result = libvlc_audio_get_track( instance, &ex ); - catch_exception( &ex ); - return result; + libvlc_media_player_previous_chapter(instance); +} + +- (NSArray *)chaptersForTitleIndex:(NSUInteger)title +{ + 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); + NSMutableArray *tempArray = [NSMutableArray array]; + NSInteger 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]; +} + +#pragma mark - +#pragma mark Titles + +- (void)setCurrentTitleIndex:(NSUInteger)value +{ + libvlc_media_player_set_title(instance, value); +} + +- (NSUInteger)currentTitleIndex +{ + NSInteger count = libvlc_media_player_get_title_count(instance); + if (count <= 0) + return NSNotFound; + + return libvlc_media_player_get_title(instance); } -- (int)countOfAudioTracks +- (NSUInteger)countOfTitles { - libvlc_exception_t ex; - libvlc_exception_init( &ex ); - int result = libvlc_audio_get_track_count( instance, &ex ); - catch_exception( &ex ); + NSUInteger result = libvlc_media_player_get_title_count(instance); return result; } -- (void)setAudioChannel:(int)value +- (NSArray *)titles { - libvlc_audio_set_channel( instance, value, NULL ); + 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 - +#pragma mark Audio tracks +- (void)setCurrentAudioTrackIndex:(NSUInteger)value +{ + libvlc_audio_set_track( instance, (int)value); } -- (int)audioChannel +- (NSUInteger)currentAudioTrackIndex { - libvlc_exception_t ex; - libvlc_exception_init( &ex ); - int result = libvlc_audio_get_channel( 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); return result; } +- (NSArray *)audioTracks +{ + 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); + NSMutableArray *tempArray = [NSMutableArray array]; + 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:(NSInteger)value +{ + libvlc_audio_set_channel(instance, value); +} + +- (NSInteger)audioChannel +{ + return libvlc_audio_get_channel(instance); +} + - (void)setMedia:(VLCMedia *)value { if (media != 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]); } } @@ -444,11 +537,8 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * } - (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; } @@ -458,53 +548,25 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * { /* 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; } - // Return if there is no media available or if the stream is not paused or - // playing something else - if (!media || (![self isPlaying] && [self state] != VLCMediaPlayerStatePaused)) - return; - - // Should never get here. - if (!instance) - return; - - // Pause the stream - libvlc_exception_t ex; - libvlc_exception_init( &ex ); - libvlc_media_player_pause( (libvlc_media_player_t *)instance, &ex ); - catch_exception( &ex ); - - // TODO: Should we record the time in case the media instance is destroyed - // then rebuilt? + libvlc_media_player_pause(instance); } - (void)stop { - if( 0 && [NSThread isMainThread] ) - { - /* 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 - * to move that to libvlc */ - [self performSelectorInBackground:@selector(stop) withObject:nil]; - return; - } + libvlc_media_player_stop(instance); +} + +- (void)gotoNextFrame +{ + libvlc_media_player_next_frame(instance); - // Return if there is no media available or if the system is not in play status - // or pause status. - if (!media) - return; - - libvlc_exception_t ex; - libvlc_exception_init( &ex ); - libvlc_media_player_stop((libvlc_media_player_t *)instance, &ex); - catch_exception( &ex ); } - (void)fastForward @@ -527,6 +589,64 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * [self setRate: -rate]; } +- (void)jumpBackward:(NSInteger)interval +{ + if( [self isSeekable] ) + { + interval = interval * 1000; + [self setTime: [VLCTime timeWithInt: ([[self time] intValue] - interval)]]; + } +} + +- (void)jumpForward:(NSInteger)interval +{ + if( [self isSeekable] ) + { + interval = interval * 1000; + [self setTime: [VLCTime timeWithInt: ([[self time] intValue] + interval)]]; + } +} + +- (void)extraShortJumpBackward +{ + [self jumpBackward:3]; +} + +- (void)extraShortJumpForward +{ + [self jumpForward:3]; +} + +- (void)shortJumpBackward +{ + [self jumpBackward:10]; +} + +- (void)shortJumpForward +{ + [self jumpForward:10]; +} + +- (void)mediumJumpBackward +{ + [self jumpBackward:60]; +} + +- (void)mediumJumpForward +{ + [self jumpForward:60]; +} + +- (void)longJumpBackward +{ + [self jumpBackward:300]; +} + +- (void)longJumpForward +{ + [self jumpForward:300]; +} + + (NSSet *)keyPathsForValuesAffectingIsPlaying { return [NSSet setWithObjects:@"state", nil]; @@ -541,16 +661,7 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * - (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[] = @@ -576,28 +687,17 @@ 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 @@ -614,6 +714,7 @@ static const VLCMediaPlayerState libvlc_to_local_state[] = delegate = nil; media = nil; cachedTime = [[VLCTime nullTime] retain]; + cachedRemainingTime = [[VLCTime nullTime] retain]; position = 0.0f; cachedState = VLCMediaPlayerStateStopped; @@ -622,11 +723,11 @@ static const VLCMediaPlayerState libvlc_to_local_state[] = // 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; @@ -634,43 +735,54 @@ static const VLCMediaPlayerState libvlc_to_local_state[] = - (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 ); - 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_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:@"time"]; + [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"]; } +- (void)delaySleep +{ + UpdateSystemActivity(UsrActivity); +} + - (void)mediaPlayerPositionChanged:(NSNumber *)newPosition { + // This seems to be the most relevant place to delay sleeping and screen saver. + [self delaySleep]; + [self willChangeValueForKey:@"position"]; position = [newPosition floatValue]; [self didChangeValueForKey:@"position"]; @@ -682,4 +794,16 @@ static const VLCMediaPlayerState libvlc_to_local_state[] = cachedState = [newState intValue]; [self didChangeValueForKey:@"state"]; } + +- (void)mediaPlayerMediaChanged:(VLCMedia *)newMedia +{ + [self willChangeValueForKey:@"media"]; + if (media != newMedia) + { + [media release]; + media = [newMedia retain]; + } + [self didChangeValueForKey:@"media"]; +} + @end