不断有人问能不能让OSD Lyrics支持MPD和MOC,之前计划是在寒假的时候进行支持。不过在前几天英语复习时稍微了解了一下MPD,对它的架构很感兴趣,正好昨天考完英语手痒痒了,于是今天就把它给干掉了。
为了支持MPD,使用了libmpd,因此又引入了一个依赖项。那些不使用MPD又有洁癖的同学,可以在configure时加上--disable-mpd选项去除对MPD的支持。
时间有限,还有下面几个问题没解决,待下一个版本处理:
===========================无聊的分隔线==============================
MPD果然和它的名字Media Player Daemon一样,是一个后台服务。它只负责播放音乐,其他的东西,什么界面啊,操作啊,管理啊,你们就自己写个客户端来搞定吧。MPD采用这样一种架构是对Unix“只做一件事,把它做好”的精神的贯彻。听说开发团队坚决把修改ID3tag之类的功能扔到一边,认为这并不是MPD的任务。
既然是个后台程序,那么必须要有强大的通信能力与前台进行交互。它在后台通过socket、TCP/IP来和客户端来通信,不得不说这是一种非常灵活的方式,理论上来说可以完全不依赖任何库就能与它交互——没有哪个操作系统是不支持socket、TCP/IP的。因为是用socket这种无语义的通信方式,MPD要自己定义一套协议,这套协议必须足够灵活、强大和易用。
虽然说可以直接用socket来和MPD进行交互,但是这样要自己解析它的协议,代码成本就高了。好在这么个强大的播放器一定有针对各种语言的通信库。对于C/C++来说就莫过于libmpd了。原本一直在犹豫要不要使用它,因为不想在OSD Lyrics里又添加一个新的依赖,最终的解决方法是加入了编译选项来屏蔽MPD支持,这样不使用MPD的人就不必安装这个库了。当然最好的解决方案是把对播放器的支持插件化,想用哪个播放器就装哪个插件,也许以后会采用这种架构吧,在这之前还有很多工作要做。
另外不得不说libmpd的接口定义得相当不错,使用起来很自然,而且和我自己给播放器支持所定义的接口大同小异。因此MPD的支持代码应该是最少的,如果不算上audacious等使用我自己的MPRIS库的那些播放器的话。
还要再抱怨一下,MPD提供的时间精度依然只到秒,关于这个我已经抱怨过好多次了。我就奇怪了,为什么这些播放器就不愿提供个毫秒级别的精度呢?大概是没考虑到会有OSD Lyrics这样一种应用吧。好在已经抽象出了模拟毫秒精度的方法。
===========================另一个分隔线===============================
为什么是MPD,而不是MOC?这完全取决于它们对开发者的友好程度。MPD本身就是要靠客户端来支持的,因此它先天就是对开发者友好的,有着良好定义的接口,以及详细的开发文档。而MOC,我不知道它是否有IPC接口,但是至少我无法在它的网站上找到对我有用的信息。在论坛上看到似乎它的MPRIS接口正在开发中,如果是这样,那么对它的支持就是易如反掌了——MPRIS支持早就已经到位了。
不止是一个播放器存在着MOC这样的问题。之前支持的好几个非MPRIS播放器没有一个能找到它们的DBUS协议文档的,最后逼得我去看代码。诚然,良好的代码是最好的文档,但是既然已经做好了DBUS接口,准备好了让第三方开发者使用,那么为什么不把它写出来,把为开发者们定义的接口告诉开发者呢?Songbird的MPRIS插件的DBUS名称我可以猜出来,Rhythmbox、Exaile和Banshee我可以从代码里看出来,但是每一次都浪费了很多无谓的时间来定位这些接口是在哪里定义和实现的。
反观MPD,整个查找文档的过程非常快乐。libmpd的文档还带有一个极具代表性的例子(当然这不是MPD的功劳)。实现起来所需要的时间远远小于我的预期。
说了那么多,其实我的OSD Lyrics也有几个模块可以分离出来作为一个库了,代码也需要有更多的文档注释。
MOC也是一定会支持的。不过如果被迫使用管道的话,我担心效率会怎样……