iOS音频播放(二):AudioSession

(本文转自码农人生)
前言

- extern OSStatus AudioSessionInitialize(CFRunLoopRef inRunLoop,
- CFStringRef inRunLoopMode,
- AudioSessionInterruptionListener inInterruptionListener,
- void *inClientData);
- typedef void (*AudioSessionInterruptionListener)(void * inClientData, UInt32 inInterruptionState);
- extern OSStatus AudioSessionAddPropertyListener(AudioSessionPropertyID inID,
- AudioSessionPropertyListener inProc,
- void *inClientData);
- typedef void (*AudioSessionPropertyListener)(void * inClientData,
- AudioSessionPropertyID inID,
- UInt32 inDataSize,
- const void * inData);
- //AudioSession的AudioRouteChangeReason枚举
- enum {
- kAudioSessionRouteChangeReason_Unknown = 0,
- kAudioSessionRouteChangeReason_NewDeviceAvailable = 1,
- kAudioSessionRouteChangeReason_OldDeviceUnavailable = 2,
- kAudioSessionRouteChangeReason_CategoryChange = 3,
- kAudioSessionRouteChangeReason_Override = 4,
- kAudioSessionRouteChangeReason_WakeFromSleep = 6,
- kAudioSessionRouteChangeReason_NoSuitableRouteForCategory = 7,
- kAudioSessionRouteChangeReason_RouteConfigurationChange = 8
- };
- //AVAudioSession的AudioRouteChangeReason枚举
- typedef NS_ENUM(NSUInteger, AVAudioSessionRouteChangeReason)
- {
- AVAudioSessionRouteChangeReasonUnknown = 0,
- AVAudioSessionRouteChangeReasonNewDeviceAvailable = 1,
- AVAudioSessionRouteChangeReasonOldDeviceUnavailable = 2,
- AVAudioSessionRouteChangeReasonCategoryChange = 3,
- AVAudioSessionRouteChangeReasonOverride = 4,
- AVAudioSessionRouteChangeReasonWakeFromSleep = 6,
- AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory = 7,
- AVAudioSessionRouteChangeReasonRouteConfigurationChange NS_ENUM_AVAILABLE_IOS(7_0) = 8
- }
- + (BOOL)usingHeadset
- {
- #if TARGET_IPHONE_SIMULATOR
- return NO;
- #endif
- CFStringRef route;
- UInt32 propertySize = sizeof(CFStringRef);
- AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &route);
- BOOL hasHeadset = NO;
- if((route == NULL) || (CFStringGetLength(route) == 0))
- {
- // Silent Mode
- }
- else
- {
- /* Known values of route:
- * "Headset"
- * "Headphone"
- * "Speaker"
- * "SpeakerAndMicrophone"
- * "HeadphonesAndMicrophone"
- * "HeadsetInOut"
- * "ReceiverAndMicrophone"
- * "Lineout"
- */
- NSString* routeStr = (__bridge NSString*)route;
- NSRange headphoneRange = [routeStr rangeOfString : @"Headphone"];
- NSRange headsetRange = [routeStr rangeOfString : @"Headset"];
- if (headphoneRange.location != NSNotFound)
- {
- hasHeadset = YES;
- }
- else if(headsetRange.location != NSNotFound)
- {
- hasHeadset = YES;
- }
- }
- if (route)
- {
- CFRelease(route);
- }
- return hasHeadset;
- }
- + (BOOL)isAirplayActived
- {
- CFDictionaryRef currentRouteDescriptionDictionary = nil;
- UInt32 dataSize = sizeof(currentRouteDescriptionDictionary);
- AudioSessionGetProperty(kAudioSessionProperty_AudioRouteDescription, &dataSize, ¤tRouteDescriptionDictionary);
- BOOL airplayActived = NO;
- if (currentRouteDescriptionDictionary)
- {
- CFArrayRef outputs = CFDictionaryGetValue(currentRouteDescriptionDictionary, kAudioSession_AudioRouteKey_Outputs);
- if(outputs != NULL && CFArrayGetCount(outputs) > 0)
- {
- CFDictionaryRef currentOutput = CFArrayGetValueAtIndex(outputs, 0);
- //Get the output type (will show airplay / hdmi etc
- CFStringRef outputType = CFDictionaryGetValue(currentOutput, kAudioSession_AudioRouteKey_Type);
- airplayActived = (CFStringCompare(outputType, kAudioSessionOutputRoute_AirPlay, 0) == kCFCompareEqualTo);
- }
- CFRelease(currentRouteDescriptionDictionary);
- }
- return airplayActived;
- }
- extern OSStatus AudioSessionSetProperty(AudioSessionPropertyID inID,
- UInt32 inDataSize,
- const void *inData);
- UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
- AudioSessionSetProperty (kAudioSessionProperty_AudioCategory,
- sizeof(sessionCategory),
- &sessionCategory);
- /* set session category */
- - (BOOL)setCategory:(NSString *)category error:(NSError **)outError;
- /* set session category with options */
- - (BOOL)setCategory:(NSString *)category withOptions: (AVAudioSessionCategoryOptions)options error:(NSError **)outError NS_AVAILABLE_IOS(6_0);
- //AudioSession的AudioSessionCategory枚举
- enum {
- kAudioSessionCategory_AmbientSound = 'ambi',
- kAudioSessionCategory_SoloAmbientSound = 'solo',
- kAudioSessionCategory_MediaPlayback = 'medi',
- kAudioSessionCategory_RecordAudio = 'reca',
- kAudioSessionCategory_PlayAndRecord = 'plar',
- kAudioSessionCategory_AudioProcessing = 'proc'
- };
- //AudioSession的AudioSessionCategory字符串
- /* Use this category for background sounds such as rain, car engine noise, etc.
- Mixes with other music. */
- AVF_EXPORT NSString *const AVAudioSessionCategoryAmbient;
- /* Use this category for background sounds. Other music will stop playing. */
- AVF_EXPORT NSString *const AVAudioSessionCategorySoloAmbient;
- /* Use this category for music tracks.*/
- AVF_EXPORT NSString *const AVAudioSessionCategoryPlayback;
- /* Use this category when recording audio. */
- AVF_EXPORT NSString *const AVAudioSessionCategoryRecord;
- /* Use this category when recording and playing back audio. */
- AVF_EXPORT NSString *const AVAudioSessionCategoryPlayAndRecord;
- /* Use this category when using a hardware codec or signal processor while
- not playing or recording audio. */
- AVF_EXPORT NSString *const AVAudioSessionCategoryAudioProcessing;
- //AudioSession的启动方法
- extern OSStatus AudioSessionSetActive(Boolean active);
- extern OSStatus AudioSessionSetActiveWithFlags(Boolean active, UInt32 inFlags);
- //AVAudioSession的启动方法
- - (BOOL)setActive:(BOOL)active error:(NSError **)outError;
- - (BOOL)setActive:(BOOL)active withFlags:(NSInteger)flags error:(NSError **)outError NS_DEPRECATED_IOS(4_0, 6_0);
- - (BOOL)setActive:(BOOL)active withOptions:(AVAudioSessionSetActiveOptions)options error:(NSError **)outError NS_AVAILABLE_IOS(6_0);

