MPMoviePlayer standard interface play/pause status reflection issue - iphone

One of my components makes heavy use of MPMoviePlayerController and recently showed a weird bug; when using the standard user interface (e.g. MPMoviePlayerController.controlStyle = MPMovieControlStyleFullscreen;) the player never changes the state of the play/pause button (that thingy in the middle of my screenshot).
The functionality stays intact but the player state is not reflected by the UI.
When bringing up the controls by tapping on the screen while a movie is playing, I see a play-symbol. What I expect would be a pause-symbol as the player is currently playing. When tapping onto the play-symbol, the player goes into pause-mode. The symbol however does not change. When tapping again onto that play symbol, the player continues the playback, just as expected.
The problem has been introduced with iOS5 and did not occur on previous iOS versions.
For validating an iOS5 issues, I created a minimalistic player that is not using my own framework and sure enough the problem did not occur, hence it must be my code triggering this quirk. Unfortunately, my code is pretty damn large (about 3k lines) so I can not post it here.
I know chances of someone being able to answer this question without source code are pretty slim as it seems to be directly connected to my code. Being desperate as I am by now, I just took the chances and hope for a little wonder, somebody actually had such issue and knows how to trigger / remove it.

Well, it seems I found the answer (and what I would call an iOS5 bug)...
The reason for MPMoviePlayerController getting irritate on the status of the play button simply was the order of my initializing code.
For triggering this issue, all you have to do is run this code;
moviePlayer = [[MPMoviePlayerController alloc] init];
moviePlayer.shouldAutoplay = YES;
moviePlayer.fullscreen = NO;
moviePlayer.view.frame = self.view.bounds;
moviePlayer.currentPlaybackTime = 0.0;
moviePlayer.initialPlaybackTime = 0.0;
[moviePlayer setContentURL:[NSURL URLWithString:#"http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"]];
[self.view addSubview:moviePlayer.view];
You will see a player UI which does not change its Pay/Pause state.
For getting things to work properly again, you have to move the setContentURL call before setting the playback-time.
moviePlayer = [[MPMoviePlayerController alloc] init];
moviePlayer.shouldAutoplay = YES;
moviePlayer.fullscreen = NO;
moviePlayer.view.frame = self.view.bounds;
[moviePlayer setContentURL:[NSURL URLWithString:#"http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"]];
moviePlayer.currentPlaybackTime = 0.0;
moviePlayer.initialPlaybackTime = 0.0;
[self.view addSubview:moviePlayer.view];
I did submit a bug at Apple (Radar Bug ID# 10484668) - will keep you posted on their answer.
OpenRadar Bug Report

I also was frequently seeing this behavior, but unfortunately simply switching the order of calls to setContentURL and setting initial and playback times made no difference.
I discovered what I was doing wrong though. I was setting the playback times to -1 to indicate start of the stream when I should have been specifying zero. Changing this fixed the problem for me.

Related

MPMoviePlayerController playback terminates before video finishes

I'm having trouble understanding this class and getting it to work properly, here is the piece of code where I use it:
MPMoviePlayerController *moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:_videoURL];
UIImage *videoThumbnail = [moviePlayer thumbnailImageAtTime:0 timeOption:MPMovieTimeOptionNearestKeyFrame];
[lastImageView setImage:videoThumbnail];
[moviePlayer setControlStyle:MPMovieControlStyleNone];
[moviePlayer setShouldAutoplay:YES];
[moviePlayer prepareToPlay];
[moviePlayer.view setFrame:lastImageView.frame];
moviePlayer.view.transform = CGAffineTransformMakeRotation((90*M_PI)/180);
[self.view addSubview:moviePlayer.view];
[moviePlayer play];
The only reason why the videoThumbnail line is still there is because i didn't get the video to play until I was just trying it out to see if it would get the image from there and then it suddenly began to work... sort of.
Now it plays for 2-3 secs and then terminates without sending MPMoviePlayerPlaybackDidFinishNotification or MPMoviePlayerPlaybackStateDidChangeNotification
I googled around a bit and couldn't find any useful tips, could someone tell me what's wrong or what i am forgetting
If you're not assigning the newly created MPMoviePlayerController instance to anything other than a variable with local scope (moviePlayer), then the movie player will be deallocated before the movie gets playing. (I imagine the thumbnailImageAtTime call keeps it around for a bit longer.)
Try assigning the movie player instance to a retained (strong) instance variable or property. Of course it should be released when finished, as multiple movie player instances don't play well together.
Also, note that, as of iOS 5, calling prepareToPlay is required. The following is from chapter 28 of Matt Neuberg's Programming iOS 5, Second Edition:
Before you can display a movie in your interface with an MPMoviePlayerController, you must call prepareToPlay, which is supplied through the MPMediaPlayer protocol (adopted by MPMoviePlayerController). This requirement is new in iOS 5, and is a major difference from previous versions of the system; your old code can break if it didn’t make this call.

Gyro not working in Cocos2D enviroment

I've got a really strange problem. I have an AR app built on the cocos2D library. Recently when I first fire up xcode for the day, the gyro is not working i.e. the yaw and roll is being measured as 0 no matter how the device is oriented. It SHOULD be working based on the check I am performing in the code:
// Initialize Gyro
self.motionManager = [[[CMMotionManager alloc] init] autorelease];
motionManager.deviceMotionUpdateInterval = (1.0/60.0);
if (motionManager.isDeviceMotionAvailable) {
NSLog(#"motion available");
[motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXTrueNorthZVertical];
}
I've fixed this issue the past few days by commenting out some lines of stuff I am no longer using or changing something related to sprite animation on screen. The bizarre thing is I'll get it working fine for the rest of my coding session, close xcode, and the next day when I open up xcode and my project again, the gyro is once again broken.
Does anyone with more experience with cocos2d or the gyro know what could possibly be causing this?
Thanks.
UPDATE
I commented out the line
[mySprite runAction:[CCMoveTo actionWithDuration:refreshRate position:ccp(newX, newY)]];
and ran the app and the gyro worked again. What's strange though is when I uncommented that same line and ran the app again, the gyro still worked. What gives?
Just a hunch … is motionManager a retaining property?
Because if not, motionManager will be autoreleased:
self.motionManager = [[[CMMotionManager alloc] init] autorelease];

How to show "Loading Movie..." message with MPMoviePlayerController

I'm working with the MPMoviePlayerController for the iOS platform and am not sure why the "Done" and "Loading Movie..." controls are not displaying automatically when loading a new video.
My original implementation of this was to use the UIWebView control to stream the videos, and when the videos are accessed, the "Done" and "Loading Movie..." controls are displayed until the video is loaded and ready to play. I would like to reproduce the same user experience with the MPMoviePlayerController.
Should I get the "Done" and "Loading Movie..." control overlays for free? If not, what do I have to set to get them to show up while the video is loading?
NSURL *videoUrl = [NSURL URLWithString:urlString];
self.moviePlayer = [[[MPMoviePlayerController alloc] init] autorelease];
self.moviePlayer.movieControlMode = MPMovieControlModeDefault;
[self.moviePlayer setContentURL:videoUrl];
[self.moviePlayer prepareToPlay];
[self.view addSubview:self.moviePlayer.view];
[[self.moviePlayer view] setFrame: [self.view bounds]];
[self.moviePlayer setFullscreen:YES animated:YES];
This is answer to your follow-up question, but anyways... You can speed-up things a little bit with this:
prepareToPlay
Prepares the current item for playback. (required)
- (void)prepareToPlay
This method is called automatically when you call the play method. Calling it before you call play gives the receiver a chance to prepare items sooner and may result in decreased latency when starting playback. However, calling this method may also interrupt any active audio sessions.
Available in iOS 3.2 and later.
Declared In MPMediaPlayback.h

Issue..with video playback on iPad with MPMoviePlayerViewController

I have been fighting some code for about a week, and am hoping that someone else may have experienced this problem and can point me in the right direction.
I am using the MPMoviePlayerViewController to play a video on the iPad. The primary problem is that it works FLAWLESSLY on the iPad Simulator, but will not play at all on the iPad. I have tried re-encoding the video to make sure that isn't an issue. The video I'm using is currently a 480x360 video encoded with H.264 Basline 3.0 with AAC/LC audio. The video plays fine on the iPhone, and also does play through Safari on the iPad. The video actually loads, and you can scrub through the video with the scrubber bar and see that it is there. The frames actually display, but just will not play. If you click play, it just immediately stops. Even when I have mp.moviePlayer.shouldAutoplay=YES set, you can see the player attempt to play, but only for a split second (maybe 1 frame?).
I have tried just adding view with the following code:
in .h
------
MPMoviePlayerViewController *vidViewController;
#property (readwrite, retain) MPMoviePlayerViewController *vidViewController;
in .m
------
MPMoviePlayerViewController *mp=[[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:videoURL]];
[mp shouldAutorotateToInterfaceOrientation:YES];
mp.moviePlayer.scalingMode=MPMovieScalingModeAspectFit;
mp.moviePlayer.shouldAutoplay=YES;
mp.moviePlayer.controlStyle=MPMovieControlStyleFullscreen;
[videoURL release];
self.vidViewController = mp;
[mp release];
[self.view addSubview:vidViewController.view];
float w = self.view.frame.size.width;
float h = w * 0.75;
self.vidViewController.view.frame = CGRectMake(0, 0, w, h);
I have also just tried to do a:
[self presentMoviePlayerViewControllerAnimated:self.vidViewController];
which I actually can not get to orient properly...always shows up in Portrait and almost completely off the screen on the bottom, and the app is only intended to run in either of the Landscape views...
If anybody needs more info, just let me know. I'm about at my wits end on this. ANY help will be GREATLY appreciated.
I see 2 problems here.
First you are not setting the frame of the view. Try adding
mp.view.frame = self.view.frame;
This is what fixed it for me.
Next the shouldAutorotateToInterfaceOrientation does not need to be called. This method simply tells you if the view supports an orientation. Check the Apple docs.
You may want to try shutting down the iPad (powering off), remove and re-install the app.
Just add a line after you add the movie player to the view:
[self.vidViewController.moviePlayer play];
See if it helps.
Thanks,
Madhup

MPMoviePlayer Audio Album art

I am streaming an MP3 file using MPMoviePlayer, and I would like to have an image displayed instead of the default Quicktime logo in the background.
I found out a way to have an image overlay the player, but the problem with that, is you have to tap outside the image to get the player controls to appear. And when they do appear, they are underneath the image.
Does someone know how to do this?
Thanks,
John
backgroundColor is deprecated, and diving into private View structures is dangerous. This worked fine for me:
UIImageView *coverImageView = [[UIImageView alloc] initWithImage:coverImage];
coverImageView.contentMode = UIViewContentModeScaleAspectFit;
coverImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
coverImageView.frame = moviePlayerController.view.bounds;
[moviePlayerController.view addSubview:coverImageView];
Most every app on the iPhone is made of a hierarchy of views. You could go up to the top root node of the movie player and walk down the child views recursively and set the hidden value to YES until you find the right item, then insert your UIImageView below that item. That way, the controls stay on top and still respond to user inputs.
The risk you run is if Apple changes the MPMoviePlayer UI and shuffles the view hierarchy, but you'll probably have lots of advance notice and can patch your app to allow for the new layout.
There is a question as to whether this is kosher for appstore apps, but many current apps (especially camera/picture-taking ones) are doing it to get rid of standard window elements.
Use AVAudioPlayer and implement your own player UI.
it will work check this
MPMoviePlayerController *moviePlayerController=[[MPMoviePlayerController alloc] initWithContentURL:theURL];
moviePlayerController.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"Default.png"]];