]> git.sesse.net Git - vlc/blobdiff - projects/macosx/framework/Sources/VLCMediaPlayer.m
osx/framework: don't interfere with the NSCell API and fail gracefully if pausing...
[vlc] / projects / macosx / framework / Sources / VLCMediaPlayer.m
index a386b629b71bb169257e5fc26f8f3e85fc35adef..8f887a5acb5c171e167ed5d768a98ec2ba62391e 100644 (file)
@@ -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 <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
@@ -192,15 +194,23 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
 
 - (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];
 }
@@ -250,7 +260,10 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
 
 - (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
@@ -264,7 +277,10 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
 
 - (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)videoSubTitles
@@ -278,7 +294,10 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
 
 - (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
@@ -292,7 +311,10 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
 
 - (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
@@ -304,9 +326,28 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
     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
@@ -325,7 +366,7 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
     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
@@ -368,12 +409,31 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
     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 );
@@ -391,9 +451,54 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
     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)setTitle:(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
@@ -416,7 +521,10 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
 
 - (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
@@ -475,21 +583,17 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
     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);
@@ -516,6 +620,64 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
     [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];
@@ -652,9 +814,11 @@ static const VLCMediaPlayerState libvlc_to_local_state[] =
 - (void)mediaPlayerTimeChanged:(NSNumber *)newTime
 {
     [self willChangeValueForKey:@"time"];
+    [self willChangeValueForKey:@"remainingTime"];
     [cachedTime release];
     cachedTime = [[VLCTime timeWithNumber:newTime] retain];
 
+    [self didChangeValueForKey:@"remainingTime"];
     [self didChangeValueForKey:@"time"];
 }