Sources/VLCMediaPlayer.m: Position getters and setters.
authorPierre d'Herbemont <pdherbemont@videolan.org>
Sat, 29 Dec 2007 02:45:41 +0000 (02:45 +0000)
committerPierre d'Herbemont <pdherbemont@videolan.org>
Sat, 29 Dec 2007 02:45:41 +0000 (02:45 +0000)
extras/MacOSX/Framework/Headers/Public/VLCMediaPlayer.h
extras/MacOSX/Framework/Sources/VLCMediaPlayer.m

index 1e12181..a684b9d 100644 (file)
@@ -24,6 +24,8 @@
 
 #import <Cocoa/Cocoa.h>
 #import "VLCMedia.h"
+#import "VLCVideoView.h"
+#import "VLCTime.h"
 
 /* Notification Messages */
 extern NSString * VLCMediaPlayerTimeChanged;
@@ -61,6 +63,8 @@ extern NSString *VLCMediaPlayerStateToString(VLCMediaPlayerState state);
     void *instance;            //  Internal
     VLCMedia *media;        //< Current media being played
     VLCTime *cachedTime;
+    VLCMediaPlayerState cachedState;
+    float position;
 }
 
 /* Initializers */
@@ -181,4 +185,11 @@ extern NSString *VLCMediaPlayerStateToString(VLCMediaPlayerState state);
  * \see VLCMediaState
  */
 - (VLCMediaPlayerState)state;
+
+/**
+ * Returns the receiver's position in the reading. 
+ * \return A number between 0 and 1. indicating the position
+ */
+- (float)position;
+- (void)setPosition:(float)newPosition;
 @end
index 39851a8..7a02d72 100644 (file)
 NSString *VLCMediaPlayerTimeChanged   = @"VLCMediaPlayerTimeChanged";
 NSString *VLCMediaPlayerStateChanged  = @"VLCMediaPlayerStateChanged";
 
