cocos2d: playing a video in the background of a menu - iphone

I have a a CCLayer with the start menu of my app and I would like to have a short movie playing in the background.
I have succeded in playing a movie in the glView but when it plays the menu is not depicted.
To handle the movie I instantiate a MPMoviePlayerController
and then I add its view to the glView this way:
[[[CCDirector sharedDirector] openGLView] addSubview:moviePlayer.view];
I have seen this question was quite similar
How to have a menu when a movie is playing-iphone cocos2d
but I would like to know if there is a better solution to it, possibly one that would let me still exploit the cocos2d framework entities (and not my own views).
I have tried to send the moviePlayer.view to back this way
[theView sendSubviewToBack:moviePlayer.view];
but the menu is stil hidden by the movie...
(many hours later..)
Ok as you can read in the first comment i have realized that (probably) the only way is exploiting custom views. I did that and it runs in the simulator by adding any views to the glView after the moviePlayer.view. However when i run it on my target IPod touch with a 3.1.3 FW the movie view is always on top.
I have therefore realized the MPMoviePlayerController actually creates its own window and its own view. Some post (like this Overlay on top of Streaming MPMoviePlayerController) suggest to intercept the event the new window is loaded and only then adding the subviews.
that is what I tried to do but that event is actually never catched neither on the simulator nor on the target Ipod.
I have therefore added a scheduled selector -(void) update which is implemented this way:
-(void) update{
NSArray *windows = [[UIApplication sharedApplication] windows];
if ([windows count] > 1)
{
UIImageView *logo = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"logo.png"]];
UIView *theView = [[CCDirector sharedDirector] openGLView];
[logo setCenter:ccp(240,80)];
[moviePlayer.view addSubview:logo];
[self unscheduleAllSelectors];
}
}
but the movie still remains on top
please guys any help would very appreciated!
(some days later...)
I have also waited for 2 seconds, while the movie is actually running, to add my logo view as a subview of the movieplayer. It works correctly on the simulator but on the Ipod (3.1.3) it turns out a different result. The first time the movie is played the logo is not depicted (movie on top). However, since as soon as the movie finishes the play method is colled, starting from the second time the logo is depicted with the movie on the background (Is i would). Does it make any sense to you?
I really need to understand how to fix this issue it is quite ridiculous I have succeded in developing a game in 2 months and now i am stuck from 2 weeks for the start menu :)
Anyway if I have decided to paste the whole code of the layer I am trying to fix so that you can better figure out what the problem is (or at least that is my hope :) )
+(id) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
StartMenu *layer = [StartMenu node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
-(void) update{
timer ++;
if (timer==120){
UIImageView *logo = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"stupidLogo.png"]];
UIView *theView = [[CCDirector sharedDirector] openGLView];
[logo setCenter:ccp(240,80)];
//logo.transform = CGAffineTransformMakeRotation(3.14/2);
[moviePlayer.view addSubview:logo];
[self unscheduleAllSelectors];
}
}
-(id) init{
self = [super init];
[self schedule: #selector(update)];
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"test_005_conv_06.mp4" ofType:#""]];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
// Register to receive a notification when the movie has finished playing.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
if ([moviePlayer respondsToSelector:#selector(view)]) {
if([MPMoviePlayerController instancesRespondToSelector:#selector(view)]){
// Use the new 3.2 style API
moviePlayer.controlStyle = MPMovieControlStyleNone;
moviePlayer.shouldAutoplay = FALSE;
// This does blows up in cocos2d, so we'll resize manually
// [moviePlayer setFullscreen:YES animated:YES];
[moviePlayer.view setTransform:CGAffineTransformMakeRotation((float)M_PI_2)];
CGSize winSize = [[CCDirector sharedDirector] winSize];
moviePlayer.view.frame = CGRectMake(0, 0, winSize.height, winSize.width); // width and height are swapped after rotation
[[[CCDirector sharedDirector] openGLView] addSubview:moviePlayer.view];
[moviePlayer play];
}
} else {
// Use the old 2.0 style API
moviePlayer.movieControlMode = MPMovieControlModeHidden;
[moviePlayer play];
}
return self;
}
- (void)moviePlayBackDidFinish:(NSNotification*)notification {
MPMoviePlayerController *moviePlayer = [notification object];
[moviePlayer play];
}

After spending some time with this I found the answer. (I want to do this too, but later, so I may as well get it going now!)
I used the code and techniques in this link by ascorbin, with help from this link. It is not complete unless you also add the following line to the EAGLView:
glView.opaque = NO;
The movie view is along side of the EAGLView, and pushed to the back to get what you are looking for. You may also have to tweak the transparency of the EAGLView like it mentions in that post. Hope that helps.
The things I needed to modify are listed here.
You need to add apple's mediaPlayer.framework to your project and include the following line in your app delegate .h:
#import <MediaPlayer/MediaPlayer.h>
In CCDirector's setGLDefaultValues method, set glClearColor's alpha to be 0.0f not 1.0f:
// glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
When creating your EAGLView in applicationDidFinishLaunching: change the following things:
Change the pixelFormat from the old value to be this:
// kEAGLColorFormatRGB565
kEAGLColorFormatRGBA8
Make sure to add the EAGLView as a sub-view (and make it non-opaque) rather than as the main view:
// [viewController setView:glView];
[viewController.view addSubview:glView];
glView.opaque = NO;
Finally, before running your scene you can add your code to play the looping movie. I added a method to the app delegate for this. You could also add a method to stop your movie from playing here in the app delegate as well for when (if?) you need to remove your movie.
[self startMovie];
and the method itself:
- (void) startMovie
{
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"test" ofType:#"m4v"]];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
if ([moviePlayer respondsToSelector:#selector(setFullscreen:animated:)]) {
// Use the new 3.2 style API
moviePlayer.controlStyle = MPMovieControlStyleNone;
moviePlayer.shouldAutoplay = YES;
moviePlayer.repeatMode = MPMovieRepeatModeOne;
CGRect win = [[UIScreen mainScreen] bounds];
moviePlayer.view.frame = CGRectMake(0, 0, win.size.height, win.size.width);
[viewController.view addSubview:moviePlayer.view];
[viewController.view sendSubviewToBack:moviePlayer.view];
}
else
{
// Use the old 2.0 style API
moviePlayer.movieControlMode = MPMovieControlModeHidden;
[moviePlayer play];
}
}
Note that you do not have to add the observer like is listed in the linked example, nor the function to repeat the movie, this is done automatically with the 'MPMovieRepeatModeOne' option. If you don't want the movie to repeat you can choose the 'MPMovieRepeatModeNone' option here as well.
I should also note that I was unable to get this to work with the old pre-3.2 API (so in your 3.1.3 case it was not working), the video didn't show through the EAGLView. I am not sure what is happening there, but I have seen no specific options on what to do about that.

Related

iOS - entire View shifts up after rotation

Doing a very simple iPad app that plays a video in fullscreen. I want the video perfectly centered, but on initial load it's a bit too far down. When I rotate it, the view resets itself properly to be perfectly centered. Obviously I'd love to have it look this way from the start.
Here's my code in viewDidLoad:
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"movie" ofType:#"m4v"]];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
[moviePlayer prepareToPlay];
CGRect screenBounds = [UIScreen mainScreen].bounds;
[moviePlayer.view setFrame:CGRectMake(0, 0, screenBounds.size.height, screenBounds.size.width)];
[self.view addSubview:moviePlayer.view];
moviePlayer.controlStyle = MPMovieControlStyleFullscreen;
[moviePlayer play];
[super viewDidLoad];
The app is set to only show in landscape mode, so the rotation takes effect every 180 degrees (instead of 90). BTW the moviePlayer var is set in the .h file like so:
#property (nonatomic, strong) MPMoviePlayerController *moviePlayer;
Then it's synthesized in my ViewController:
#synthesize moviePlayer;
So does anyone have any ideas? I tried changing "setFrame" to start at 0,-20 instead of 0,0 but that messed things up on the later rotations. If there's a way to ignore the dumb status bar on initial load, I'd love to know it. Thanks.
Try setting the frame in -viewDidLayoutSubviews. Layout should be handled there, not in the setup methods.
Try calling
[self setWantsFullScreenLayout:YES];
in the viewcontroller implementation. This should force it to "ignore the dumb status bar on initial load".

How to include a video in my apps intro?

I am creating an iphone app using cocos2d and I was wondering if it would be possible to play a video as an intro of the scene and if its possible how would I do that and what video format should I use?
Just additional info on what I mean
I am looking to include a small animation like Cut the rope has, a small animation before a scene is loaded.
Add MediaPlayer framework to your project.
Add this header file
#import <MediaPlayer/MediaPlayer.h>
NSURL *urlString = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"SAP_Business_Analytics_new_audio_low" ofType:#"mov"]];
player = [[MPMoviePlayerController alloc] initWithContentURL:urlString];
[[player view] setFrame: [self.view frame]]; // frame must match parent view
[self.view addSubview: [player view]];
[player play];

MPMoviePlayerController delay when there should be virtually none

each time my app changes the displayed animation, which is a looping movie, he takes a pause till he finally start the movie.
The MoviePlayerConntroller is created this way
self.moviePlayer = [MPMoviePlayerController alloc];
[moviePlayer initWithContentURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"NewChar" ofType:#"m4v"]] ];
// remove playerview from our view (no prob is he isnt attached to any)
[moviePlayer.view removeFromSuperview];
// tell our playerview the size he has to use
moviePlayer.view.frame = CGRectMake(0, 0, 320, 430);
// and add hin to the superview behind everything else
[self.view insertSubview:moviePlayer.view atIndex:0];
// no moviecontrolls
moviePlayer.controlStyle = MPMovieControlStyleNone;
// looping forever
moviePlayer.repeatMode= MPMovieRepeatModeOne;
// let him use his own Audio Session for old devices
moviePlayer.useApplicationAudioSession= NO;
// fix the silly black background on iOS 4.3
moviePlayer.view.backgroundColor = [UIColor clearColor];
the actual movie is played this way
[moviePlayer initWithContentURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"Whatever" ofType:#"m4v"]]];
[moviePlayer play];
Just as I said, each time the movie is changed, he takes a while to display it. On newer devices its ok, since they are faster, but on G2 it is somewhat disturbing.
Tried prepare playback, but that makes no difference.
Any idea what I missed?
Thanks for reading! :)
It takes time to load up the movie from disk, and obviously will be slower on older devices. How big is the video?

MPMoviePlayerController visible while loading stream

Any one know how to keep the MPMoviePlayerController visible while the movie is loading.
Or before the movie is ready to play?
For some reason it only shows up when the Movie is ready to play.
Heres what I have.
mp = [[MPMoviePlayerController alloc] initWithContentURL:url];
[self.view addSubview:[mp view]];
mp.view.frame = mediaPlayerContainer.frame;
[mediaPlayerContainer removeFromSuperview];
mp.useApplicationAudioSession = YES;
mp.shouldAutoplay = YES;
mp.controlStyle = MPMovieControlStyleFullscreen;
My mediaPlayerContainer is just a dummy container so I can visually build a frame for my mp view.
The only other thing I can think of doing is using a "screenshot" of a player as a place holder. And removing it if the player is in "play" mode.
That seems janky though.
Thnks.
MPMoviePlayerController has a backgroundView property...
You can add an UIImageView to it and it should be displayed while it is loading the video.

Hide MPMoviePlayerController while new video loads

I have an iPad app that has 4 buttons on the left side that corresponds to 4 different video clips. When a user taps the video they want to see, it appears on the right side. I am wanting it to appear to be loading (as if it were streaming over the internet). I added the UIActivityIndicator to the center of the black video frame and have a thread that pauses for 3 seconds. However, the player containing the previous video does not disappear. It just freezes on the last frame of the previous video for 3 seconds (hiding the activity indicator) and then the new video appears.
Any ideas on how to make the player temporarily be hidden? Thanks for any help. Here is my code:
-(IBAction) videoButton1{
[player stop];
[player release];
[self.activityIndicator startAnimating];
NSString *url = [[NSBundle mainBundle] pathForResource:#"video1" ofType:#"mov"];
[self setupVideoPlayer:url];
}
-(void) setupVideoPlayer: (NSString *) url{
player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:url)];
player.view.frame = CGRectMake(487, 205, 478, 320);
[self.view addSubview:player.view];
[NSThread sleepForTimeInterval:3.0];
self.activityIndicator stopAnimating];
[player play];
}
You can set the frame of your player to a View that you can make in IB or programmatically instead of doing a CGRectMake every time.
self.player.view.frame =
self.viewForMovie.bounds;
self.player.view.autoresizingMask =
UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight;
Then in your "videoButton1" you can set the alpha of the View to 0
viewForMovie.alpha = 0;
And in your "setupVideoPlayer" you can change the alpha back to 1.