Multiple MPMoviePlayerController instances - ios4

I'm trying to put two MPMoviePlayerController on a UIView like this
for (int i = 0; i < 2; i++)
{
UIView* v = [[UIView alloc] initWithFrame: CGRectMake(0.0f, 300.0f * i, self.view.width, 300.0f)];
[self.view addSubview: v];
NSURL* url = [NSURL URLWithString: [urls objectAtIndex: i]];
MPMoviePlayerController* movieController = [[MPMoviePlayerController alloc] initWithContentURL: url];
movieController.movieSourceType = MPMovieSourceTypeFile;
movieController.shouldAutoplay = NO;
movieController.view.frame = v.bounds;
[self.view addSubview: movieController.view];
}
But only one view at a time is shown. I know Apple's documentation says
Note: Although you may create multiple MPMoviePlayerController objects and present their views in your interface, only one movie player at a time may play its movie.
but shouldn't the view show all two players at a time? Also only one instance sends MPMoviePlayerLoadStateDidChangeNotification notifications...

You can play multiple videos on the screen by using the AVFoundation framework: AV Foundation Programming Guide
The downside is, that it is not as easy to use as the MPMoviePlayerController, and you shoul create a UIView subclass which contains the AVFoundation classes. This way you can create the necessary controls for it, control the video playback, animate the view (for example animate the transition to fullscreen).
Here it is how I used it:
// Create an AVURLAsset with an NSURL containing the path to the video
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
// Create an AVPlayerItem using the asset
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset];
// Create the AVPlayer using the playeritem
AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
// Create an AVPlayerLayer using the player
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
// Add it to your view's sublayers
[self.layer addSublayer:playerLayer];
// You can play/pause using the AVPlayer object
[player play];
[player pause];
// You can seek to a specified time
[player seekToTime:kCMTimeZero];
// It is also useful to use the AVPlayerItem's notifications and Key-Value
// Observing on the AVPlayer's status and the AVPlayerLayer's readForDisplay property
// (to know when the video is ready to be played, if for example you want to cover the
// black rectangle with an image until the video is ready to be played)
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[player currentItem]];
[player addObserver:self forKeyPath:#"currentItem.status"
options:0
context:nil];
[playerLayer addObserver:self forKeyPath:#"readyForDisplay"
options:0
context:nil];
You can resize the AVPlayerLayer as you like, even while the video is playing.
If you want to use animations while resizing or repositioning your AVPlayerLayer, you have to alter it's default animations, otherwise you'll see that the player layer's video is not resized in sync with its rect. (Thanks to #djromero for his answer regarding the AVPlayerLayer animation)
Here is a small example for how to alter its default animation. The setup for this example is that the AVPlayerLayer is in a UIView subclass that acts as its container:
// UIView animation to animate the view
[UIView animateWithDuration:0.5 animations:^(){
// CATransaction to alter the AVPlayerLayer's animation
[CATransaction begin];
// Set the CATransaction's duration to the value used for the UIView animation
[CATransaction setValue:[NSNumber numberWithFloat:0.5]
forKey:kCATransactionAnimationDuration];
// Set the CATransaction's timing function to linear (which corresponds to the
// default animation curve for the UIView: UIViewAnimationCurveLinear)
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionLinear]];
self.frame = CGRectMake(50.0, 50.0, 200.0, 100.0);
playerLayer.frame = CGRectMake(0.0, 0.0, 200.0, 100.0);
[CATransaction commit];
}];

You won't be able to do this. Internally MPMoviePlayerController seems to use the same view to trade between instances depending on whatever instance is playing. Your only option is to develop your own video player using AVFoundation in order to get multiple instances, or use HTML and UIWebViews. See: http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/00_Introduction.html#//apple_ref/doc/uid/TP40010188

Do you require to play both the videos simultaneously?
I guess i have two options:
Add two video thumbnail image buttons on the same screen. According to selection selected video gets played and other gets stopped. So at a time in view only single video will gets played.
Create one separate view controller and add your video into that. Now add that viewcontroller.view in your main view wherever you want.
Let me know if any of these work for you.

Related

IOS 7 Safari like History dragging gesture using uiwebview

