MPMoviePlayerViewController play movie from Documents directory - objective-c - iphone

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.

Related

Is there a way to force an AVPlayer audio stream to always play live with limited buffering?

I am creating an app that will stream audio live from an internet radio stream.
I am using AVPLayer and create an AVAudioSession, etc, etc...
Everything works fine, except... there is no [stop] function with AVPlayer, only [play] and [pause]. So when a user pauses the stream, it buffers and when they click play, it starts where it left off when they pressed pause before.
The question... Is there a way to force the audio stream to always play live?
I really don't want any buffering more than a few seconds...
Thank you for your help!
If you don't want buffering then try to play streaming live audio via MPMovieviewcontroller.
It is perfect player for live streaming audio/video. I am also use this player in one of my
App for play live audio streaming. I think your all requirement match with this. Try to imple
ment it. It is easy to implement also.Here is my code to play stream audio using
MPMovieviewcontroller:
NSURL *fileURL=[NSURL URLWithString:geturl];
NSLog(#"fileURL..%#",fileURL);
moviePlayerController = [[MPMoviePlayerViewController alloc] initWithContentURL:fileURL];
[moviePlayerController.moviePlayer prepareToPlay];
moviePlayerController.moviePlayer.shouldAutoplay=YES;
moviePlayerController.view.frame = self.view.frame;
[self presentMoviePlayerViewControllerAnimated:moviePlayerController];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(MPMoviePlayerDidExitFullscreen:) name:MPMoviePlayerDidExitFullscreenNotification object:nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
[moviePlayerController.moviePlayer play];
- (void)MPMoviePlayerDidExitFullscreen:(NSNotification *)notification
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerDidExitFullscreenNotification
object:nil];
[moviePlayerController.moviePlayer stop];
MPMoviePlayerController *player = [notification object];
[[NSNotificationCenter defaultCenter]
removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
[moviePlayerController dismissMoviePlayerViewControllerAnimated];
}
And for background playing I add these lines in my info.plist. You also add these to plist:

MPMoviePlayerController ends immediately

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];

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.