+NSString *VLCMediaPlayerStateToString(VLCMediaPlayerState state)
+{
+    static NSString *stateToStrings[] = {
+        [VLCMediaPlayerStateStopped]      = @"VLCMediaPlayerStateStopped",
+        [VLCMediaPlayerStateOpening]      = @"VLCMediaPlayerStateOpening",
+        [VLCMediaPlayerStateBuffering]    = @"VLCMediaPlayerStateBuffering",
+        [VLCMediaPlayerStateEnded]        = @"VLCMediaPlayerStateEnded",
+        [VLCMediaPlayerStateError]        = @"VLCMediaPlayerStateError",
+        [VLCMediaPlayerStatePlaying]      = @"VLCMediaPlayerStatePlaying",
+        [VLCMediaPlayerStatePaused]       = @"VLCMediaPlayerStatePaused"
+    };
+    return stateToStrings[state];
+}
+
 /* libvlc event callback */
 static void HandleMediaInstanceVolumeChanged(const libvlc_event_t *event, void *self)
 {
@@ -44,9 +58,10 @@ static void HandleMediaInstanceVolumeChanged(const libvlc_event_t *event, void *
 static void HandleMediaTimeChanged(const libvlc_event_t * event, void * self)
 {
     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+    NSLog(@"time!");
     [[VLCEventManager sharedManager] callOnMainThreadObject:self 
                                                  withMethod:@selector(mediaPlayerTimeChanged:) 
-                                       withArgumentAsObject:[NSNumber numberWithLongLong:event->u.media_instance_position_changed.new_position]];
+                                       withArgumentAsObject:[NSNumber numberWithLongLong:event->u.media_instance_time_changed.new_time]];
 
     [[VLCEventManager sharedManager] callOnMainThreadDelegateOfObject:self
                                                    withDelegateMethod:@selector(mediaPlayerTimeChanged:)
@@ -54,35 +69,61 @@ static void HandleMediaTimeChanged(const libvlc_event_t * event, void * self)
     [pool release];
 }
 
+static void HandleMediaPositionChanged(const libvlc_event_t * event, void * self)
+{
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
+    [[VLCEventManager sharedManager] callOnMainThreadObject:self 
+                                                 withMethod:@selector(mediaPlayerPositionChanged:) 
+                                       withArgumentAsObject:[NSNumber numberWithFloat:event->u.media_instance_position_changed.new_position]];
+    [pool release];
+}
+
 static void HandleMediaInstanceStateChanged(const libvlc_event_t *event, void *self)
 {
+    VLCMediaPlayerState newState;
+    
+    if( event->type == libvlc_MediaInstancePlayed )
+        newState = VLCMediaPlayerStatePlaying;
+    else if( event->type == libvlc_MediaInstancePaused )
+        newState = VLCMediaPlayerStatePaused;
+    else if( event->type == libvlc_MediaInstanceReachedEnd )
+        newState = VLCMediaPlayerStateStopped;
+    else
+    {
+        NSLog(@"%s: Unknown event", __FUNCTION__);
+        return;
+    }
+
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
+    [[VLCEventManager sharedManager] callOnMainThreadObject:self 
+                                                 withMethod:@selector(mediaPlayerStateChanged:) 
+                                       withArgumentAsObject:[NSNumber numberWithInt:newState]];
+
     [[VLCEventManager sharedManager] callOnMainThreadDelegateOfObject:self
                                                    withDelegateMethod:@selector(mediaPlayerStateChanged:)
                                                  withNotificationName:VLCMediaPlayerStateChanged];
-}
 
-NSString *VLCMediaPlayerStateToString(VLCMediaPlayerState state)
-{
-    static NSString *stateToStrings[] = {
-        [VLCMediaPlayerStateStopped]      = @"VLCMediaPlayerStateStopped",
-        [VLCMediaPlayerStateOpening]      = @"VLCMediaPlayerStateOpening",
-        [VLCMediaPlayerStateBuffering]    = @"VLCMediaPlayerStateBuffering",
-        [VLCMediaPlayerStateEnded]        = @"VLCMediaPlayerStateEnded",
-        [VLCMediaPlayerStateError]        = @"VLCMediaPlayerStateError",
-        [VLCMediaPlayerStatePlaying]      = @"VLCMediaPlayerStatePlaying",
-        [VLCMediaPlayerStatePaused]       = @"VLCMediaPlayerStatePaused"
-    };
-    return stateToStrings[state];
+    [pool release];
+
 }
 
+
 // TODO: Documentation
 @interface VLCMediaPlayer (Private)
 - (void)registerObservers;
 - (void)unregisterObservers;
 - (void)mediaPlayerTimeChanged:(NSNumber *)newTime;
+- (void)mediaPlayerPositionChanged:(NSNumber *)newTime;
+- (void)mediaPlayerStateChanged:(NSNumber *)newState;
 @end
 
 @implementation VLCMediaPlayer
++ (void)initialize {
+    [self setKeys:[NSArray arrayWithObject:@"state"] triggerChangeNotificationsForDependentKey:@"playing"];
+}
+
 - (id)init
 {
     return [self initWithVideoView:nil];
@@ -95,6 +136,9 @@ NSString *VLCMediaPlayerStateToString(VLCMediaPlayerState state)
         delegate = nil;
         media = nil;
         cachedTime = [[VLCTime nullTime] retain];
+        position = 0.0f;
+        cachedState = VLCMediaPlayerStateStopped;
+
         // Create a media instance, it doesn't matter what library we start off with
         // it will change depending on the media descriptor provided to the media
         // instance
@@ -110,14 +154,27 @@ NSString *VLCMediaPlayerStateToString(VLCMediaPlayerState state)
     return self;
 }
 
+- (void)release
+{
+    @synchronized(self)
+    {
+        if([self retainCount] <= 1)
+        {
+            /* We must make sure we won't receive new event after an upcoming dealloc
+             * We also may receive a -retain in some event callback that may occcur
+             * Before libvlc_event_detach. So this can't happen in dealloc */
+            [self unregisterObservers];
+        }
+        [super release];
+    }
+}
+
 - (void)dealloc
 {
     // 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;
 
-    // Next get rid of the event managers so we can stop trapping events
-    [self unregisterObservers];
     libvlc_media_instance_release((libvlc_media_instance_t *)instance);
     
     // Get rid of everything else
@@ -483,20 +540,18 @@ static const VLCMediaPlayerState libvlc_to_local_state[] =
 
 - (VLCMediaPlayerState)state
 {
-    // If there is no instance, assume that we're in a stopped state
-    if (!instance)
-        return VLCMediaPlayerStateStopped;
-    
+    return cachedState;
+}
+- (float)position
+{
+    return position;
+}
+- (void)setPosition:(float)newPosition
+{
     libvlc_exception_t ex;
     libvlc_exception_init( &ex );
-    libvlc_state_t libvlc_state = libvlc_media_instance_get_state( (libvlc_media_instance_t *)instance, &ex );
-    if (libvlc_exception_raised( &ex ))
-    {
-        libvlc_exception_clear( &ex );
-        return VLCMediaPlayerStateError;
-    }
-    else
-        return libvlc_to_local_state[libvlc_state];
+    libvlc_media_instance_set_position( instance, newPosition, &ex );
+    quit_on_exception( &ex );
 }
 @end
 
@@ -512,7 +567,8 @@ static const VLCMediaPlayerState libvlc_to_local_state[] =
     libvlc_event_attach( p_em, libvlc_MediaInstancePaused,          HandleMediaInstanceStateChanged, self, &ex );
     libvlc_event_attach( p_em, libvlc_MediaInstanceReachedEnd,      HandleMediaInstanceStateChanged, self, &ex );
     /* FIXME: We may want to turn that off when none is interested by that */
-    libvlc_event_attach( p_em, libvlc_MediaInstancePositionChanged, HandleMediaTimeChanged,            self, &ex );
+    libvlc_event_attach( p_em, libvlc_MediaInstancePositionChanged, HandleMediaPositionChanged,      self, &ex );
+    libvlc_event_attach( p_em, libvlc_MediaInstanceTimeChanged,     HandleMediaTimeChanged,          self, &ex );
     quit_on_exception( &ex );
 }
 
@@ -523,7 +579,9 @@ static const VLCMediaPlayerState libvlc_to_local_state[] =
     libvlc_event_detach( p_em, libvlc_MediaInstancePaused,          HandleMediaInstanceStateChanged, self, NULL );
     libvlc_event_detach( p_em, libvlc_MediaInstanceReachedEnd,      HandleMediaInstanceStateChanged, self, NULL );
     libvlc_event_detach( p_em, libvlc_MediaInstancePositionChanged, HandleMediaTimeChanged,            self, NULL );
+    libvlc_event_detach( p_em, libvlc_MediaInstanceTimeChanged,     HandleMediaTimeChanged,            self, NULL );
 }
+
 - (void)mediaPlayerTimeChanged:(NSNumber *)newTime
 {
     [self willChangeValueForKey:@"time"];
@@ -531,4 +589,20 @@ static const VLCMediaPlayerState libvlc_to_local_state[] =
     cachedTime = [[VLCTime timeWithNumber:newTime] retain];
     [self didChangeValueForKey:@"time"];
 }
+
+- (void)mediaPlayerPositionChanged:(NSNumber *)newPosition
+{
+    if( [newPosition floatValue] - position < 0.005 && position - [newPosition floatValue] < 0.005 )
+        return; /* Forget that, this is too much precision for our uses */
+    [self willChangeValueForKey:@"position"];
+    position = ((float)((int)([newPosition floatValue]*1000)))/1000.;
+    [self didChangeValueForKey:@"position"];
+}
+
+- (void)mediaPlayerStateChanged:(NSNumber *)newState
+{
+    [self willChangeValueForKey:@"state"];
+    cachedState = [newState intValue];
+    [self didChangeValueForKey:@"state"];
+}
 @end