If you see in ios 7 safari app have left and right dragging to see history of webpages. It also show content of previous page while dragging . I want similar functionality using UIWebiview.
I can get forward and backward page but how that dragging functionality with displaying previous content will be implemented?
Note: this is iOS 7 only. For iOS 6 you should use the PanGestureRecognizer and detect if it's left or right.
Your need two properties:
#property (nonatomic, strong) UIImageView * imgvcChild1;
#property (retain, strong) IBOutlet UIWebView *webView;
First of all, add the gesture recognizer to the webView:
[[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:#selector(EdgeLeftPanDetected:)];
panLeft.edges = UIRectEdgeLeft;
[self.webView addGestureRecognizer:panLeft];
Control the gesture:
- (void) EdgeLeftPanDetected:(UIScreenEdgePanGestureRecognizer*)gesture {
if (gesture.state == UIGestureRecognizerStateBegan) {
UIGraphicsBeginImageContext ( self.webView.frame.size );
[self.webView.layer renderInContext:UIGraphicsGetCurrentContext() ];
UIImage *grab = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if ( _imgvcChild1 ) [ _imgvcChild1 removeFromSuperview ];
_imgvcChild1 = [[ UIImageView alloc ] initWithImage:grab ];
_imgvcChild1.frame = self.webView.frame;
_imgvcChild1.userInteractionEnabled = YES;
_imgvcChild2 = [self.arrayImagenes lastObject];
if ([self.webView canGoBack]) {
[self.webView goBack];
}
[ self.view addSubview:_imgvcChild1 ];
}
if (gesture.state == UIGestureRecognizerStateChanged) {
_imgvcChild1.frame = CGRectMake([ gesture locationInView:_imgvcChild1.superview ].x, _imgvcChild1.frame.origin.y, _imgvcChild1.frame.size.width, _imgvcChild1.frame.size.height);
}
}
if (gesture.state == UIGestureRecognizerStateEnded) {
[_imgvcChild1 removeFromSuperview];
}
}
This a prototype, it needs a lot of work, it's just for going back and the page where you go back doesn't have animation. If you want to have animation in the previous page you'll need to create a image before loading the new page and store it on an NSMutableArray and then show it with a different animation (this image starts like -1/4 of screen and goes like 1/4 of the speed of imgvcChild1)
You'll need another gesture recognizer for the right and another array of UIImageViews if you want to go forward too.
Few days back i too have similar kind of requirement. I did lot of research for this, but no luck. I read somewhere that this kind of gesture (History dragging) are managed by OS or the browser itself.
History dragging gesture are not available for UIWebView. As of now you cannot do this with UIWebView.
The one gesture will implement to achieve near to this functionality is UIPanGestureRecognizer but, you still not get the content of the previous page(history).

Handle touch event in uiimage in uiwebview

I am drawing one image (called image1) on top of the another image (called main image) And saved that image locally. Now I am loading the "main image" in the UIWebview. It is fine. But now I need to handle event when touch on the "image1".
Please help me.
Thanks,
Jasmine.
Try this
EDITED
create a UIWebView object 'webview' and create a UITapGestureRecognizer object 'TapGesture'
then
TapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(tapAction:)];
TapGesture.numberOfTapsRequired = 1;
TapGesture.delegate = self;
[self.webview TapGesture];
In this case once you click the image it will call 'tapAction ' method ,In that you can add your code
in TapAction you can add
[UIView animateWithDuration:1.0 animations:^
{
// you can add zooming frame here
}
completion:^(BOOL finished)
{
[self performTransition:UIViewAnimationOptionTransitionCrossDissolve];
}
];

Presenting UITabBarController Modally - Autorotate Problem

