DOUAudioStreamer 中kqueue的应用
DOUAudioStreamer是一个基于Core Audio的流式音频播放器,其中的DOUAudioEventLoop通过kqueue来控制音频的各种状态。
kqueue简介(详情请看官方manual)
kqueue的功能类似epoll,多用于后台多个socket连接时的I/O复用,注册感兴趣的event,把描述符链表交给内核,然后就等待。一旦有某个或多个事件发生,内核就把 一个只包含有发生了事件的描述符的链表通知给进程,由此避免了每次函数返回的时候都要去遍历整个链表(相较与select和poll)。尽管对于只打开了几个描述符的进程而言这点改进算不得什么,但对于那些打开了几千个文件描述符的程序来说,这种性能改进就相当显著了。
在DOUAudioStreamer中kqueue系统调用生成一个之关联的唯一的描述符,通过kevent来注册和监听音频播放的各种状态的变化,以及变化后(即感兴趣的event发生后)的各种处理。
typedef NS_ENUM(uint64_t, event_type) {
event_play, //播放
event_pause, //暂停
event_stop, //停止
event_seek, //手动选择播放位置
event_streamer_changed, //更换了streamer
event_provider_events,
event_finalizing, //dealloc中发送event,正在释放
#if TARGET_OS_IPHONE
event_interruption_begin,
event_interruption_end,
event_old_device_unavailable, //最后一步
#endif /* TARGET_OS_IPHONE */
event_first = event_play,
#if TARGET_OS_IPHONE
event_last = event_old_device_unavailable,
#else /* TARGET_OS_IPHONE */
event_last = event_finalizing,
#endif /* TARGET_OS_IPHONE */
event_timeout
};
init中初始化过程中的_setupAudioSession(也可以[AVAudioSession sharedInstance] 来设置)
AudioSessionInitialize(NULL, NULL, audio_session_interruption_listener, (__bridge void *)self); //注册被其他应用打断,或其他应用音频播放停止后的处理
//设置MediaPlayback属性可在后台播放声音,也可以避免一些不插耳机时无声的问题
UInt32 audioCategory = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory); AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, audio_route_change_listener, (__bridge void *)self); AudioSessionSetActive(TRUE);
kevent相关的操作
/**
* 官方manual中
The EV_SET() macro is provided for ease of initializing a kevent structure.
EVFILT_USER
Establishes a user event identified by ident which is not associated with any kernel mechanism but is triggered by user level code.
*
*
**/ //相当于register各种感兴趣事件
- (void)_enableEvents
{
for (uint64_t event = event_first; event <= event_last; ++event) {
struct kevent kev;
/**从event_play到event_old_device_unavailable,监听 EV_ADD--添加event,EV_ENABLE--事件被触发后允许返回,EV_CLEAR--返回事件后,重新设置event的状态 **/
EV_SET(&kev, event, EVFILT_USER, EV_ADD | EV_ENABLE | EV_CLEAR, , , NULL);
kevent(_kq, &kev, , NULL, , NULL);
}
} - (void)_sendEvent:(event_type)event
{
[self _sendEvent:event userData:NULL];
} - (void)_sendEvent:(event_type)event userData:(void *)userData
{
struct kevent kev;
//EVFILT_USER通过NOTE_TRIGGER来触发
EV_SET(&kev, event, EVFILT_USER, , NOTE_TRIGGER, , userData);
kevent(_kq, &kev, , NULL, , NULL);
} - (event_type)_waitForEvent
{
return [self _waitForEventWithTimeout:NSUIntegerMax];
}
//kevent监听着感兴趣的事件,一有可用事件就返回事件类型
- (event_type)_waitForEventWithTimeout:(NSUInteger)timeout
{
struct timespec _ts;
struct timespec *ts = NULL;
if (timeout != NSUIntegerMax) {
ts = &_ts; ts->tv_sec = timeout / ;
ts->tv_nsec = (timeout % ) * ;
} while () {
struct kevent kev;
int n = kevent(_kq, NULL, , &kev, , ts);
if (n > ) {
if (kev.filter == EVFILT_USER &&
kev.ident >= event_first &&
kev.ident <= event_last) {
_lastKQUserData = kev.udata;
return kev.ident;
}
}
else {
break;
}
} return event_timeout;
}
最后 _waitForEventWithTimeout / _waitForEvent 被 event_loop_main线程方法中的_eventLoop不断调用,通过_waitForEvent返回的event_type来继续在_handleEvent中处理各种状态需要的操作;
另外_handleEvent中用的是if-else,switch语句是不是性能更好一点,
DOUAudioStreamer 中kqueue的应用的更多相关文章
- DOUAudioStreamer 中的DOUAudioFileProvider理解笔记
概览 DOUAudioFileProvider读取音频文件local,ipod-library,remote audiofile(通过DOUSimpleHTTPRequest封装的CFHTTPMess ...
- Python Twisted、Reactor
catalogue . Twisted理论基础 . 异步编程模式与Reactor . Twisted网络编程 . reactor进程管理编程 . Twisted并发连接 1. Twisted理论基础 ...
- 【转】Python Twisted介绍
Python Twisted介绍 作者:Jessica McKellar 原文链接 Twisted是用Python实现的基于事件驱动的网络引擎框架.Twisted诞生于2000年初,在当时的网络游戏开 ...
- Python Twisted介绍
原文链接:http://www.aosabook.org/en/twisted.html 作者:Jessica McKellar Twisted是用Python实现的基于事件驱动的网络引擎框架.Twi ...
- Linux系统时间与RTC时间【转】
http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=3637782 Linux的RTC驱动相对还是比较简单的,可以将它作为一个普通的字符 ...
- Python开源框架
info:更多Django信息url:https://www.oschina.net/p/djangodetail: Django 是 Python 编程语言驱动的一个开源模型-视图-控制器(MVC) ...
- kqueue例子
网络服务器通常都使用epoll进行异步IO处理,而开发者通常使用mac,为了方便开发,我把自己的handy库移植到了mac平台上.移植过程中,网上居然没有搜到kqueue的使用例子,让我惊讶不已.为了 ...
- 可扩展的事件复用技术:epoll和kqueue
通常来说我喜欢Linux更甚于BSD系统,但是我真的想在Linux上拥有BSD的kqueue功能. 什么是事件复用技术 假设你有一个简单的web服务器,并且那里已经打开了两个socket连接.当服务器 ...
- 在Mac OS X Yosemite 10.10.3 中搭建第一个 ASP.NET 5 Web 项目
终于有时间在 Mac 上安装一下 ASP.NET 5,网上有许多教程,但是多数的时间比较早了,版本不是最新,搭着 Build 2015 的春风,我也实践一下 Mac OS X 上的 ASP.NET 5 ...
随机推荐
- 生肖年(switch练习)
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- tmux简要介绍
什么是tmux tmux全称terminal multiplexer,是一个终端复用软件.它可以帮助我们方便地管理多个终端会话. 下面介绍tmux中涉及到的一些名词 window 窗口 pane 窗格 ...
- JavaWeb的国际化(17/4/8)
国际化的缺点: 因为文字不同,所以带来的排版问题一样严重,通常都是重新在写一个网站反而更加清晰,快捷 1:需要从浏览器中获取到浏览器语言(Accept-Language) 2:利用locale获取 ...
- 内嵌的Component调用外部的方法
如果一个内嵌的Component控件需要调用外部定义的方法,用outerDocument.方法名来调用,前提是该方法是public的.如:<mx:DataGridColumn headerTex ...
- 纯净CentOS7.2 yum源配置与使用yum 安装系统工具net-tools
本节我们来讲CentOS 的yum 源配置 一.yum 简介 yum,是Yellow dog Updater, Modified 的简称,是杜克大学为了提高RPM 软件包安装性而开发的一种软件包管理器 ...
- 谈谈一些有趣的CSS题目(十五)-- 奇妙的 background-clip: text
开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...
- Spring Boot快速建立HelloWorld项目
Spring Boot使我们更容易去创建基于Spring的独立和产品级的可以”即时运行“的应用和服务.支持约定大于配置,目的是尽可能快地构建和运行Spring应用. 构建环境 JDK 6+ Maven ...
- 【Java SE】如何用Java实现直接选择排序
摘要:直接选择排序属于选择排序的一种,但是它的排序算法比冒泡排序的速度要快一些,由于它的算法比较简单,所以也比较适合初学者学习掌握. 适宜人群:有一定Java SE基础,明白Java的数据类型,数组的 ...
- 开源框架是如何通过JMX来做监控的(一) - JMX简介和Standard MBean
相关文章目录: 开源框架是如何通过JMX来做监控的(一) - JMX简介和Standard MBean 开源框架是如何通过JMX来做监控的(二) - Druid连接池的监控 相信很多做Java开发的同 ...
- C语言解析17monipdb.dat(http://www.ipip.net/)免费数据库
官方给的链接打不开,而且里面的逻辑,每次都会打开文件,所以自己做了点个修改,发上来,借大家参考: #include <stdio.h> #include <stdlib.h> ...