AVAudioSessionCategoryPlayAndRecord makes AirPlay invisible - objective-c

I am encountering the following problem: AirPlay becomes not available whenever I set play-and-record category to the audio session in my application:
[[AVAudioSession sharedInstance]
setCategory: AVAudioSessionCategoryPlayAndRecord
error: &setCategoryError];
This call makes the AirPlay disappear and reroutes the audio to the speaker immediately.
The problem can be easily reproduced e.g. on the sample project avTouch from Xcode documentation by replacing AVAudioSessionCategoryPlayback category with AVAudioSessionCategoryPlayAndRecord: in the original example AirPlay picker is visible and allows to change output source, whereas with the AVAudioSessionCategoryPlayAndRecord category the picker disappears.
Is there a proper way to switch to AVAudioSessionCategoryPlayAndRecord category so that the AirPlay is still available?
(A question like this has been already asked, but didn't get any answer.)

What AirPlay device are you trying to use? Does it have a microphone?
If not, iOS won't present it as an option when using the PlayAndRecord category, because that device can't play and record. It would show up when using the Play category though.
Also, if the device you are using is a Bluetooth device, have you set AVAudioSessionCategoryOptionAllowBluetooth to YES?

I think you should add the code below above AVAudioSession. I hope it works.
NSError *setCategoryError = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error: &setCategoryError];
if (setCategoryError) {
// Handle error
}

Well, AirPlay and the PlayAndRecord category are just incompatible.
That's what I learned from the Apple forums.
Why do you need audio input on the device when audio output happens somewhere else?

Related

MPMoviePlayerController Background playing