- #import <Endian.h>
- NSString * OSStatusToString(OSStatus status)
- {
- size_t len = sizeof(UInt32);
- long addr = (unsigned long)&status;
- char cstring[5];
- len = (status >> 24) == 0 ? len - 1 : len;
- len = (status >> 16) == 0 ? len - 1 : len;
- len = (status >> 8) == 0 ? len - 1 : len;
- len = (status >> 0) == 0 ? len - 1 : len;
- addr += (4 - len);
- status = EndianU32_NtoB(status); // strings are big endian
- strncpy(cstring, (char *)addr, len);
- cstring[len] = 0;
- return [NSString stringWithCString:(char *)cstring encoding:NSMacOSRomanStringEncoding];
- }
- static void MyAudioSessionInterruptionListener(void *inClientData, UInt32 inInterruptionState)
- {
- AudioSessionInterruptionType interruptionType = kAudioSessionInterruptionType_ShouldNotResume;
- UInt32 interruptionTypeSize = sizeof(interruptionType);
- AudioSessionGetProperty(kAudioSessionProperty_InterruptionType,
- &interruptionTypeSize,
- &interruptionType);
- NSDictionary *userInfo = @{MyAudioInterruptionStateKey:@(inInterruptionState),
- MyAudioInterruptionTypeKey:@(interruptionType)};
- [[NSNotificationCenter defaultCenter] postNotificationName:MyAudioInterruptionNotification object:nil userInfo:userInfo];
- }
- - (void)interruptionNotificationReceived:(NSNotification *)notification
- {
- UInt32 interruptionState = [notification.userInfo[MyAudioInterruptionStateKey] unsignedIntValue];
- AudioSessionInterruptionType interruptionType = [notification.userInfo[MyAudioInterruptionTypeKey] unsignedIntValue];
- [self handleAudioSessionInterruptionWithState:interruptionState type:interruptionType];
- }
- - (void)handleAudioSessionInterruptionWithState:(UInt32)interruptionState type:(AudioSessionInterruptionType)interruptionType
- {
- if (interruptionState == kAudioSessionBeginInterruption)
- {
- //控制UI,暂停播放
- }
- else if (interruptionState == kAudioSessionEndInterruption)
- {
- if (interruptionType == kAudioSessionInterruptionType_ShouldResume)
- {
- OSStatus status = AudioSessionSetActive(true);
- if (status == noErr)
- {
- //控制UI,继续播放
- }
- }
- }
- }
iOS音频播放(二):AudioSession的更多相关文章
- iOS音频播放 (二):AudioSession 转
原文出处 :http://msching.github.io/blog/2014/07/08/audio-in-ios-2/ 前言 本篇为<iOS音频播放>系列的第二篇. 在实施前一篇中所 ...
- IOS 音频播放
iOS音频播放 (一):概述 前言 从事音乐相关的app开发也已经有一段时日了,在这过程中app的播放器几经修改我也因此对于iOS下的音频播放实现有了一定的研究.写这个系列的博客目的一方面希望能够抛砖 ...
- iOS音频播放(一):概述
(本文转自码农人生) 前言 从事音乐相关的app开发也已经有一段时日了,在这过程中app的播放器几经修改,我也因此对于iOS下的音频播放实现有了一定的研究.写这个 系列的博客目的一方面希望能够抛砖引玉 ...
- iOS音频播放 (五):AudioQueue
码农人生 ChengYin's coding life 主页 Blog 分类 Categories 归档 Archives 关于 About Weibo GitHub RSS Where there ...
- iOS音频播放、录音、视频播放、拍照、视频录制
随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像头的操 ...
- iOS音频播放概述
在iOS系统中apple对音频播放需要的操作进行了封装并提供了不同层次的接口 下面对其中的中高层接口进行功能说明: Audio File Services:读写音频数据,可以完成播放流程中的第2步: ...
- iOS音频播放 (四):AudioFile 转
原文出处 : http://msching.github.io/blog/2014/07/19/audio-in-ios-4/ 前言 接着第三篇的AudioStreamFile这一篇要来聊一下Audi ...
- iOS音频播放之AudioQueue(一):播放本地音乐
AudioQueue简单介绍 AudioStreamer说明 AudioQueue具体解释 AudioQueue工作原理 AudioQueue主要接口 AudioQueueNewOutput Audi ...
- iOS音频播放 (三):AudioFileStream 转
原文出处 :http://msching.github.io/blog/2014/07/09/audio-in-ios-3/ 前言 本来说好是要在第三篇中讲AudioFileStream和AudioQ ...
随机推荐
- 【转】android电池(五):电池 充电IC(PM2301)驱动分析篇
关键词:android 电池 电量计 PL2301任务初始化宏 power_supply 中断线程化 平台信息:内核:linux2.6/linux3.0系统:android/android4.0 ...
- Python 自动化脚本学习(三)
函数 例子 def hello(): print("hello" + "world"); 有参数的函数 def hello(name): print(" ...
- android:强大的图片下载和缓存库Picasso
1.Picasso简单介绍 Picasso是Square公司出品的一个强大的图片下载和缓存图片库.官方网址是:http://square.github.io/picasso/ 仅仅须要一句代码就能够将 ...
- 被Oracle全局暂时表坑了
今天凌晨4点多钟,在客户现场的负责人打电话给我,说非常奇怪,下载功能时快时慢.此下载功能非常复杂,之前一直是我优化,在半梦半醒中打开电脑,通过远程看着现场同事在PL/SQL developer中操作. ...
- dom4j解析XML的CURD操作
在开发JavaWeb项目中通常是利用XML配置文件来提高应用程序的访问效率,而在配置XML的同时,更多时候是对XML进行解析. 一.解析XML配置文件有两种机制: DOM和SAX的机制: DOM是将整 ...
- idea maven 无法加载已经安装的模块
新建了一下maven项目,下面新建了一个模块,某一个模块clean install之后,别的模块虽然使用dependency标签引入了,但是仍然无法使用, 这个时候,应该重新建立一个项目,将原有项目的 ...
- Follow-up letter to information seeking meeting, e-mail version
Subject: (logical to recipient!) Thank you for meeting Tuesday, Nov. 23 November 26, 20XY Mr. Jame ...
- Android常用组件Broadcast介绍
一.Broadcast简介 Broadcast是Android的四大组件之一.可分为: 1.普通广播 发送一个广播,所有监听该广播的广播接收者都可以监听到改广播. 2.异步广播 当处理完之后的Inte ...
- Oracle运维服务的四根救命稻草
企业信息化系统建设按生命周期可分为IT规划阶段.IT建设阶段和IT运维阶段,其中,IT运维阶段的时间最长,IT运维管理关乎着IT运维的质量.成本和速度,更关乎着IT系统的安全.连续和可用.大数据云计算 ...
- ASP.NET MVC 自定义错误页面心得
自定义错误页面的目的,就是为了能让程序在出现错误/异常的时候,能够有较好的显示体验. 所以,首先要先了解,我们可以在哪里捕获异常. 当程序发生错误的时候,我们可以在两个地方捕获: Global里面的A ...