How to rotate MPMoviePlayerController video but not for its superview - iphone

My MPMoviePlayerController view is added as a subview to another view controller's view. When I play the video in full screen and flip the simulator, the video does not flip, nor does the parent view. However, when I add return YES to the rotation method (check codes below), the video rotates when it is in full screen as I wanted, but the parent view also rotates, which I don't want, because I did not design a landscape view for the parent view. How can I allow rotation ONLY for the video when it is in full screen and not the parent view??
Here are the codes I used:
For the video:
- (void)viewDidAppear:(BOOL)animated {
NSBundle *bundle=[NSBundle mainBundle];
NSString *moviePath = [bundle pathForResource:#"MainPageMovie" ofType:#"mp4"];
NSURL *movieURL=[[NSURL fileURLWithPath:moviePath] retain];
MPMoviePlayerController *theMovie = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
theMovie.scalingMode = MPMovieScalingModeAspectFill;
theMovie.view.frame = CGRectMake(115.0, 156.0, 200.0, 150.0);
[self.view addSubview:theMovie.view];
[theMovie play];
[super viewDidLoad];
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
}
And for the rotation method:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return YES;
}

A simple way would be to use MPMoviePlayerViewController to display the movie. Being a separate view controller, this should handle rotation for you.
If you really want to do it by adding an MPMoviePlayerController as a subview, you have a more difficult task ahead of you. Basically, you would have to listen for UIDeviceOrientationDidChangeNotification and apply the appropriate transform, bounds, and center to the movie player view depending on the device's orientation.

Related

iPhone app : MPMoviePlayer: PlayVideo in Landscape mode only

I have an iPhone app which runs in portrait mode only. But I want to make mpmovieplayer to play video in landscape mode only.
How can I achieve that?
Here is the code.
NSString *path = [[NSBundle mainBundle] pathForResource:lblVideoName.text ofType:#"mp4" inDirectory:nil];
NSURL *url = [[NSURL alloc] initFileURLWithPath:path];
NSLog(#"URL== %#",url);
moviePlayer = [[MPMoviePlayerController alloc]
initWithContentURL:url];
moviePlayer.controlStyle = MPMovieControlStyleDefault;
moviePlayer.shouldAutoplay = YES;
[self.view addSubview:moviePlayer.view];
[moviePlayer setFullscreen:YES animated:YES];
You can present the movie in it's own view controller that's setup for landscape.
// in the VC where the user indicates he wants to see a movie...
- (void)startTheMovie {
// run a storyboard segue with a modal transition, or ...
MyMovieVC *movieVC = [[MyMovieVC alloc] initWithNibName:#"MyMovieVC" bundle:nil];
[self presentModalViewController:movieVC animated:YES];
}
// in MyMovieVC
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) ||
(interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
// and the code that you wrote on view will appear
You can include a dismiss button in this interface, or, the youtube way is to have it dismiss itself. You can do that by subscribing to the finished notification:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayerFinished:)
name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
then, on the finished message
- (void)moviePlayerFinished:(NSNotification*)notification {
[self dismissModalViewControllerAnimated:YES];
}
Note, if you're doing this in a tabbed interface, all the tabs - even the ones not visible - need to agree to let the interface turn landscape. This makes some sense but has caused me heartache in the past. I don't have a pretty solution to this. My approach has been a publicly accessible BOOL isLandscapeOK on my AppDelegate. This MovieVC would set it to YES, and the other tab VCs would answer portrait or landscape if isLandscapeOK==YES.

Trouble presenting MPMoviePlayerViewController, or MoviePlayerController in fullscreen

I'm trying to create a movie to play when my app starts up. The first view Controller is a UITabBarController. In the code for the view controller for the first tab, is where I put my movie. This dummy code works (setting the frame to be smaller than the full screen and just showing the video):
- (void)PlayOpeningMovie {
NSString *filepath = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"m4v"];
NSURL *fileURL = [NSURL fileURLWithPath:filepath];
MPMoviePlayerController *moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
// MPMoviePlayerViewController *moviePlayerController = [[MPMoviePlayerViewController alloc] initWithContentURL:fileURL];
[moviePlayerController.view setFrame:CGRectMake(120, 120, 300, 200)];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlaybackComplete:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayerController];
[self.view addSubview:moviePlayerController.view];
// [moviePlayerController setFullscreen:YES];
// [self presentMoviePlayerViewControllerAnimated:moviePlayerController];
[moviePlayerController play];
// [[moviePlayerController moviePlayer] play];
}
However, if I switch it around, comment out the setFrame method, and use the fullscreen property, I do not see the movie.
I was also playing around with creating a MPMovieplayerViewController and presenting that modally with the method for the MPMoviePlayerViewControllers, but it never gets presented and I can't figure out why. I tried creating a dummy viewController with a yellow background as well, and presenting that modally and that does not work either.
I have tried adding a dummy UIView to the screen, and that works.
So for some reason, I can get small UIViews/MPMoviePlayers to show with addSubview. I cannot get the presentModal__ to work. I cannot get fullscreen mode to work for the MoviePlayerController. I'm really stumped as to why I cannot present modally from this view. Thanks.
[moviePlayerController setControlStyle:MPMovieControlStyleFullscreen];
[moviePlayerController setFullscreen:YES];
Just add this two lines to present it in full screen.

