views:

1317

answers:

4

In MonoTouch, we ran into this problem with the Movie Player sample in that it would only play the video once, but would not play it a second time.

I am asking this question to post an answer, since it has been hitting various folks.

+6  A: 

MPMoviePlayerController is a singleton underneath the hood. If you have not properly release'd (ObjC) or Dispose()'d (MonoTouch) and you create a second instance, it will either not play, or play audio only.

Additionally if you subscribe to MPMoviePlayerScalingModeDidChangeNotification or MPMoviePlayerPlaybackDidFinishNotification or MPMoviePlayerContentPreloadDidFinishNotification, be warned that the posted NSNotification takes a reference to the MPMoviePlayerController as well, so if you keep it around, you will have a reference the player.

Although Mono's Garbage Collector will eventually kick-in, this is a case where deterministic termination is wanted (you want the reference gone now, not gone when the GC decides to perform a collection).

This is why you want to call the Dispose () method on the controller, and the Dispose() method on the notification.

For example:

// Deterministic termination, do not wait for the GC
if (moviePlayer != null){
    moviePlayer.Dispose ()
    moviePlayer = null;
}

If you were listening to notifications, call Dispose in your notification handler at the end, to release the reference that it keeps to your MPMoviePlayerController for example:

var center = NSNotificationCenter.DefaultCenter;
center.AddObserver (
    "MPMoviePlayerPlaybackDidFinishNotification"),
    (notify) => { Console.WriteLine ("Done!"); notify.Dispose (); });
Geoff Norton
A: 

This is a valuable answer, but it doesn't solve my problem yet. The effect of disposing the player is that it completely dissapears, the aspect of your app switches back to portrait. If you start the player again, it comes back, aspect switches to landscape and the video plays. The effect is not pretty. I use videos of Dutch Sign Language that are only about a few seconds long. If you want to see what the Sign is exactly like, you need to see it at least three times in a row. I would want the re-start to be as smooth as possible. Hope there is a solution for that.

Richard
A: 

The secret lays in the endPlay with setting the: moviePlayer.initialPlaybackTime = -1; before releasing it. Try it out : :)

-(void)playMovie:(NSString *)urlString{ movieURL = [NSURL URLWithString:urlString]; moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:movieURL]; moviePlayer.initialPlaybackTime = 0; //Register to receive a notification when the movie has finished playing. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(endPlay:) name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer];

moviePlayer.scalingMode = MPMovieScalingModeAspectFit; 
moviePlayer.movieControlMode = MPMovieControlModeDefault;
moviePlayer.backgroundColor = [UIColor blackColor];

[moviePlayer play];

}

-(void)endPlay: (NSNotification*)notification{ [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer]; moviePlayer.initialPlaybackTime = -1; [moviePlayer stop]; [moviePlayer release]; }

Tiger
A: 

Can't see your code Nir and I don't have edit privileges so here it is again:

The secret lays in the endPlay with setting the: moviePlayer.initialPlaybackTime = -1; before releasing it. Try it out : :)

-(void)playMovie:(NSString *)urlString{ movieURL = [NSURL URLWithString:urlString];          
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];    
moviePlayer.initialPlaybackTime = 0; 
//Register to receive a notification when the movie has finished playing. 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(endPlay:) name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer];

moviePlayer.scalingMode = MPMovieScalingModeAspectFit; 
moviePlayer.movieControlMode = MPMovieControlModeDefault;
moviePlayer.backgroundColor = [UIColor blackColor];

[moviePlayer play];

}

-(void)endPlay: (NSNotification*)notification{
 [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer]; 
moviePlayer.initialPlaybackTime = -1; 
[moviePlayer stop]; 
[moviePlayer release]; 
} 
Bryan