Buffering label in a stream using MPMoviePlayer - iphone

Im making a radio streaming application, my app is working perfectly. I have two buttons in my screen one for playing and the other for pausing, also I have a label that indicates the state of my player. I have no problem making this label show the state "Playing" or "Paused" my problem is that when I press the play button there is a time where the buffer is gathering information and I can't figure out a way to show a "Buffering..." label before the player start to stream the audio.
This is the code Im using for streaming the radio station.
NSString *url = [NSString stringWithFormat:#"http://66.7.218:8816"];
player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:url]];
player.movieSourceType = MPMovieSourceTypeStreaming;
player.view.hidden = YES;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance]setActive:YES error:nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[player prepareToPlay];
[player play];
Im usin a function I created called changeStatus and this function is called each second to identify the status of the player.
-(void)changeStatus
{
if (player.loadState == MPMovieLoadStateUnknown) {
status.text = #"Buffering...";
}
if(player.playbackState == MPMoviePlaybackStatePlaying)
{
status.text = #"Playing.";
}
if(player.playbackState == MPMoviePlaybackStatePaused)
{
status.text = #"Paused";
}
}
I really need to solve this problem and Ive tried all I can to solve it. Hope you can help me! Thanks in advance.

I achieved to solve the problem. The part that was missing is the if clause which gives the signal to start playing only when the player is prepared to play. Without that the player starts to play before the buffer is completely loaded so it plays no audio. And that was the reason my Playing label showed immediately instead of the buffering one.
NSString *url = [NSString stringWithFormat:#"http://66.7.218:8816"];
player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:url]];
player.movieSourceType = MPMovieSourceTypeStreaming;
player.view.hidden = YES;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance]setActive:YES error:nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[player prepareToPlay];
if(player.isPreparedToPlay)
{
[player play];
}
Adittionally, the MPMoviePlaybackStateInterrupted refers to the buffering process while doing an stream. So if you want to make something happens in the buffering process refer to this method.
-(void)changeStatus
{
if(player.playbackState == MPMoviePlaybackStatePlaying)
{
status.text = #"Playing.";
}
if(player.playbackState == MPMoviePlaybackStateInterrupted)
{
status.text = #"Buffering...";
}
}
Thanks a lot to the user That Guy who helped me solving this.

Actually there's a notification called
MPMediaPlaybackIsPreparedToPlayDidChangeNotification
The observer will get notified after it is ready to play. It is more or less the same effect but with different mechanism.

Related

Create a Slider and Custom ActivityIndicator for Streaming Audio

I am Working with streaming URL and I need to create a UISlider(control volume) and an indicator(buffering/loading) like one in the above image.
Code I am using is
_theAudio=[[AVPlayer alloc] initWithURL:streamURL];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[_theAudio play];
refer this Link
or
- (void)updateSlider {
// Updates the slider about the music time
slider.value = player.currentTime;
}
- (IBAction)sliderChanged : (UISlider *)sender {
// Fast skips the music when user scrolls the UISlider
[player stop];
[player setCurrentTime:slider.value];
[player prepareToPlay];
[player play];
}
// Stops the timer when the music is finished
- (void)audioPlayerDidFinishPlaying : (AVAudioPlayer *)player successfully : (BOOL)flag {
// Music completed
if (flag) {
[sliderTimer invalidate];
}
}
for volume control u can add below line in
sliderValue_changed delegate
[audioPlayer setVolume:slider.value];
but first set min slider value to 0 and max to 1.

How to play even background mode using MPMoviePlayerController

Audio Live Streaming Service using IIS7 is prepared.
Audio Live streaming server setting is very complex, but have succeeded.
I obtained a URL for streaming like this(#"http://xxx.xxx.xx.xx/liveStream.isml/manifest(format=m3u8-aapl).m3u8").
My using code is unexpectedly simple.
self.theURL = [NSURL URLWithString:#"http://xxx.xxx.xx.xx/liveStream.isml/manifest(format=m3u8-aapl).m3u8"];
if(moviePlayer == nil)
{
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:theURL];
}
[moviePlayer play];
Hm... I can't control music player as I wished.
Question is like this.
I don't want to stop to play music even though backgroundMode.
Please tell me some advice. Thanks.
please check in only device.I have also done in my Application. My code is given below.i am talking about iOS5
And in plist i made an array named "Required background mode" and insert an item in array name, "App Plays Audio". some times URL problem is occurs check this URL MPMoviePlayer sound working in Simulators and ipad device, but not Working in iPhone Device
- (void)viewDidLoad
{
[super viewDidLoad];
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: &setCategoryErr];
[[AVAudioSession sharedInstance] setActive: YES error: &activationErr];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
UIBackgroundTaskIdentifier newTaskId = UIBackgroundTaskInvalid;
newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
}

How to resume AVAudioPlayer after interrupted in background