MPMoviePlayerController : orientation problem

finally I have to post my problem here. Yes it could be duplicate question here as I have referred many answers regarding to this question.But I could not find any fix. (Also didn't find any question regarding to tab-bar app specific so...) And I don't want to use MPMoviePlayerViewController
I have tab-bar application. In last tab's VC there is a button. On click event I want to start movie player. For that I am using MPMoviePlayerController. Its all fine when orientation is Portrait . But regarding to changes, now I have to play it in landscape mode only.
here is my code :
-(void)playMovie
{
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
[self.scrollView addSubview:moviePlayer.view];
[moviePlayer play];
[moviePlayer setFullscreen:TRUE];
}
-(void)btnPlayHandler:(id)sender
{
NSLog(#"btnPlayHandler");
NSURL * videoUrl = [NSURL URLWithString:[NSString stringWithFormat:#"%#",[dictResponse valueForKey:#"VideoPath"]]];
moviePlayer = [[MPMoviePlayerController alloc]initWithContentURL:videoUrl];
//[moviePlayer.view setFrame:CGRectMake(20, 40, 280, 222)];
moviePlayer.fullscreen = YES ;
moviePlayer.shouldAutoplay = NO ;
[self performSelector:#selector(playMovie) withObject:nil afterDelay:1];
}
- (void) movieWillExit:(NSNotification *)notification
{
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
}
- (void) movieExit:(NSNotification *)notification
{
[moviePlayer stop];
[moviePlayer.view removeFromSuperview];
moviePlayer = nil ;
[btnPlay setHidden:FALSE];
}
- (void)moviePreLoad:(NSNotification *)notification
{
NSLog(#"moviePreLoad");
}
- (void)moviePlaybackComplete:(NSNotification *)notification
{
NSLog(#"moviePlaybackComplete");
[btnPlay setHidden:FALSE];
}
Only device's orientation is changed not player's view ! How to accomplish this ??? Is it because the tab-bar application ?
You are making the window landscape, but as you have set the MPMoviePlayer view in scrollview, it is not rotating. try to rotate the scrollview according to your orientation.
See this link http://blog.sallarp.com/shouldautorotatetointerfaceorientation/. Hopefully it will solve your problem.

Flipping a Video Horizontally in Xcode

I have a video such that when I play it in full view and flip the simulator horizontally the video would not flip. How can I make the video flip according to the iPhone's accelerometer?
Here is the code for the video if it helps:
- (void)viewDidAppear:(BOOL)animated {
NSBundle *bundle=[NSBundle mainBundle];
NSString *moviePath = [bundle pathForResource:#"MainPageMovie" ofType:#"mp4"];
NSURL *movieURL=[[NSURL fileURLWithPath:moviePath] retain];
MPMoviePlayerController *theMovie = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
theMovie.scalingMode = MPMovieScalingModeAspectFill;
theMovie.view.frame = CGRectMake(115.0, 156.0, 200.0, 150.0);
[self.view addSubview:theMovie.view];
[theMovie play];
[super viewDidLoad];
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
}
Your MPMoviePlayerController view is added as a subview to another view controller's view. In that parent view controller, have you overridden shouldAutorotateToInterfaceOrientation method?
If you are just looking for landscape (horizontal) rotation, you can have your code as below:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return ((interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (interfaceOrientation == UIInterfaceOrientationLandscapeRight));
}
In order to rotate specific subviews of the larger view controller view, (which in your situation would be the case with only rotating the video), you'd have to do CGAffineTransforms. This would allow you to resize a view, rotate it, etc. AFAIK, this is probably the best route to go for rotating a single view.
However, you may want to research more into MPMoviePlayerViewController. Take a look at this post, it seems to address your problem.

MPMoviePlayerController switching movies causes white flash

I have a small UIView that displays a repeated movie. When the user taps a button another movie is loaded and displayed in the same UIView.
The problem is that there is a half second "flash" between the removing of the first movie and the displaying of the second. Is there any to remove this?
- (void) setUpMovie:(NSString*)title {
NSString *url = [[NSBundle mainBundle] pathForResource:title ofType:#"mp4"];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:url]];
[[player view] setFrame:self.movieView.bounds];
[self.movieView addSubview:player.view];
if ([title isEqualToString:#"Bo_idle_02"]) {
[player setRepeatMode:MPMovieRepeatModeOne];
} else {
[player setRepeatMode:MPMovieRepeatModeNone];
}
[player setControlStyle:MPMovieControlStyleNone];
[player play];
}
- (void) startDanceAnimation { [self setUpMovie:#"Bo_dance_02"]; return; }
I managed to get my movies changing without the white flash using the AVFoundation as suggested previously. sudo code below, hope it helps someone :)
Apples reference docs can be found here and I used them to get most of my information:
http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/00_Introduction.html#//apple_ref/doc/uid/TP40010188-CH1-SW3
The first thing I did was to add the following class, called PlayerView (can't remember where I got it sorry) to my project. Its a subclass of UIView and its the view that the movie will be displayed in. Once you add it to your project open UI Builder, add a new view to an existing xib and change its class to PlayerView. Connect this using an IBOutlet. Again remember this is the view that will display the movie.
PlayerView.h
#import
#import
#import
#interface PlayerView : UIView {
AVPlayer *player;
}
#property (nonatomic,retain) AVPlayer *player;
#end
PlayerView.m
#import "PlayerView.h"
#implementation PlayerView
#synthesize player;
+ (Class)layerClass {
return [AVPlayerLayer class];
}
- (AVPlayer*)player {
return [(AVPlayerLayer *)[self layer] player];
}
- (void)setPlayer:(AVPlayer *)player {
[(AVPlayerLayer *)[self layer] setPlayer:player];
}
- (void) dealloc {
[super dealloc];
[player release];
}
#end
In the ViewContoller that displays the movies I have the following:
DisplayMovies.h
#import
#import
#class PlayerView;
#interface DisplayMovies : UIViewController {
IBOutlet AVPlayer *player;
AVPlayerItem *movieOneItem;
AVPlayerItem *movieTwoItem;
}
#property (nonatomic, retain) AVPlayer *player;
#property (retain) AVPlayerItem *movieOneItem;
#property (retain) AVPlayerItem *movieTwoItem;
DisplayMovies.m
#implementation DisplayMovies
#synthesize player, movieOneItem, movieTwoItem;
- (void)viewDidLoad {
// load the two movies
NSURL *movieOneItemURL = [[NSBundle mainBundle] URLForResource:#"movieOne" withExtension:#"mp4"];
AVURLAsset *movieOneItemAsset = [AVURLAsset URLAssetWithURL:movieOneItemURL options:nil];
self.movieOneItem = [AVPlayerItem playerItemWithAsset:movieOneItemAsset];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieOneItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:self.movieOneItem];
NSURL *movieTwoItemURL = [[NSBundle mainBundle] URLForResource:#"movieTwo" withExtension:#"mp4"];
AVURLAsset *movieTwoItemAsset = [AVURLAsset URLAssetWithURL:movieTwoItemURL options:nil];
self.movieTwoItem = [AVPlayerItem playerItemWithAsset:movieTwoItemAsset];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieTwoItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:self.movieTwoItem];
[self.player play];
}
- (void) movieOneItemDidReachEnd:(NSNotification*)notification {
// play movie two once movie one finishes
[self.player seekToTime:kCMTimeZero];
[self.player replaceCurrentItemWithPlayerItem:self.movieTwoItem];
[self.player play];
}
- (void) movieTwoItemDidReachEnd:(NSNotification*)notification {
// play movie one once movie two finishes
[self.player seekToTime:kCMTimeZero];
[self.player replaceCurrentItemWithPlayerItem:self.movieOneItem];
[self.player play];
}
The solution posted above didn't work for me. I was still getting short flashes between tracks. I was able to solve the problem by creating two views each with its own AVPlayer. I set them both playing and then switch between them by hiding the top view. This got rid of the flash, and I was able to animate a transition between the two tracks by hiding the top view by setting its alpha to 0.0 instead of using setHidden. Here is my code:
AVPlayerItem *theAsset = [self generatePlaylistAssetWithVideoOne]; //In my app this returns an AVPlayer Item
layerView1 = [[VideoLayerView alloc] initWithFrame:CGRectMake(-50, 0, 580, 320)]; //VideoLayerView is a subclass of UIView with the video layer stuff added in.
[layerView1 setPlayer:thePlayer];
[thePlayer play];
[self.view addSubview:layerView1];
AVPlayerItem *theAsset2 = [self generatePlaylistAssetWithVideoTwo];
[thePlayer2 setActionAtItemEnd:AVPlayerActionAtItemEndNone];
layerView2 = [[VideoLayerView alloc] initWithFrame:CGRectMake(-50, 0, 580, 320)];
[layerView2 setPlayer:thePlayer2];
[thePlayer2 play];
[self.view addSubview:layerView2];
Then to animate between the videos I used:
if (water) //Water is a BOOL set up earlier in the file
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
///DO STUFF
[layerView2 setAlpha:0];
[UIView commitAnimations];
water = NO;
}
else
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
///DO STUFF
[layerView2 setAlpha:1.0];
[UIView commitAnimations];
water = YES;
}
To change the videos, you just need to set the hidden view to start playing what you want and then do the switch after the flash.
I still have to come back to this project but I have received some more advice. I will be back working on this project in hopefully two weeks so I will let ye know which solution worked (fingers crossed) for me. In the mean time here's my options:
1.
You won't be able to use MPMoviePlayerController to switch the movie without a flash.
As an alternative, you can use AV Foundation. The AVPlayer -replaceCurrentItemWithPlayerItem: method will seamlessly transition from the old player item to the new one without flashes.
For more information about programming with AV Foundation, see the "AV Foundation Programming Guide" which you can find here:
http://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/AVFoundationPG/
2.
You can merge all your movies into a single (large) movie, then use the MPMediaPlayback currentPlaybackTime / endPlaybackTime properties to "select" and play the desired movie (within the large movie). If you use this technique you'll also need to make sure there's a key frame at the point in time where the new movie starts.
3.
Alternately, create a single MPMoviePlayerController object, use the -setContentURL: to set the new movie URL, and take advantage of the backgroundView property to make a more seamless transition. The backgroundView is automatically sized with the view property, but it will be hidden before the movie is preloaded. You can put a black view behind both movie views, and then make the backgroundView's backgroundColor = black, which should make it appear more seamless.
Hope this helps.
Find solution here http://joris.kluivers.nl/blog/2010/01/04/mpmovieplayercontroller-handle-with-care/ from iOS 6 you need to use [self.moviePlayer prepareToPlay]; and catch MPMoviePlayerReadyForDisplayDidChangeNotification to use [self.moviePlayer play];