Okay guys i have a problem. I'm stream MPMoviePlayerController and i want it to play audio in background and i've somewhat achieved this.
This is what i do in my -didFinishLaunchingWithOptions:
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
[audioSession setActive:YES error:nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
Now whenever the application calls -applicationWillResignActive:
i do a post notification to continue the playback. And this works but it's an ugly fix. As there is a second delay between the sound stopping and the notification being called. So the playback stops for a second and then continues again by calling the notification which just says [viewPlayer play];
And many other have achieved smooth background playback. Like spotify or other apps whenever you enter background mode there is no sound lag/clipping in sound. This is really annoying to listen to whenever i press the home button or lock the phone.
Yes i did set the background mode for playback.
I have also tried -applicationDidEnterBackground: but this notification is even slower. It comes after -applicationWillResignActive:
I have no idea how to fix this, and or how others achieved it. I have looked through almost all other similar questions. None have my problem.
Thanks in advance.
I've recently used a framework to stream YouTube video inline in a UIView. This framework has a category on MPMoviePlayerController which works pretty well. You notice a change in the music when going to background but it is still acceptable.
The category can be found here:
MPMoviePlayerController+BackgroundPlayback.h
MPMoviePlayerController+BackgroundPlayback.m

playing a youtube movie from url in objective C

I have a tableview which contains youtube urls.
http://www.youtube.com/v/M67PNWvKdg0&autoplay=1
I am trying to play the video file with the following piece of code. I also imported the media framework.
Video *video = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSURL *urlString=[NSURL URLWithString:video.url];
//NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
//pathForResource:#"Video1" ofType:#"mp4"]];
MPMoviePlayerViewController *playercontroller = [[MPMoviePlayerViewController alloc]
initWithContentURL:urlString];
[self presentMoviePlayerViewControllerAnimated:playercontroller];
playercontroller.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
[playercontroller.moviePlayer play];
playercontroller = nil;
What it does for now is it pops up a movie player but then immediately goes back to my tableview. Does anybody knows what the problem is?
Thanks in advance
Are you working on iOS 6? I found difficulty in playing Youtube videos through MPMoviePlayerController, so I found out this to be very useful.
This has MPMoviePlayerController only...
And this would work well for Versions < iOS 6 too.
You can't play youtube videos via Media Player. You have only two solutions: open the link via external app (just open it and iOS will run Safari or YouTube.app if installed) or you can implement your own view with UIWebView and open the link inside WebView.
May be this link would help you, and one more thing is the video plays only on device cant test on a simulator.
There's another way but you have to be a little adventurous.
You can use a third party rtsp framework of which there are a few.
Then you need to link to the m.youtube.com, this is the rtsp version of youtube that Android and other phones will get you to.
If you try to open this link in safari on the iphone the page redirects to the h264 links.
You can open the url in an uitableview and change the user-agent tag. Or simply copy the links you want into a table.
Are all youtube videos automatically converted to h264 now, at one time I remember they were a subset of the rtsp pages.
If you have an Android device you can access this page in a webview quite easily.
here check this link out.
http://streammore-tv.tumblr.com/post/34794206547/welcome

NSUserNotification with custom soundName

Did anyone manage to make a NSUserNotification soundName to work with a custom sound?
I tried with aif and caf format 44100KHz 16bit 2 second of duration. The notification is displayed at the proper time, with the right title and text, but the default sound gets played instead of my custom sound.
The sound files are correctly copied in the application bundle.
If I try this the sounds work ok:
NSSound* sound = [NSSound soundNamed:#"morse.aif"];
[sound play];
But when I use the same sound in my notification, the default notification sound gets played:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
NSUserNotification* notification = [[NSUserNotification alloc]init];
notification.title = #"Titolo";
notification.deliveryDate = [NSDate dateWithTimeIntervalSinceNow:10];
notification.soundName = #"morse.aif";
[[NSUserNotificationCenter defaultUserNotificationCenter]scheduleNotification:notification];
}
I tried with and without extension, but with no success.
notification.soundName = #"morse.aif";
notification.soundName = #"morse2.caf";
notification.soundName = #"morse";
none of these work.
My application is not signed and not sandboxed, but I don't think that's necessary for user notifications, and apart from the sound problem the notifications work great.
It seems to me like this issue is case-sensitivity. Using notification.soundName = #"Morse"; works perfectly for me. As you can see in the NSSound documentation for soundNamed The search folders for sounds are, in order:
~/Library/Sounds
/Library/Sounds
/Network/Library/Sounds
/System/Library/Sounds
If you look in the last one, which is probably where you're trying to pull from since they're the sounds in System Preferences, you can see their names
So keep the case of the file, and omit the extension and it should work as expected.
If you have multiple versions of your App binary notification center may be searching the wrong binary for your sound files.
If you make sure to delete any old copies of the binary it should fix the issue.
From the Apple Dev Forums: https://devforums.apple.com/message/708511
This can happen if you have multiple version of your app binary floating around. NotificationCenter only fines one of them. If it is the one without the sound then it will not work.

How do you programmatically detect your iPad's generation?

I'm working on a program that needs to be able to detect whether or not camera hardware is present in the iPad. I assumed that the easiest way to do this was to determine what generation the device was, but if there is a simpler way to detect the hardware that works too. The iPads that this application is being designed for will likely be recently purchased and running on a standard updated version of iOS.
Nope You can simply check what device is being used!
For checking all iOS devices:
NSString *deviceType = [UIDevice currentDevice].model;
NSLog(deviceType);
In order to check for a camera
if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera])
//there is a camera

App's audio not working through speakers

There's a weird bug in my app. I'm using AVAudioPlayer to play sounds (multiple instances of it), the sound works perfectly through headphones, but using the app without headphones produces no sound from the speaker. All of the audio clips are AAC encoded.
I have tried setting the AVAudioSession properties both through the Objective-C API ([AVAudioSession sharedInstance]) and the C API, but none of the the options seem to work.
accepted answer (in ios7) did not work for me, the following code did work. (i do not have enough points to comment, posting this as separate answer)
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker
error:nil];
ISSUE on iPhone - when sound was very low - seemed it was coming out the phone ear piece (not
headphone jack) instead of bottom speaker - change to DEFAULT TO SPEAKER
//http://stackoverflow.com/questions/3104562/avaudiorecorder-avaudioplayer-sound-output-on-internal-speaker-how-to-chang
UInt32 doChangeDefaultRoute = 1;
AudioSessionSetProperty (
kAudioSessionProperty_OverrideCategoryDefaultToSpeaker,
sizeof (doChangeDefaultRoute),
&doChangeDefaultRoute
);
For those of you using Swift Syntax...
Below worked for me.
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord, withOptions: AVAudioSessionCategoryOptions.DefaultToSpeaker)
}
catch {
print("can't default to speaker ")
}