1背景
hplayer学习 上一篇中追踪到了start设置回调,这一篇继续后续
2步骤
2.1 start如下
void HVideoWidget::start() {
if (media.type == MEDIA_TYPE_NONE) {
QMessageBox::information(this, tr("Info"), tr("Please first set media source, then start."));
updateUI();
return;
}
if (!pImpl_player) {
pImpl_player = HVideoPlayerFactory::create(media.type);
pImpl_player->set_media(media);
pImpl_player->set_event_callback(hplayer_event_callback, this);
title = media.src.c_str();
int ret = pImpl_player->start();
if (ret != 0) {
onOpenFailed();
}
else {
onOpenSucceed();
}
updateUI();
}
else {
if (status == PAUSE) {
resume();
}
}
}
从title = media.src.c_str();开始 从前几篇有提到media是一个结构体,有type和src以及index,src是选择的文件路径。
2.2 pImpl_player->start()
之后的int ret = pImpl_player->start();,这里pImpl_player工厂方法是HFFPlayer,申明的时候是HVideoPlayer。
先看申明(src/ui/HVideoWidget.h)
class HVideoWidget : public QFrame
public:
HVideoPlayer* pImpl_player;
再从HVideoPlayer的头文件(src/video/HVideoPlayer.h)查看
class HVideoPlayer
{
public:
virtual int start() = 0;
再看工厂方法对象,找头文件(src/video/hffplayer.h)
class HFFPlayer : public HVideoPlayer, public HThread {
public:
virtual int start() {
quit = 0;
return HThread::start();
}
这里用了多态
在C++中,当父类的函数声明为虚函数,子类重写该函数(无论是否显式添加 virtual 关键字),并通过父类指针或引用指向子类对象时,实际调用的是子类的函数。这是由虚函数的动态绑定机制(运行时多态)决定的。
父类为虚函数,子类的函数只要签名(名称,参数,返回值)一样,virtual和override加不加都一样,加了可读性更好一点。
在C++中,如果父类的函数不是虚函数,而子类将同名函数声明为虚函数,当通过父类指针调用该函数时,实际调用的是父类的函数。
所以上面实际调用的是HFFPlayer的虚函数(子类,这里加上override,可读性更好),因为基类是虚函数,子类加不加都是虚函数。如果父类不是虚函数,子类加了或者不加,用父类申明,子类初始化,都是调用的父类的函数。
2.3 HThread::start()---待续
2.4 后续的updateUI
在HVideoWidget.h头文件中
class HVideoWidget : public QFrame
protected:
void initUI();
void initConnect();
void updateUI();
在HVideoWidget.cpp中有如下代码
void HVideoWidget::updateUI() {
titlebar->labTitle->setText(QString::asprintf("%02d ", playerid) + title);
toolbar->btnStart->setVisible(status != PLAY);
toolbar->btnPause->setVisible(status == PLAY);
btnMedia->setVisible(status == STOP);
if (status == STOP) {
toolbar->sldProgress->hide();
toolbar->lblDuration->hide();
}
}