Is MPMusicPlayerController working properly on iPod 5g? - ios

I am developing an application for iOS which works in two different modes, one of them plays music from the iPod library, and the other one synthesizes sounds (eg: pure tones).
In order to synthesize sounds I use an audio unit, so through its callback I can pass the desired signal. As far as sounds must be played at an specific volume, I set the device volume using iPodMusicPlayer.
The issue I see is that the first time the application is run on an iPod Touch 5g after turning it on, once the iPodMusicPlayer is used to set the volume of the device, applicationMusicPlayer will not respond to stop.
I came up with the following code. Runing it on an iPod Touch 5g after turning it on, music will not stop after touching stop.
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
MPMusicPlayerController *mp = [MPMusicPlayerController iPodMusicPlayer];
mp.volume = 0.3;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)playAction:(id)sender {
MPMusicPlayerController *mp = [MPMusicPlayerController applicationMusicPlayer];
MPMediaQuery *query = [MPMediaQuery songsQuery];
[mp setQueueWithQuery:query];
[mp play];
}
- (IBAction)stopAction:(id)sender {
MPMusicPlayerController *mp = [MPMusicPlayerController applicationMusicPlayer];
[mp stop];
}
#end
PS: It is also possible to reproduce the issue by entering the music app, the quitting it (double press on home button and quit music from the multitasking bar), and finally run the code above.
In the other devices I have tested so far (iPad 2nd and 3rd generation, iPod Touch 4 generation) the application works well.
Thanks in advance.

Related

Cannot play video audio via speakers - iOS

I have an iOS 9 application and I have implemented the AVPlayerViewController into one of my view controllers. I am trying to play a video. One problem I have noticed is that if I plug in the headphones, the audio plays in the headphones fine. But if I unplug the headphones, the audio will play from the little ear speaker at the top of the iPhone and NOT from the main speaker. How can I change this? Here is my code:
// Setup the video player view.
AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc] init];
playerViewController.player = [AVPlayer playerWithURL:pass_URL];
self.player_view = playerViewController;
self.player_view.view.frame = self.view.frame;
[self.view addSubview:playerViewController.view];
self.view.autoresizesSubviews = TRUE;
[self.player_view.player play];
I have imported the following frameworks into my Xcode project:
#import <AVFoundation/AVFoundation.h>
#import <AVKit/AVKit.h>
Thanks for your time, Dan.
You need to add a routing change observer (AVAudioSessionRouteChangeNotification) to your AVAudioSession. You can then detect the removal of the headphones and dictate the routing yourself (e.g. with overrideOutputAudioPort) if necessary.

MPNowPlayingInfoCenter and MPRemoteCommandCenter works in simulator but not on device

I'm integrating MPNowPlayingInfoCenter into a music playing app. The integration of that and MPRemoteCommandCenter work great when I run it in the iOS simulator. When I run the same code on a device the music controls in Control Center do not change at all. It's as if the app isn't event registering with MPNow and MPRemote centers.
MPNowPlayingInfoCenter *np = [MPNowPlayingInfoCenter defaultCenter];
np.nowPlayingInfo = #{MPMediaItemPropertyTitle:[tracks objectAtIndex:self.currentTrack],
MPMediaItemPropertyArtist:currentArtist,
MPMediaItemPropertyAlbumTitle:currentAlbum,
MPMediaItemPropertyMediaType:#(MPMediaTypeMusic),
MPMediaItemPropertyPlaybackDuration:#(self.audioHandler.audioDuration),
MPNowPlayingInfoPropertyElapsedPlaybackTime:#(self.audioHandler.position),
MPNowPlayingInfoPropertyPlaybackRate:rate
};
I've got all this good stuff in my view controller life cycle methods:
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
}
- (void)viewWillDisappear:(BOOL)animated {
// Turn off remote control event delivery
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
// Resign as first responder
[self resignFirstResponder];
[super viewWillDisappear:animated];
}
- (BOOL)canBecomeFirstResponder {
return YES;
}
A couple notes:
I'm not using AVPlayer. I'm using CoreAudio/Audio units to play
the audio. This part of the app is working fine.
I'm testing on iOS 7 and iOS 8 only.
I'm using the Amazing Audio Engine as a CoreAudio wrapper: http://theamazingaudioengine.com
Found it. When initializing the amazing audio engine (a great framework by the way) one needs to tell the framework that it doesn't want to share the audio output with other apps if one wants to use the MPNowPlayingInfoCenter. To do this I did:
self.audioController = [[AEAudioController alloc]
initWithAudioDescription:[AEAudioController nonInterleaved16BitStereoAudioDescription]
inputEnabled:NO];
self.audioController.allowMixingWithOtherApps = NO;

