Qt Mobility 提供了很多移动平台上所需的特性和功能,例如摄像头服务、地图服务和短信服务等。
Meego中的应用程序大部分都是建立在Qt Mobility API的基础上的。
其中的video模块在底层调用gstreamer,为应用程序提供了一个方便高效的视频播放API,下面是最简单的example。
player = new QMediaPlayer; player->setMedia(QUrl::fromLocalFile("/Users/me/Music/coolsong.mp3")); widget = new QVideoWidget; player->setVideoOutput(widget); widget->show(); player->play();
下面是一些主要类的功能:
QMediaServiceProvider
提供媒体服务的抽象类,主要功能是requestService得到QMediaService对象。
QMediaService
媒体服务的抽象类,主要功能是requestControl得到QMediaControl对象。
QMediaControl
控制媒体的抽象类,包含大量控制媒体的成员函数。
QMediaServiceProviderPlugin
所有提供媒体服务的plugin都必须继承这个抽象类。create成员函数用来得到实现后的QMediaService派生类实例的指针,key成员函数用来得到一个QStringList,里面包含这个plugin中能提供的所有媒体服务的id。
注:由于一个plugin可能包含几个QMediaServiceProvider的实现,一个QMediaServiceProvider的实现又可能提供几个QMediaService的实现,一个QMediaService的实现也可能提供几个QMediaControl的实现...所以他们的每个派生类都有一个id来识别。
QMediaPlayer
提供给外部应用程序的主要API,应用程序可以通过调用其成员函数play,setVolume,setPosition等控制视频文件的播放。大部分成员函数都是通过调用QMediaPlayerControl类型指针的方法来实现的。例如:
void QMediaPlayer::pause() { Q_D(QMediaPlayer); if (d->control != 0) d->control->pause(); }
那么这个d->control到底指向什么东东呢?
上面已经说了,QMediaPlayer中成员函数的功能都是通过调用QMediaPlayerControl类型对象的成员函数的方法来实现的。获取QMediaPlayerControl类型对象的指针,是在QMediaPlayer构造函数中实现的:
provider = QMediaServiceProvider::defaultServiceProvider(); ... d -> service = provider->requestService(Q_MEDIASERVICE_MEDIAPLAYER); ... d -> control = qobject_cast
1.其实前两句在source code中是不存在的,而是分别通过默认参数和基类初始化式来实现的,我将其改写,只为了清晰地表示出代码体现出的意义。
2.provider和service分别是QMediaServiceProvider和QMediaService类型指针。
3.Q_MEDIASERVICE_MEDIAPLAYER和QMediaPlayerControl_iid就是上面所说的派生类的id。
显然我们可以沿着provider和d->service顺藤摸瓜找到d->control。
首先我们在Qmediaserviceprovider.cpp中找到QMediaServiceProvider::defaultServiceProvider()的定义:
Q_GLOBAL_STATIC(QPluginServiceProvider, pluginProvider); ... QMediaServiceProvider *QMediaServiceProvider::defaultServiceProvider() { return pluginProvider(); }
Q_GLOBAL_STATIC是Qt常用的一个宏,Q_GLOBAL_STATIC(QPluginServiceProvider, pluginProvider)代表的含义:pluginProvider是一个无参函数,返回一个指向新建QPluginServiceProvider对象的指针。这也就是说QMediaPlayer构造函数中的provider指向一个新分配的QPluginServiceProvider对象。
而QPluginServiceProvider继承QMediaServiceProvider 类,它实现了父类的所有纯虚函数。其中最重要的功能即requestService函数,程序扫描plugin/mediaservice/文件夹内的所有插件文件,并用QPluginLoader载入,获得一个指向插件root component的指针obj,然后用qobject_cast将obj转型为一个QMediaServiceProviderPlugin指针:
QMediaServiceProviderPlugin *plugin = qobject_cast
由Qt的插件机制知道,若插件的root component继承自QMediaServiceProviderPlugin,则qobject_cast转型有效,否则结果为0。接着用create就可以得到QMediaService指针service,并将其作为requestService的返回值返回。这个service指向的内容实际上已经是插件文件中继承自QMediaService且id为Q_MEDIASERVICE_MEDIAPLAYER的那个类的实例了。
最后,回到QMediaPlayer的构造函数中,既然d -> service 指向插件中QMediaService派生类的实例,那么d -> service -> requestControl( QMediaPlayerControl_iid )也就指向插件中QMediaControl派生类的实例了。