Adding CCLayer over a View playing video using MPMoviePlayerController? - objective-c

I have created a View which plays video using MPMoviePlayerController. Now I wish to show a CCLayer over/overlapping this View while the video is in action. How to move forward with this?

//This is where you give path of your video and init it.
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"video_file_name" ofType:#"mp4/mov"]];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
moviePlayer.controlStyle = MPMovieControlStyleNone;
moviePlayer.shouldAutoplay = YES;
NSLog(#"%f", [[CCDirector sharedDirector] view].frame.size.width);
moviePlayer.view.frame = [[CCDirector sharedDirector] view].frame;
[[[CCDirector sharedDirector] view] addSubview:moviePlayer.view];
[[[CCDirector sharedDirector] view] bringSubviewToFront:moviePlayer.view];
[moviePlayer play];
[[NSNotificationCenter defaultCenter] addObserver:self // the object listening / "observing" to the notification
selector:#selector(playbackComplete:) // method to call when the notification was pushed
name:MPMoviePlayerPlaybackDidFinishNotification // notification the observer should listen to
object:moviePlayer]; // the object that is passed to the method
//[[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:1.0 scene:[MainMenu scene] withColor:ccWHITE]];
}
//This is where you define what happens once the playback is complete
-(void)playbackComplete:(id)sender {
// [(MPMoviePlayerController *)sender stop];
// ((MPMoviePlayerController *)sender).view.hidden=YES;
// [((MPMoviePlayerController *)sender) removeFromParentAndCleanup:YES];
[moviePlayer.view removeFromSuperview];
//This is where you load another scene(Ex: Image, Animation etc)
NSLog(#"Make transition");
CGSize size = [[CCDirector sharedDirector] winSize];
[[CCDirector sharedDirector] replaceScene:[CCTransitionSlideInT transitionWithDuration:1.0 scene:[GameLayer scene] ]];
}

Related

EXC_BAD_ACCESS when movie played the second time

I am using mpmovieplayercontroller to play a movie in my game. When the user taps the screen I run a method that replaces the current layer containing the movie with the game main menu. It works fine the first time, but when I try to play the video the second time from the main menu I get an EXC_BAD_ACCESS error on the line
int retVal = UIApplicationMain(argc, argv, nil, #"AppController");
in the main.m.
Please find the relevant code below.
-(void)playVideo {
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"movie" ofType:#"mp4"]];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
moviePlayer.repeatMode = MPMovieRepeatModeOne;
// 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(setFullscreen:animated:)]) {
// Use the new 3.2 style API
moviePlayer.controlStyle = MPMovieControlStyleNone;
moviePlayer.shouldAutoplay = YES;
// This does blows up in cocos2d, so we'll resize manually
[moviePlayer setFullscreen:YES animated:YES];
CGSize winSize = [[CCDirector sharedDirector] winSize];
moviePlayer.view.frame = CGRectMake(0, 0, winSize.width, winSize.height); //width and height are swapped after rotation
[[[CCDirector sharedDirector] view] addSubview:moviePlayer.view ];
[moviePlayer play];
UITapGestureRecognizer * tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
tapGestureRecognizer.delegate = (id)self;
tapGestureRecognizer.numberOfTapsRequired = 1;
[[[CCDirector sharedDirector] view] addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer release];
} else {
// Use the old 2.0 style API
moviePlayer.controlStyle = MPMovieControlStyleNone;
[moviePlayer play];
}
}
- (void)handleTap:(UITapGestureRecognizer *)gesture {
[moviePlayer stop];
[[MenuManager sharedMenuManager] runMenu:kMMenuLayer];
}
// this enables you to handle multiple recognizers on single view
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
-(void)moviePlayBackDidFinish:(NSNotification*)notification {
moviePlayer = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
// If the moviePlayer.view was added to the openGL view, it needs to be removed
if ([moviePlayer respondsToSelector:#selector(setFullscreen:animated:)]) {
[moviePlayer.view removeFromSuperview];
CCLOG(#"this block is okay");
}
[moviePlayer release];
}
Please help.
The reason why you're getting the message is sent to a deallocated instance is because you've not removed the tapGestureRecognizer from the view. I believe your MenuManager singleton replaces the current layer with another, but since the tapGestureRecognizer is still part of the view it will try to access the handleTap, which by this time is deallocated. Add the following line before singleton call in handleTap.
[[[CCDirector sharedDirector] view] removeGestureRecognizer:tapGestureRecognizer];

UISwipeGestureRecognizer method not called?

In my Box2d game i try to use uiswipegesture to get the swipe gesture up and when i do in test project it works fine but when i implement in box2d game it does not called swipe action here is the code
{UISwipeGestureRecognizer *swipeGestureup = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(oneFingerSwipeUp)];
[swipeGestureup setDirection: UISwipeGestureRecognizerDirectionUp ];
[[[CCDirector sharedDirector] openGLView] addGestureRecognizer:swipeGestureup];
[swipeGestureup release];}
and method is
-(void)oneFingerSwipeUp:(id)sender{
NSLog(#"swipe auction called");
[player jump];
}
{
UISwipeGestureRecognizer *swipeGestureup = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(oneFingerSwipeUp:)];
[swipeGestureup setDirection: UISwipeGestureRecognizerDirectionUp ];
[[[CCDirector sharedDirector] openGLView] addGestureRecognizer:swipeGestureup];
[swipeGestureup release];
}
- (void)oneFingerSwipeUp:(UISwipeGestureRecognizer *)recognizer{
NSLog(#"swipe auction called");
}

MPMoviePlayerController view orientation differs on iphone 3g and 4g

I'm trying to play fullscreen landscape video in .m4v format on iPhone using MPMoviePlayerController in my cocos2d game. On 4g device everything works well, but on 3g the video has screen dimensions but vertical orientation, so I can only see the left side of the movie. I'm not sure if the problem is with MPMoviePlayerController or with cocos2d gl view. Here's my code:
NSString *url = [[NSBundle mainBundle] pathForResource:#"intro" ofType:#"m4v"];
player = [[[MPMoviePlayerController alloc] initWithContentURL: [NSURL fileURLWithPath:url]] retain];
[player.view setFrame: [[CCDirector sharedDirector] openGLView].bounds];
if ([player respondsToSelector:#selector(setFullscreen:animated:)]) {
// Use the new 3.2 style API
player.controlStyle = MPMovieControlStyleNone;
player.shouldAutoplay = YES;
CGSize winSize = [[CCDirector sharedDirector] winSize];
CGRect rScreen;
rScreen.origin.x = 0;
rScreen.origin.y = 0;
rScreen.size.width = winSize.width;
rScreen.size.height = winSize.height;
player.view.frame = rScreen;
} else {
// Use the old 2.0 style API
player.movieControlMode = MPMovieControlModeHidden;
}
[[[CCDirector sharedDirector] openGLView] addSubview:player.view];
[player play];
How to make video play well on 3g device? Thanks for your help!

MPMoviePlayerController controls when opened in a UIModalPresentationFormSheet style modal and the user makes the video fullscreen

In my iPad app, I have a UIButton that is calling an IBAction to call a view controller as a modal to show a video in. I wanted the modal to appear as 720x405, and that part seems to work out okay. Here is the IBAction code the button is executing:
-(IBAction)videoPlayerTest:(id)sender {
VideoModalViewController *vc = [[VideoModalViewController alloc] initWithNibName: #"VideoModalViewController" bundle: nil];
vc.fileName = #"testvideo.m4v";
vc.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:vc animated: YES];
vc.view.superview.frame = CGRectMake(0, 0, 720, 405);
vc.view.superview.center = self.view.center;
[vc release];
}
The modal comes up where I want it, and the controls respond on the MPMoviePlayerController; the jog bar, pause, play, etc. but if the user taps on the fullscreen button, the video does go fullscreen alright, but after that the MPMoviePlayerController won't respond to any subsequent taps on the player controls. If I remove the modalPresentationStyle line it will work, but the modal appears on a fullscreen view instead of the 720x405 modal like I want. I've added Observers to try resizing the frame and recenter it when the user makes the movie controller fullscreen and back to windowed, but it didn't appear to help at all. Here is that code.
- (void)willEnterFullscreen:(NSNotification*)notification {
NSLog(#"willEnterFullscreen");
[self setModalPresentationStyle:UIModalPresentationFullScreen];
self.view.frame = CGRectMake(0, 0, 1024, 768);
self.view.center = self.view.center;
}
- (void)willExitFullscreen:(NSNotification*)notification {
NSLog(#"willExitFullscreen");
[self setModalPresentationStyle:UIModalPresentationFormSheet];
self.view.frame = CGRectMake(0, 0, 720, 405);
self.view.center = self.view.center;
}
- (void)playMovie {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(willEnterFullscreen:) name:MPMoviePlayerWillEnterFullscreenNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(willExitFullscreen:) name:MPMoviePlayerWillExitFullscreenNotification object:nil];
NSString *videoString = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:fileName];
NSURL *videoURL = [NSURL fileURLWithPath:videoString];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];
[self.view addSubview:moviePlayer.view];
moviePlayer.view.frame = CGRectMake(0, 0, 720, 405);
moviePlayer.view.backgroundColor = [UIColor grayColor];
[moviePlayer prepareToPlay];
[moviePlayer play];
}
This is my first post-- hope I did it right and provided enough information about the problem I'm having.
I've solved my problem. I was unaware of MPMoviePlayerViewController and I created that and used that as my modal instead. It works great.
-(void)playVideo:(NSString *)fileName {
NSString *videoString = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:fileName];
NSURL *videoURL = [NSURL fileURLWithPath:videoString];
mpViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:videoURL];
[self presentModalViewController:mpViewController animated:NO];
[[mpViewController moviePlayer] play];
}
-(IBAction)videoPlayerTest:(id)sender {
[self playVideo:#"testvideo.m4v"];
}
Thought I'd post what I came up with just in case somebody else encounters the same

Received memory warning. Level=2. Data Formatters temporarily unavailable, will re-try after a 'continue'

I am using cocos2d 0.99.4 and Xcode 4.0. so, I changed my AppDelegate in this way according to the documentation and example given in 0.99.4 version.
- (void) applicationDidFinishLaunching:(UIApplication*)application
{
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[CCDirector setDirectorType:kCCDirectorTypeDisplayLink];
CCDirector *director = [CCDirector sharedDirector];
[director setDeviceOrientation:kCCDeviceOrientationLandscapeLeft];
[director setAnimationInterval:1.0/60];
[director setDisplayFPS:NO];
EAGLView *glView = [EAGLView viewWithFrame:[window bounds]
pixelFormat:kEAGLColorFormatRGBA8
depthFormat:GL_DEPTH_COMPONENT24_OES
preserveBackbuffer:NO];
[[CCDirector sharedDirector] setOpenGLView:glView];
[window addSubview:glView];
[window makeKeyAndVisible];
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888];
gameLevel = [[NSUserDefaults standardUserDefaults] integerForKey:#"gameLevel"] ;
gameLevel = 1;
CCScene *scene = [CCScene node];
CCLayer *layer = [GamewinScreen node];
[scene addChild :layer];
[[CCDirector sharedDirector] runWithScene: scene];
}
//The method test1 is also in the app Delegate class.
-(void)test1
{
[[CCDirector sharedDirector] end];
[[CCDirector sharedDirector] setOpenGLView:[[window subviews] objectAtIndex:0]];
CCScene *Scene = [CCScene node];
CCLayer *Layer = [OpeningScreen node];
[Scene addChild:Layer];
[[CCDirector sharedDirector] runWithScene: Scene];
}
In GameWinScreen I have a selector #selector(goToFirstScreen),
-(void)goToFirstScreen:(id)sender
{
[MY_DELEGATE performSelector:#selector(test1) withObject:nil afterDelay:1.0];
}
After playing the game for 50 minutes and more I am getting
Received memory warning. Level=1
for more than 10 times and then
Received memory warning. Level=2
and the application is crashing. giving the following message
Program received signal: “0”.
Data Formatters temporarily unavailable, will re-try after a 'continue'. (Unknown error loading shared library "/Developer/usr/lib/libXcodeDebuggerSupport.dylib")
alt text http://www.freeimagehosting.net/uploads/52ac11fe93.png
alt text http://www.freeimagehosting.net/uploads/619333a82f.png
This is cocos2d telling you that you are doing something wrong. You are calling setDirectorType on the director in goToFirstScreen, but the second time you call it there is already a director. I'm not sure why you are restarting the director. Why not just replace the scene:
-(void)goToFirstScreen:(id)sender
{
CCScene *Scene = [CCScene node];
CCLayer *Layer = [OpeningScreen node];
[Scene addChild:Layer];
[[CCDirector sharedDirector] replaceScene:Scene];
}