/*****************************************************************************
* 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 <pdherbemont # videolan.org>
* Faustion Osuna <enrique.osuna # gmail.com>
+ * Felix Paul Kühne <fkuehne # videolan.org>
*
* 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
# include "config.h"
#endif
+/* prevent system sleep */
+#import <CoreServices/CoreServices.h>
+/* FIXME: Ugly hack! */
+#ifdef __x86_64__
+#import <CoreServices/../Frameworks/OSServices.framework/Headers/Power.h>
+#endif
+
#include <vlc/vlc.h>
/* Notification Messages */
- (void)dealloc
{
+ NSAssert(libvlc_media_player_get_state(instance, NULL) == 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, NULL);
+
+ libvlc_media_player_release(instance);
// Get rid of everything else
[media release];
[cachedTime release];
+ [drawable release];
[super dealloc];
}
- (void)setVideoAspectRatio:(char *)value
{
- libvlc_video_set_aspect_ratio( instance, value, NULL );
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ libvlc_video_set_aspect_ratio( instance, value, &ex );
+ catch_exception( &ex );
}
- (char *)videoAspectRatio
- (void)setVideoSubTitles:(int)value
{
- libvlc_video_set_spu( instance, value, NULL );
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ libvlc_video_set_spu( instance, value, &ex );
+ catch_exception( &ex );
+}
+
+- (int)countOfVideoSubTitles
+{
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ int result = libvlc_video_get_spu_count( instance, &ex );
+ catch_exception( &ex );
+ return result;
}
-- (int)videoSubTitles
+- (int)currentVideoSubTitles
{
libvlc_exception_t ex;
libvlc_exception_init( &ex );
int result = libvlc_video_get_spu( instance, &ex );
+ if (libvlc_exception_raised(&ex))
+ {
+ libvlc_exception_clear(&ex);
+ return -1;
+ }
+ else
+ {
+ libvlc_exception_clear(&ex);
+ 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;
}
- (void)setVideoCropGeometry:(char *)value
{
- libvlc_video_set_crop_geometry( instance, value, NULL );
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ libvlc_video_set_crop_geometry( instance, value, &ex );
+ catch_exception( &ex );
}
- (char *)videoCropGeometry
- (void)setVideoTeleText:(int)value
{
- libvlc_video_set_teletext( instance, value, NULL );
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ libvlc_video_set_teletext( instance, value, &ex );
+ catch_exception( &ex );
}
- (int)videoTeleText
return result;
}
+- (void)saveVideoSnapshotAt: (NSString *)path withWidth:(NSUInteger)width andHeight:(NSUInteger)height
+{
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ libvlc_video_take_snapshot( instance, [path UTF8String], width, height, &ex );
+ catch_exception( &ex );
+}
+
+- (void)setDeinterlaceFilter: (NSString *)name enabled: (BOOL)enabled
+{
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ libvlc_video_set_deinterlace( instance, (int)enabled , [name UTF8String], &ex );
+ catch_exception( &ex );
+}
+
- (void)setRate:(float)value
{
- libvlc_media_player_set_rate( instance, value, NULL );
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ libvlc_media_player_set_rate( instance, value, &ex );
+ catch_exception( &ex );
}
- (float)rate
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;
+ return result;
}
- (BOOL)hasVideoOut
return cachedTime;
}
+- (VLCTime *)remainingTime
+{
+ double currentTime = [[cachedTime numberValue] doubleValue];
+ double remaining = currentTime / position * (1 - position);
+ return [VLCTime timeWithNumber:[NSNumber numberWithDouble:-remaining]];
+}
+
+- (int)fps
+{
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ int result = libvlc_media_player_get_fps( instance, &ex );
+ catch_exception( &ex );
+ return result;
+}
+
- (void)setChapter:(int)value;
{
- libvlc_media_player_set_chapter( instance, value, NULL );
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ libvlc_media_player_set_chapter( instance, value, &ex );
+ catch_exception( &ex );
}
-- (int)chapter
+- (int)currentChapter
{
libvlc_exception_t ex;
libvlc_exception_init( &ex );
return result;
}
+- (void)nextChapter
+{
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ libvlc_media_player_next_chapter( instance, &ex );
+ catch_exception( &ex );
+}
+
+- (void)previousChapter
+{
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ libvlc_media_player_previous_chapter( instance, &ex );
+ catch_exception( &ex );
+}
+
+- (void)setCurrentTitle:(int)value
+{
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ libvlc_media_player_set_title( instance, value, &ex );
+ catch_exception( &ex );
+}
+
+- (int)currentTitle
+{
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ int result = libvlc_media_player_get_title( instance, &ex );
+ catch_exception( &ex );
+ return result;
+}
+
+- (int)countOfTitles
+{
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ int result = libvlc_media_player_get_title_count( instance, &ex );
+ catch_exception( &ex );
+ return result;
+}
+
- (void)setAudioTrack:(int)value
{
- libvlc_audio_set_track( instance, value, NULL );
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ libvlc_audio_set_track( instance, value, &ex );
+ catch_exception( &ex );
}
-- (int)audioTrack
+- (int)currentAudioTrack
{
libvlc_exception_t ex;
libvlc_exception_init( &ex );
- (void)setAudioChannel:(int)value
{
- libvlc_audio_set_channel( instance, value, NULL );
+ libvlc_exception_t ex;
+ libvlc_exception_init( &ex );
+ libvlc_audio_set_channel( instance, value, &ex );
+ catch_exception( &ex );
}
- (int)audioChannel
libvlc_exception_t ex;
libvlc_exception_init( &ex );
libvlc_media_player_pause( (libvlc_media_player_t *)instance, &ex );
- catch_exception( &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);
}
- (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_exception_t ex;
libvlc_exception_init( &ex );
libvlc_media_player_stop((libvlc_media_player_t *)instance, &ex);
[self setRate: -rate];
}
+- (void)jumpBackward:(NSInteger)interval
+{
+ if( [self isSeekable] )
+ {
+ interval = interval * 1000000;
+ [self setTime: [VLCTime timeWithInt: ([[self time] intValue] - interval)]];
+ }
+}
+
+- (void)jumpForward:(NSInteger)interval
+{
+ if( [self isSeekable] )
+ {
+ interval = interval * 1000000;
+ [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];
- (void)mediaPlayerTimeChanged:(NSNumber *)newTime
{
[self willChangeValueForKey:@"time"];
+ [self willChangeValueForKey:@"remainingTime"];
[cachedTime release];
cachedTime = [[VLCTime timeWithNumber:newTime] 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"];
cachedState = [newState intValue];
[self didChangeValueForKey:@"state"];
}
+
@end