I'm a new developer and I'm getting to grips with audio in iOS.
This will be tricky to explain, but I'll give it a go. I'm using a media picker so that the user can select a song from their library. I don't want there to be a queue or for it to play immediately. Instead, I want it to appear in a tableview and when the user selects that song in the table view, it will play that when, in another view, a button is pressed.
So basically, I want the user to be able to select a song from their library and it is added to list. They can then selected a song from that list and It will play that when a button is pressed.
If it helps, this is the code I'm using for the media picker and to play audio (and they're not actually connected to each other):
Media Picker:
MPMediaPickerController *mediaPicker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeAnyAudio];
[mediaPicker setDelegate:self];
[mediaPicker setAllowsPickingMultipleItems:NO];
mediaPicker.prompt = NSLocalizedString(#"text1", "text2");
[self presentViewController:mediaPicker animated:YES completion:nil];
Playing Audio:
if (self.panicButtonPressed == NO) {
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:#"Alarm 1"
ofType:#"mp3"]];
alarmSound = [[AVAudioPlayer alloc]
initWithContentsOfURL:url
error:nil];
[alarmSound play];
self.panicButtonPressed = YES;
}
Any help would be greatly appreciated.
Once you get the file URL you can use it to access the files metadata (title,artist,etc.). You can then populate your table with this data and the URL.
Related
I am trying to play mp3 and other audio formats stored on a server with AVPlayer, but every time I get error EXC_BAD_ACCESS.
However, I am able to play these audio files on the browser on chrome.
My Code is in viewDidLoad like this
AVPlayerViewController *playerController = [AVPlayerViewController new];
AVPlayer *songPlayer = [[AVPlayer alloc] initWithURL:[NSURL URLWithString:#"http://mplayer.example.com/Recordings/sun.mp3"]];
playerController.player = songPlayer;
playerController.view.frame = self.view.frame;
[playerController.view sizeToFit];
playerController.videoGravity = AVLayerVideoGravityResizeAspect;
playerController.showsPlaybackControls = YES;
[songPlayer play];
[self.view insertSubview:playerController.view atIndex:0];
I can't figure out what's wrong with my code because my URL is correct and I can fetch audio files from this URL.
You provided URL showing me this message "This webpage is not available
ERR_NAME_NOT_RESOLVED". I tested your code with this URL "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4". It is working fine.
I've been looking at this tutorial for information on how to locate songs in a user's music library on their iPhone. Everything is working as it's supposed to, except that songs that are purchased but not on the user's phone do not play.
Does anyone know a way to fix this, or know how to test to see if the song is purchased vs installed and then alert the user?
Below is the code I'm using from the tutorial that selects and plays the songs:
/*
* This method is called when the user presses button. It displays a media picker
* screen to the user configured to show only audio files.
*/
- (IBAction)pickSong:(id)sender
{
MPMediaPickerController *picker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeAnyAudio];
[picker setDelegate:self];
[picker setAllowsPickingMultipleItems: NO];
[self presentViewController:picker animated:YES completion:NULL];
}
#pragma mark - Media Picker Delegate
/*
* This method is called when the user chooses something from the media picker screen. It dismisses the media picker screen
* and plays the selected song.
*/
- (void)mediaPicker:(MPMediaPickerController *) mediaPicker didPickMediaItems:(MPMediaItemCollection *) collection {
// remove the media picker screen
[self dismissViewControllerAnimated:YES completion:NULL];
// grab the first selection (media picker is capable of returning more than one selected item,
// but this app only deals with one song at a time)
MPMediaItem *item = [[collection items] objectAtIndex:0];
// display title of song in a navigation bar
//NSString *title = [item valueForProperty:MPMediaItemPropertyTitle];
//[_navBar.topItem setTitle:title];
// get a URL reference to the selected item
NSURL *url = [item valueForProperty:MPMediaItemPropertyAssetURL];
// pass the URL to playURL:, defined earlier in this file
[self playURL:url];
}
I have video play play. I'm displaying the video in center of the view adjusting of CGRectMake. But when i click the play button i need to play video in full screen mode automatically without pressing maximize icon. Is it possible?
MPMoviePlayerController *moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"solar" ofType:#"mp4"]]];
[[moviePlayerController view] setFrame:CGRectMake(172, 210, 680, 400)];
[moviePlayerController setShouldAutoplay:NO];
[moviePlayerController setControlStyle:MPMovieControlStyleEmbedded];
[[moviePlayerController backgroundView] setBackgroundColor:[UIColor clearColor]];
[moviePlayerController prepareToPlay];
[self.view addSubview:moviePlayerController.view];
Set MoviePlayer to FullScreen by below method
mpviewController.moviePlayer.controlStyle = MPMovieControlStyleFullscreen;
[self presentModalViewController:mpviewController animated:NO];
This will embed your video to your iOS app:
Add MediaPlayer.framework
Add your video to the root of your project
In your .h file add the following
#property(nonatomic, strong) MPMoviePlayerViewController *moviePlayer; - Put this under #interface ViewController :UIViewController;
in your .m file, add the following
#synthesize moviePlayer; -Put this under #implementation ViewController
NSString *videoPath = [[NSBundle mainBundle] pathForResource:#"your video name" ofType:#"mp4"];
NSURL *videoURL = [NSURL fileURLWithPath:videoPath];
moviePlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:videoURL];
[self presentMoviePlayerViewControllerAnimated:moviePlayer];
First try to use add observer pattern to know when movie player begins
to play at that time switch it to full screen mode. I am giving you
the link just check it. It may help you . In this link the observer
pattern is used for checking whether the player is enter on fullscreen
and in selector method what he wants to do he did. So u can also use
same methodology and instead of checking for fullscreen u should check
for play begin and on selector method set it to full screen..
MPMoviePlayerController stops working in full screen mode // portrait orientation // iOS 7
I am trying to create AVAudioplayer programatically.The audio player successfully playing.But i have some issues.I am displaying 12 audio items in UITableview.If i click first item that should navigate audio player view controller.And i click the play button the song will play.If i click back button the song play continuously.But if i click again same item the Audio view controller the view will display initial state like progress bar should not move and current time and song duration are empty.but song play continuously.
And another issue is there. If i click first item that corresponding song will play.I should not click any pass button.i click back button and click second item.if i click second item the audio view controller will display.I click play button the song display.In background first song play and second song also play.This is my second issue.how to solve these two issues.please help me any body.
-(void)playOrPauseButtonPressed:(id)sender
{
if(playing==NO)
{
[playButton setBackgroundImage:[UIImage imageNamed:#"Pause.png"] forState:UIControlStateNormal];
// Here Pause.png is a image showing Pause Button.
NSError *err=nil;
AVAudioSession *audioSession=[AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
NSLog(#"%# %d",urlsArray,selectedIndex);
NSString *sourcePath=[urlsArray objectAtIndex:selectedIndex];
NSData *objectData=[NSData dataWithContentsOfURL:[NSURL URLWithString:sourcePath]];
audioPlayer = [[AVAudioPlayer alloc] initWithData:objectData error:&err];
audioPlayer.numberOfLoops = 0;
[audioPlayer prepareToPlay];
audioPlayer.delegate=self;
[audioPlayer play];
playing=YES;
}
else if (playing==YES)
{
[playButton setBackgroundImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateNormal];
[audioPlayer pause];
playing=NO;
}
if (self.audioPlayer)
{
[self updateViewForPlayerInfo];
[self updateViewForPlayerState];
[self.audioPlayer setDelegate:self];
}
}
-(void)updateViewForPlayerInfo
{
self.songDuration.text = [NSString stringWithFormat:#"%d:%02d", (int)self.audioPlayer.duration / 60, (int)self.audioPlayer.duration % 60, nil];
NSLog(#"%f", self.audioPlayer.duration);
self.progressBar.maximumValue = self.audioPlayer.duration;
self.volumeSlider.value = self.audioPlayer.volume;
}
-(void)updateViewForPlayerState
{
[self updateCurrentTime];
if (self.updatedTimer)
{
[self.updatedTimer invalidate];
}
if (self.audioPlayer.playing)
{
self.updatedTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(updateCurrentTime) userInfo:self.audioPlayer repeats:YES];
}
}
-(void)updateCurrentTime
{
//NSLog(#"self.audioPlayer.currentTime = %f", self.audioPlayer.currentTime);
self.currentTime.text = [NSString stringWithFormat:#"%d:%02d", (int)self.audioPlayer.currentTime / 60, (int)self.audioPlayer.currentTime % 60, nil];
self.progressBar.value = self.audioPlayer.currentTime;
}
-(void)volumeSliderMoved:(UISlider *)sender
{
self.audioPlayer.volume=[sender value];
}
I think the problem is here
audioPlayer = [[AVAudioPlayer alloc] initWithData:objectData error:&err];
Each time you are creating the audioPlayer object. So my suggestion is check for audioPlayer before creating the object like this
if(audioPlayer)
{
audioPlayer.delegate=nil;
audioPlayer=nil;
}
Then create the object.
In short what's happening is the following:
you click on the table cell
you create an audio player view controller
You play the audio - your audio player itself is retained for some reason (Unclear why - are you using ARC?)
You click the back button - the Audio player view controller is released
you click the table cell again - and create a new audio player view controller with it's own player!
Basically - if you want the previous song continue playing even when your exiting the Audio player view controller - and to have only a single player for the audio - I would hold it in a singleton class that will manage the player , or as a property of the app delegate.
This way - when you enter the Audio Player view controller - It will check the following:
If a player doesn't exist - create it and assign it the item - ready to play
If a player exists but it's the same item - just update the controls to show it's current playing status.
If a player exists but it's another item - either don't update the controls - and when the user hits play - replace the item in the player and start updating the controls - or stop the song as you display the Audio player view controller. (Up to you - I don't know the design of your app obviously)
In working with AVAudioPlayer, I use a property to keep up with the player. Based on looking at your code it isn't clear to me that you are keeping the player around, or that you aren't instantiating a new instance every time. Based on your description, it sounds like you ARE instantiating a new instance - don't think you want that.
So in your .h file, something like this:
#property (nonatomic, strong) AVAudioPlayer *myAVAudioPlayer;
and then the corresponding #synthesize in your .m file.
When you want to move from one song to the next, simply stop playing current - then reload a new URL using an init for your self.myAVAudioPlayer property. You MUST then call the prepareToPlay method again for the AVAudioPlayer option.
You probably will make it easier on yourself by not managing the variables regarding playing or not (it looked like you were doing that from your post). Use your property and check by accessing the setter/getter for the property for state of the player:
if(!self.myAVAudioPlayer)
{
// allocate and initialize using the code you have
[self.myAVAudioPlayer prepareToPlay];
} else
if ([self.myAVAudioPlayer isPlaying])
{
//do whatever you need for isPlaying - looks like pause
} else
if (![self.myAVAudioPlayer isPlaying])
{
// do whatever you need to do if the player isn't playing when the button is pressed
// at this point you will likely just re-init with a new URL and reset other items
// don't forget to call -prepareToPlay again
}
Here is a link to another approach which takes advantage of AVPlayerItem --> click https://stackoverflow.com/a/22254588/3563814
I have a UIViewController subclass called videoPlayerViewController.
In storyboard I dragged out a UIViewController. I set the class correctly in Storyboard.
I put a button on the screen. When I click the button, it executes the method playVideo:.
- (IBAction)playVideo:(id)sender
{
NSURL *movieURL = [NSURL URLWithString:#"http://www.ebookfrenzy.com/ios_book/movie/movie.mov"];
MPMoviePlayerController *player =
[[MPMoviePlayerController alloc] initWithContentURL: movieURL];
[player prepareToPlay];
[player.view setFrame: self.view.bounds]; // player's frame must match parent's
[self.view addSubview: player.view];
[player play];
}
I get a black screen that does nothing.
This is the simplest version of the code I've had in this method over the last 6 hours.
I've tried every StackOverflow answer out there.
I just want to play a video that I stream from the internet.
If I set:
player.movieSourceType = MPMovieSourceTypeStreaming;
the screen reads "loading" for a second, and then crashes.
What exactly am I doing wrong?
I understand there are so many MPMoviePlayerController questions out there, and to just ask a general "How does it work" question seems ludicrous. I've been at this almost 6 hours now and no Google/Stack Overflow/Apple Documentation search has made this work.
I used your provided code but created a MoviePlayerController property named mcp in the header file that I assigned to player to after creating it. That worked for me. The movie loaded and played just fine.
In the .h file:
#property (strong, nonatomic) MPMoviePlayerController *mcp;
In the .m file:
- (IBAction)playVideo:(id)sender
{
NSURL *movieURL = [NSURL URLWithString:#"http://www.ebookfrenzy.com/ios_book/movie/movie.mov"];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL: movieURL];
[player prepareToPlay];
[player.view setFrame: self.view.bounds]; // player's frame must match parent's
_mcp = player;
[self.view addSubview: _mcp.view];
[_mcp play];
}