AirPlay with multiple instances of AVPlayer

In my app, I have multiple tabs and on each tab I have an instance of AVPlayer. When I activate AirPlay, however, "the first player wins". That means that the player on the currently active tab connects to AirPlay and when I switch to a different tab and press play, nothing happens. So only the first instance of AVPlayer that connects to AirPlay can actually play through AirPlay and no players on the other tabs work. What to do?
The solution is quite easy: When your view controller that contains a player appears, you set allowsExternalPlayback on the AVPlayer instance to YES, when in disappears you set it to NO.
Example:
- (void)viewWillAppear:(BOOL)animated
{
// _player is an instance of AVPlayer
if ([_player respondsToSelector:#selector(setAllowsExternalPlayback:)]) {
// iOS 6+
_player.allowsExternalPlayback = YES;
} else {
// iOS 5
_player.allowsAirPlayVideo = YES;
}
[super viewWillAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
// _player is an instance of AVPlayer
if ([_player respondsToSelector:#selector(setAllowsExternalPlayback:)]) {
// iOS 6+
_player.allowsExternalPlayback = NO;
} else {
// iOS 5
_player.allowsAirPlayVideo = NO;
}
[super viewWillDisappear:animated];
}
Enjoy.

AVAudioPlayer setVolume - How?

Does anyone know the best way to mute game sounds on my app.
I am currently using SystemSoundID which I know cannot have the volume adjusted and need to move to AVAudioPlayer.
Ideally I need a settings page where the volume can be changed and the volume level saved so when coming back out or leaving and re-opening the app it remembers to volume level?
I have tried it various ways using AVAudioPlayer but had no success at present and am receiving some bad reviews for my app for people saying they hate that they cant control the game volume... HELP!!
for AVAudioPlayer you can use this code to mute volume
in .h file
#interface ViewController : UIViewController
{
BOOL muted;
}
and in .m file
- (void)viewDidLoad
{
[super viewDidLoad];
muted = NO;
}
- (IBAction)speakerOnOff:(id)sender
{
if (muted) {
muted = NO;
[player setVolume:1.0];
} else {
muted = YES;
[player setVolume:0.0];
}
}
this code is from this great answer.

MPMusicPlayerController applicationMusicPlayer - Resume when application launches

The MPMusicPlayerController applicationMusicPlayer runs independent of the iPod (or Music) app, which is what I want. It stops playing when the application goes into the background which is again what I want.
However, I would like it to resume playing when the application resumes. Currently I do this by calling the play method again, however this causes the audio to start from the beginning. Is there a way I can actually resume playing from where the audio left off? I can't seem to find anything about it.
Inside the App Delegate's applicationWillResignActive: method, read the musicPlayer.currentPlaybackTime property (declared in the MPMediaPlayback protocol) and store that value somewhere. You could set up a property such as:
#property (assign, nonatomic) NSTimeInterval playbackTime;
and assign it with:
- (void)applicationWillResignActive:(UIApplication *)application
{
MPMusicPlayerController *myPlayer =
[MPMusicPlayerController applicationMusicPlayer];
self.playbackTime = myPlayer.currentPlaybackTime;
[myPlayer pause];
}
When the app is about to become active again, the App Delegate's applicationDidBecomeActive: method will be called. Inside that method, set the currentPlaybackTime property.
- (void)applicationDidBecomeActive:(UIApplication *)application
{
MPMusicPlayerController *myPlayer =
[MPMusicPlayerController applicationMusicPlayer];
myPlayer.currentPlaybackTime = self.playbackTime;
[myPlayer play];
}

Resources