MPMoviePlayerController ends immediately - iphone

I'm trying to load a 25-second mp4 movie from my resource file, but when I play it, my MPMoviePlayerPlaybackDidFinishNotification selector is called immediately with MPMovieFinishReasonPlaybackEnded. When I log my playback state it shows this:
MPMoviePlaybackStatePlaying
MPMoviePlaybackStatePaused
MPMoviePlaybackStateStopped
MovieFinishReasonPlaybackEnded
MPMoviePlaybackStatePlaying
MPMoviePlaybackStatePaused
even though I only call the play method once. I hope someone can help me.
-- Edited to show my code:
MPMoviePlayerController* player = [[[MPMoviePlayerController alloc] initWithContentURL:movieURL] autorelease];
if (player)
{
self.moviePlayerController = player;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayerPlaybackStateDidChange:)
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:player];
player.contentURL = movieURL;
player.movieSourceType = MPMovieSourceTypeFile;
player.controlStyle = MPMovieControlStyleNone;
player.fullscreen = YES;
switch (orientation) {
case UIInterfaceOrientationLandscapeLeft:
player.view.transform = CGAffineTransformMakeRotation(90.0f * (M_PI / 180.0f));
break;
case UIInterfaceOrientationLandscapeRight:
player.view.transform = CGAffineTransformMakeRotation(-90.0f * (M_PI / 180.0f));
break;
default:
break;
}
player.view.frame = self.view.bounds;
[self.view addSubview:player.view];
}
[self.moviePlayerController play]

Is self.moviePlayerController a retained property? If not, the MPMoviePlayerController instance will be released very quickly (by the autorelease), and you might get similar behaviour.

Without having any more of your code to look at, I would suggest trying to play another file that you know can play. For example, grab the movie from this sample project: http://developer.apple.com/library/ios/#samplecode/MoviePlayer_iPhone/Introduction/Intro.html and see if it plays.
I had something similar happen to me when I was trying to play a file that wasn't properly formatted.
Hmm... I don't see what's wrong. Are you sure that movieURL is correct? How do you get it?
For the record, here is how I present movies, although it wouldn't have quite the same effect as what you're doing.
NSString *path = [[NSBundle mainBundle] pathForResource:movieFileName ofType:#"m4v"];
// If path is NULL (the resource does not exist) return to avoid crash
if (path == NULL)
return;
NSURL *url = [NSURL fileURLWithPath:path];
MPMoviePlayerViewController *mpViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
mpViewController.moviePlayer.controlStyle = MPMovieControlStyleFullscreen;
mpViewController.moviePlayer.shouldAutoplay = YES;
// NOTE: This can sometimes crash the app in the Simulator. This is a known bug
// in xcode: http://stackoverflow.com/a/8317546/472344
[self presentMoviePlayerViewControllerAnimated:mpViewController];
[mpViewController release];

Related

Buffering label in a stream using MPMoviePlayer

Im making a radio streaming application, my app is working perfectly. I have two buttons in my screen one for playing and the other for pausing, also I have a label that indicates the state of my player. I have no problem making this label show the state "Playing" or "Paused" my problem is that when I press the play button there is a time where the buffer is gathering information and I can't figure out a way to show a "Buffering..." label before the player start to stream the audio.
This is the code Im using for streaming the radio station.
NSString *url = [NSString stringWithFormat:#"http://66.7.218:8816"];
player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:url]];
player.movieSourceType = MPMovieSourceTypeStreaming;
player.view.hidden = YES;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance]setActive:YES error:nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[player prepareToPlay];
[player play];
Im usin a function I created called changeStatus and this function is called each second to identify the status of the player.
-(void)changeStatus
{
if (player.loadState == MPMovieLoadStateUnknown) {
status.text = #"Buffering...";
}
if(player.playbackState == MPMoviePlaybackStatePlaying)
{
status.text = #"Playing.";
}
if(player.playbackState == MPMoviePlaybackStatePaused)
{
status.text = #"Paused";
}
}
I really need to solve this problem and Ive tried all I can to solve it. Hope you can help me! Thanks in advance.
I achieved to solve the problem. The part that was missing is the if clause which gives the signal to start playing only when the player is prepared to play. Without that the player starts to play before the buffer is completely loaded so it plays no audio. And that was the reason my Playing label showed immediately instead of the buffering one.
NSString *url = [NSString stringWithFormat:#"http://66.7.218:8816"];
player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:url]];
player.movieSourceType = MPMovieSourceTypeStreaming;
player.view.hidden = YES;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance]setActive:YES error:nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[player prepareToPlay];
if(player.isPreparedToPlay)
{
[player play];
}
Adittionally, the MPMoviePlaybackStateInterrupted refers to the buffering process while doing an stream. So if you want to make something happens in the buffering process refer to this method.
-(void)changeStatus
{
if(player.playbackState == MPMoviePlaybackStatePlaying)
{
status.text = #"Playing.";
}
if(player.playbackState == MPMoviePlaybackStateInterrupted)
{
status.text = #"Buffering...";
}
}
Thanks a lot to the user That Guy who helped me solving this.
Actually there's a notification called
MPMediaPlaybackIsPreparedToPlayDidChangeNotification
The observer will get notified after it is ready to play. It is more or less the same effect but with different mechanism.