I am playing music using AVAudioPlayer in background. The problem is: if there is a incoming calling interrupts the player, it will never resume unless switch to foreground and do it manually.
The code is simple, to play it in background:
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayAndRecord error: nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
url = [[NSURL alloc] initFileURLWithPath:...];
audio_player = [[AVAudioPlayer alloc] initWithContentsOfURL: url error:NULL];
audio_player.delegate = self;
bool ret = [audio_player play];
delegate to handle interruptions:
-(void)audioPlayerBeginInterruption:(AVAudioPlayer *)player
{
//tried this, not working [[AVAudioSession sharedInstance] setActive: NO error: nil];
NSLog(#"-- interrupted --");
}
//----------- THIS PART NOT WORKING WHEN RUNNING IN BACKGROUND ----------
- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player
{
NSLog(#"resume!");
//--- tried, not working: [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayAndRecord error: nil];
//--- tried, not working: [[AVAudioSession sharedInstance] setActive: YES error: nil];
//--- tried, not working: [audio_player prepareToPlay];
[audio_player play];
}
Can any one help me?
Found the solution!
I had the same problem, my app was resuming the audio nicely after an interruption, only if my app was open. When it was on the background it failed ro resume playing the audio after an interruption.
I fixed this by adding the following lines of code:
Add this line whenever your app start playing audio.[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
And on the endInterruption method, wait 1 or 2 seconds before resume playing the audio. This to allow the OS to stop using the audio channel.
- (void)endInterruptionWithFlags:(NSUInteger)flags {
// Validate if there are flags available.
if (flags) {
// Validate if the audio session is active and immediately ready to be used.
if (AVAudioSessionInterruptionFlags_ShouldResume) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1), dispatch_get_main_queue(), ^{
// Resume playing the audio.
});
}
}
}
You can also add this line when your app stops (not pause) playing audio. But is not required.
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
Try this
-(void)audioPlayerEndInterruption:(AVAudioPlayer *)audioPlayer withFlags:(NSUInteger)flags{
if (flags == AVAudioSessionFlags_ResumePlay) {
[audioPlayer play];
}
Hope it helps.

didSelectRowAtIndexPath - access tapCount or similar

I'd like to control an instance of AVAudioPlayer from a UITableView item in a didSelectRowAtIndexPath instance.
First touch of the row item triggers 'play' of the AVAudioPlayer. Second touch of the row item triggers 'stop' of the AVAudioPlayer.
I can make the 'play' work but can't get the 'stop' to work. Also, subsequent touches of the row item starts another thread of the audio in the background.
What's the best way to ensure 1 tap starts the audio and a 2nd tap stops it?
Code samples - this method preps audio file and AVAudioPlayer for use:
- (void)makeReadyAudio {
NSString *path = [[NSBundle mainBundle] pathForResource:#"Murderers" ofType:#"mp3"];
NSURL *url = [NSURL fileURLWithPath:path];
NSError *error;
musicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
[musicPlayer prepareToPlay];
}
This block will start & stop the AVAudioPlayer within a case statement in the didSelectRowAtIndexPath section:
case 7: {
//touch to start audio sound playing, touch again to stop playing
[self makeReadyAudio];
if ([musicPlayer isPlaying]) {
[musicPlayer stop];
NSLog(#"musicPlayer tested to be playing, so stop it.");
} else {
[musicPlayer play];
NSLog(#"musicPlayer tested to be *not* playing, so play it.");
}
break;
}
How about:
- (void) didSelectRowAtIndexPath:
{
if (player.isPlaying) {
[player stop];
} else {
[player start];
}
}
In other words, keep the player around and see what it is doing.
The problem is that you call makeReadyAudio every single time the row is tapped. You need to check if you have already done that. For example by doing something like:
if (musicPlayer == nil) {
[self makeReadyAudio];
}

AVaudioPlayer regarding song overlapping

I have using AVAudioPlayer in my app but the problem is that when i play the song from list it will played while before stopping the song i am again goes to song list then select another song then both song will start playing simultaneously so please tell me the code which will terminate my first song.
I use flag variable for initializing the song file---
fileURL = [[NSURL alloc] initFileURLWithPath: [[NSBundle mainBundle] pathForResource:#" Om Namo" ofType:#"aac"]];
self._player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
if (self._player)
{
_fileName.text = [NSString stringWithFormat: #"%# (%d ch.)", [[self._player.url relativePath] lastPathComponent], self._player.numberOfChannels, nil];
[self updateViewForPlayerInfo];
[self updateViewForPlayerState];
}
[fileURL release];
break;
Play and push function---
- (void)startPlayback
{
if ([self._player play])
{
//[self stop];
[self updateViewForPlayerState];
self._player.delegate = self;
}
else
NSLog(#"Could not play %#\n", self._player.url);
}
- (void)pausePlayback
{
[self._player pause];
[self updateViewForPlayerState];
}
I also make stop function---
-(void)stop
{
[_player release];
self._player=nil;
}
Please help me .
Is correct my stop function.
and where i put our stop function or any other solution to fix this problem...
I can think of 3 things :
1) You can make code look like code by putting 4 spaces infront of each line. The reason you've gt no answers so far is probably because your question is almost unreadable ;)
2) In your stop method you might want to try this :
- (void) stop {
[_player stop];
self._player = nil;
}
3) Apple highly discourage using an underscore in front of member names. I've never run into problems but I'd rename _player to player.