对于词典软件来说,发音是个必需具备的基本功能,而且 dict.cn 的 Web API 提供了 MP3 格式的单词(短语)发音,所以从开始写 Dict Mac 的起,发音就被列入计划加入的功能。0.02 版完成之后,也就是从 5 月 25 日左右开始准备实现发音功能。
最初的问题是找到合适的 API,花了一个晚上,从 blog 和论坛的帖子堆里发现无数名称,逐一在 Apple 的文档里查找印证,最后终于锁定 Audio Queue Service 这个 framework。有了 framework 的确切名称后就不必再流连于 Stackoverflow 之类的网站,开始专心阅读 Apple 的文档。
花了一个晚上草草看了一下《Audio Queue Service Programming Guide》,感觉不是很好。这个 framework 功能比较强大,设计得比较灵活,相对来说也就没有提供傻瓜化的播放 API,即使是播放一个 MP3 文件也要 400 多行代码。好在这些代码在 programming guide 里都已经直接给出。但是一来我不喜欢这种 copy/paste 代码的方式,二来如果这些代码有 bug(当然 programming guide 里的代码本身有 bug 的可能性不大,但是和 Dict Mac 的 code base 集成的时候很可能引入问题),也要花不少时间解决,而且很可能要重读 programming guide 甚至查阅 API reference。
另外的问题是选择把 dict.cn 的 MP3 文件 download 到本地文件系统之后再打开文件播放的方式,还是直接播放网络的流数据的方式。从尽量减小暴露给用户的复杂度的角度说,稍稍倾向后者。但是考虑到今后还要实现本地缓存,以及尽早实现功能,还是决定先写出把 MP3 文件按照单词作为索引存储在本地文件系统的代码。花了两个晚上写好了这些代码后,第二天白天我脑子里突然冒出一个问题:OS X 会不会有现成的播放 MP3 的命令行工具?从以往的经验看,OS X 的命令行工具还是相当强大的。Google 了一下,果然有一个 afplay。这样一下子把实现发音功能的剩余工作从至少两个晚上变成了一个小时 —— 只要 fork 一个新进程运行 afplay 即可。
其实刚开始写 Dict Mac 的时候就考虑过是不是把必要的 UI 之外的其它功能都做成一个后端独立进程。最后决定当前阶段还是写成一个进程。不过 afplay 至少让发音功能成为了一个独立的进程。一开始我还在抱怨为什么 Mac OS X 不能直接提供一个播放 MP3 的傻瓜接口,其实这样的傻瓜功能应该做成工具而不是 API,像 Audio Queue Service 那样灵活的接口才值得作为 API 的形式提供。这个事情上 OS X 继承了 UNIX 的精髓,也是像 Windows 这样的不管底层功能还是傻瓜功能一股脑的做成 API 的非 UNIX 类的 OS 最缺乏的文化。
发表评论