MPMoviePlayerViewController play movie from Documents directory - objective-c

I have subfolder called "Video" in Documents folder. And there is somevideo.mp4 file. I have full path to this file but MPMoviePlayerViewController doesn't want to play video from local. Here is code:
NSString *path = [[self getVideoFolderPath] stringByAppendingPathComponent:#"somevideo.mp4"];
NSURL *fURL = [NSURL fileURLWithPath:path];
MPMoviePlayerViewController *videoPlayerView = [[MPMoviePlayerViewController alloc] initWithContentURL:fURL];
[self presentMoviePlayerViewControllerAnimated:videoPlayerView];
[videoPlayerView.moviePlayer play];
It doesn't play. Appears white screen and nothing else. This code works with remote video, when i put URL to website with video file, but local doesn't play. How to get correct file path to video file?
Are you using iOS prior to 4.3? If so, you need to do this
[videoPlayerView setContentURL: fURL];
Here is a snippet of code from where I play video from the documents folder. One of the things I would recommend is to avoid some of the autorelease objects. Especially on NSURL when you have viewcontrollers. I know it should be safe but I've never found it to be 100%
if ( [[NSFileManager defaultManager] fileExistsAtPath:fullpathVideoFile] == NO )
{
NSLog(#"No video file found");
return self;
}
playbackURL = [[NSURL alloc] initFileURLWithPath:fullpathVideoFile isDirectory:NO];
if ( playbackURL == nil )
{
NSLog(#"playbackURL == nil");
return self;
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerLoadedMovie:) name:#"MPMoviePlayerLoadStateDidChangeNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerStartedMovie:) name:#"MPMoviePlayerNowPlayingMovieDidChangeNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerFinishedMovie:) name:#"MPMoviePlayerPlaybackDidFinishNotification" object:nil];
[self setContentURL:playbackURL];
In my case, I created a subclass of MPMoviePlayerController (as I generally do with all view controllers) so the references to 'self' would be to the MPMoviePlayerController object instance
Strange. The code you put seems to be correct. Make sure the path to the audio you are trying to retrieve isn't broken.

How to expose class members or how to implement method acting on those members

I am trying to stop a sound from another class.
As soon as the application opens the sound starts to play and is set to play on a loop unless the 'User' changes the settings and turns sound to OFF.
This works but only on start up of the application where it checks to see if the settings sound is set to 'ON/OFF' but I would like if it would do it when changed in the settings.
This is what I have so far...
FirstClass
// grab the path to the caf file
NSString *soundFilePath =
[[NSBundle mainBundle] pathForResource: #"Menu_Loop"
ofType: #"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
// create a new AVAudioPlayer initialized with the URL to the file
AVAudioPlayer *newPlayer =
[[AVAudioPlayer alloc] initWithContentsOfURL: fileURL
error: nil];
[fileURL release];
// set our ivar equal to the new player
self.player = newPlayer;
[newPlayer release];
// preloads buffers, gets ready to play
[player prepareToPlay];
player.numberOfLoops = -1; // Loop indefinately
if ([SoundSwitch isEqualToString:#"1"]){
[self.player play]; // Plays the sound
}else{
[self.player stop]; // Stops the sound
}
This plays the sound.
and if I wanted to stop it simply:
[self.player stop]
But this only works in the same class how would I get it to work in another?
I would use NSNotifications, so that you can send stop or play notifications from anywhere in your application. This is how you do it:
in your init method for FirstClass do this:
//Notification for stoping
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(stop) name:#"StopSound" object:nil];
//Notification for playing
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(play) name:#"PlaySound" object:nil];
Now create those two methods from the selectors (stop method and play method)
-(void)stop{
[self.player stop]
}
-(void)play{
[self.player play]
}
in the dealloc remember to remove the notification observers:
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"StopSound" object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"PlaySound" object:nil];
Now from anywhere in your application just send the notification to stop or play the sound
//Stop
[[NSNotificationCenter defaultCenter] postNotificationName:#"StopSound" object:nil];
//Play
[[NSNotificationCenter defaultCenter] postNotificationName:#"PlaySound" object:nil];
I will shoot here in a dark as I don't know those apple stuff but I think you have to create instance of AVAudioPlayer where you want to manipulate your sound from. If this class you presented is accessible in a second place you want to play/stop sound maybe you could expose your 'player' member to external use? or what could be better you can add to this class methods PlaySound(), StopSound() and by them allow external code to play sounds.
Sample code with a little help from google :)
- (void)playSound:{
[self.player play];
}
- (void)stopSound:{
[self.player stop];
}
and now you can invoke playSound and stopSound methods from outside of your class

How to play animation/movie instead of iPhone splash screen?

I want to play an animation(Gif) or a movie instead of Default.png. Is that possible? I tried what is described in this blog :http://www.cuppadev.co.uk/iphone/playing-animated-gifs-on-the-iphone/ but I don't know how to play a Gif animation instead of Default.png
If you're asking about a sanctioned App Store app, then no, you can't use anything but a static Default.png.
If you're writing an app for jailbroken phone, this may be possible (but I don't know).
The Following code should come in
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
NSBundle *bundle = [NSBundle mainBundle];
if(bundle != nil)
{
NSString *videoPath = [bundle pathForResource:#"trail_video" ofType:#"mp4"];
if (moviePath)
{
videoURL = [NSURL fileURLWithPath:moviePath];
}
}
theMovie = [[MPMoviePlayerViewController alloc] initWithContentURL:videoURL];
theMovie.moviePlayer.controlStyle = MPMovieControlStyleNone;
theMovie.moviePlayer.scalingMode = MPMovieScalingModeFill;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayerDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:theMovie.moviePlayer];
[theMovie.moviePlayer setFullscreen:YES animated:NO];
[theMovie.moviePlayer prepareToPlay];
[theMovie.moviePlayer play];
window.rootViewController = theMovie;
[self.window.rootViewController.view bringSubviewToFront:mMoviePlayer.moviePlayer.view];
In the moviePlayerDidFinish method load the screen which you desire to load.
Unfortunately, it's impossible to do it on the latest iPhone OS. A trick using symbolic link is currently blocked by OS.

MPMoviePlayerController play video second time

I need to have the possibility to play more than one video in an app.
Unfortunately, the second time I press play, video appears blinking.
I use only this code for playing vide
NSURL *url = [[[NSURL alloc]initFileURLWithPath:[[NSBundle mainBundle]pathForResource:#"Movie" ofType:#"m4v"]] autorelease];
MPMoviePlayerController *mp = [[MPMoviePlayerController alloc]initWithContentURL:url];
mp.movieControlMode = MPMovieControlModeDefault;
[mp play];
moviePlayer = mp;
[mp release];
Can anyone tell me where can be the problem?
Thanks in advance!
UPDATE 1: It seems that the Apple MoviePlayer example has the same problem.
you can also do it by setting the initial playback time to -1.0 before calling the play function
mp.initialPlaybackTime = -1.0;
Put this code before ur play method is called.
I had this problem and solved it by using the notification system to execute a callback after the MPMoviePlayerController finishes playing, and releasing the player object there.
Add a notification before you play the movie:
NSURL *url = [[[NSURL alloc]initFileURLWithPath:[[NSBundle mainBundle]pathForResource:#"Movie" ofType:#"m4v"]] autorelease];
MPMoviePlayerController *mp = [[MPMoviePlayerController alloc]initWithContentURL:url];
mp.movieControlMode = MPMovieControlModeDefault;
//***Add this line***
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(myMovieFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:mp];
[mp play];
Then add the callback method,
-(void)myMovieFinished:(NSNotification*)aNotification
{
MPMoviePlayerController *moviePlayer = [aNotification object];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerDidFinishNotification object:moviePlayer];
[moviePlayer release];
}
It seams that the only solution is... to make the app for 3.1
I also find run on the OS 3.1 or later version of simulator can be played well.It won't appears blinking.But when I add
initialPlaybackTime = -1.0
it will also play well on OS 3.0.