I'm attempting to present a UITabBarController modally using the following code:
// Declare all view controllers.
TabOne *tabOne = [[TabOne alloc] initWithNibName:#"TabOne" bundle:nil];
TabTwo *tabTwo = [[TabTwo alloc] init];
TabThree *tabThree = [[TabThree alloc] init];
// Set each view controller's delegate to self.
tabOne.delegate = self;
tabTwo.delegate = self;
tabThree.delegate = self;
// Set a title for each view controller.
tabOne.title = #"One";
tabTwo.title = #"Two";
tabThree.title = #"Three";
// Create a tab bar controller.
UITabBarController *tabBarController = [[UITabBarController alloc] init];
[tabBarController setViewControllers:[NSArray arrayWithObjects:tabOne,tabTwo,tabThree, nil]];
// Present the tab bar controller modally.
[self presentModalViewController:tabBarController animated:NO];
// Memory management.
[tabOne release];
[tabTwo release];
[tabThree release];
This all works as expected except that I get the following warnings in the console:
Using two-stage rotation animation. To use the smoother single-stage animation, this application must remove two-stage method implementations.
Using two-stage rotation animation is not supported when rotating more than one view controller or view controllers not the window delegate.
I've done some research on this and have checked that shouldAutorotateToInterfaceOrientation is implemented as follows:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
As far as I can tell, the problem is that the tab bar controller is not the root view controller, but I'm presenting this modal view some way into a deep view hierarchy. It's called from another modal view, which itself is called from a tab bar set in the application delegate.
I know this is a bit of an old chestnut, but it's got me stumped. Any thoughts?
Thanks in advance.
I've had a similar problem.
UITabBarController has some odd behavior with its orientation handling. When setting its orientation, it calls recursively into self.selectedViewController to decide whether to use one-stage or two-stage animation. That seems sensible, but the trouble is self.selectedViewController is initially nil (in particular, if you're displaying the UITabBarController modally for the first time), and that can confuse the controller. Depending on the iOS version, a nil selectedViewController will lead the UITabBarController to believe that one-stage animation is unsupported.
Try this: when you first load / initialize your UITabBarController, add the line
tabBarController.selectedIndex = 0;
I was getting this warning (including serious visual problems: the view controller was switching orientation but the status bar was not), and setting the index this way fixed the problem. The UITabBarController successfully called into its selected view controller, and detected the one-stage animation.

How to play m3u8 format in iPhone

I have got a url http://stream.alayam.com/alayam/alayam/playlist.m3u8 and wanted to play in iPhone, with m3u8 format, I have successfully got the voice, however movie is not coming. I have used MPMEDIAPLAYER framework and other things.
I am giving u answer in new answer because code will be more readable.
I just download MPMovieController example from Apple website and then add your link with http://
In NSURL i pass link http://stream.alayam.com/alayam/alayam/playlist.m3u8 not this one stream.alayam.com/alayam/alayam/playlist.m3u8 and it works fine.
-(void)initAndPlayMovie:(NSURL *)movieURL
{
// Initialize a movie player object with the specified URL
MPMoviePlayerController *mp = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
if (mp)
{
// save the movie player object
self.moviePlayer = mp;
[mp release];
// Apply the user specified settings to the movie player object
[self setMoviePlayerUserSettings];
// Play the movie!
[self.moviePlayer play];
}
}

What's wrong with my MPMediaPlayerController?

Hi all
I've create simple movie player in iPhone development. But i got just only vedio's voice.
Here is my code (when button click),
-(IBAction)playMe{
NSBundle *bundle=[NSBundle mainBundle];
NSString *moviePath=[bundle pathForResource:#"iiii" ofType:#"mp4"];
NSURL *movieURL = [NSURL fileURLWithPath:moviePath];
MPMoviePlayerController *theMovie=[[MPMoviePlayerController alloc] initWithContentURL:movieURL];
theMovie.scalingMode = MPMovieScalingModeAspectFill;
[theMovie play];
[self.view addSubview:theMovie.view];
}
When i click i got only voice not with movie. I also used iOS 4.1 simulator.
it may be because of you have not set frame to display movie player try this.
theMovie.view.frame=CGRectMake(0,0,300.400);
If this does not work
you can check out following tutorials
http://www.edumobile.org/iphone/iphone-programming-tutorials/how-to-play-video-in-iphoneos4/
http://iosdevelopertips.com/video/getting-mpmovieplayercontroller-to-cooperate-with-ios4-3-2-ipad-and-earlier-versions-of-iphone-sdk.html
http://www.devx.com/wireless/Article/44642/1954
http://iosdevelopertips.com/video/how-to-play-movies-from-application-bundle-or-from-a-remote-server-url.html

Resources