#include "play_control_window.h" #include "mainwindowa.h" #define PLAY_SPEED_STEP 0.25 #define PLAY_SPEED_START 0.5 #define PLAY_SPEED_STOP 2 // 4 speed multiple from start to stop in step #include "clickable_slider.h" PlayControlWnd::PlayControlWnd(PlayerController* playerController, QWidget* parent) : QWidget(parent) { // 1. 创建控件 btn_pre = new QPushButton("<<", this); btn_play = new QPushButton("Play", this); btn_next = new QPushButton(">>", this); btn_stop = new QPushButton("Stop", this); slider_speed = new QSlider(Qt::Horizontal, this); label_speed = new QLabel("1.0x", this); check_mute = new QCheckBox("Mute", this); slider_vol = new QSlider(Qt::Horizontal, this); label_vol = new QLabel("0", this); progress_slider = new ClickableSlider(this); label_curTime = new QLabel("00:00", this); label_totalTime = new QLabel("00:00", this); label_divider = new QLabel("/", this); // 2. 设置控件属性 slider_speed->setMinimum(1); slider_speed->setMaximum(8); slider_speed->setValue(4); slider_speed->setTickPosition(QSlider::TicksAbove); slider_speed->setTickInterval(1); slider_speed->setFixedHeight(30); label_speed->setFixedWidth(28); label_speed->setAlignment(Qt::AlignRight | Qt::AlignVCenter); slider_vol->setMinimum(0); slider_vol->setMaximum(100); slider_vol->setSingleStep(5); slider_vol->setPageStep(5); slider_vol->setFixedHeight(22); label_vol->setFixedWidth(20); label_vol->setAlignment(Qt::AlignCenter); progress_slider->setMinimum(0); progress_slider->setMaximum(100); progress_slider->setSingleStep(1); progress_slider->setPageStep(5); progress_slider->setTracking(true); progress_slider->setFixedHeight(18); label_curTime->setFixedWidth(48); label_totalTime->setFixedWidth(48); label_divider->setText("/"); label_divider->setFixedWidth(10); // 3. 布局 hLayout_progress = new QHBoxLayout; hLayout_progress->setSpacing(2); hLayout_progress->addWidget(progress_slider, 1); hLayout_progress->addWidget(label_curTime); hLayout_progress->addWidget(label_divider); hLayout_progress->addWidget(label_totalTime); hLayout_controls = new QHBoxLayout; hLayout_controls->setSpacing(1); hLayout_controls->addWidget(btn_pre); hLayout_controls->addWidget(btn_play); hLayout_controls->addWidget(btn_next); hLayout_controls->addWidget(btn_stop); hLayout_controls->addSpacing(10); hLayout_controls->addWidget(slider_speed); hLayout_controls->addWidget(label_speed); hLayout_controls->addSpacing(10); hLayout_controls->addWidget(check_mute); hLayout_controls->addWidget(slider_vol); hLayout_controls->addWidget(label_vol); mainLayout = new QVBoxLayout(this); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSpacing(2); mainLayout->addLayout(hLayout_progress); mainLayout->addLayout(hLayout_controls); setLayout(mainLayout); // 4. 信号槽 connect(slider_vol, SIGNAL(valueChanged(int)), label_vol, SLOT(setNum(int))); connect(check_mute, &QCheckBox::stateChanged, this, &PlayControlWnd::volume_muted); connect(check_mute, &QCheckBox::stateChanged, playerController, &PlayerController::playMute); connect(btn_stop, &QPushButton::clicked, playerController, &PlayerController::stopPlay); connect(btn_play, &QPushButton::clicked, playerController, &PlayerController::pausePlay); connect(slider_vol, &QSlider::valueChanged, playerController, [this, playerController](int value) { auto maxValue = get_volum_slider_max(); playerController->setVolume(value, maxValue); }); connect(btn_pre, &QPushButton::pressed, playerController, &PlayerController::playSeekPre); connect(btn_next, &QPushButton::pressed, playerController, &PlayerController::playSeekNext); connect(progress_slider, &QSlider::sliderReleased, playerController, &PlayerController::playStartSeek); connect(progress_slider, &QSlider::sliderPressed, playerController, &PlayerController::pausePlay); connect(progress_slider, &ClickableSlider::onClick, playerController, [this, playerController]() { int maxValue = get_progress_slider_max(); double total_time = get_total_time(); int value = get_progress_slider_value(); double seek_time = 0; if (maxValue > 0) seek_time = value * total_time * 1.0 / maxValue; qDebug() << "val:" << value << ",maxVal:" << maxValue << ",total time" << total_time << ",seek time:" << seek_time; // playerController->videoSeek(seek_time); playerController->videoSeekEx(value, maxValue); }); connect(slider_speed, &QSlider::valueChanged, this, &PlayControlWnd::speed_changed); connect(slider_speed, &QSlider::valueChanged, playerController, [this, playerController]() { auto speed = get_speed(); playerController->setPlaySpeed(speed); }); clear_all(); } PlayControlWnd::~PlayControlWnd() { } void PlayControlWnd::set_focus_policy() { /* * Disable widgets in this window to accept foucs, * so all key event will be transfered to the * parent widget. The mainwindow will handle these keyevent * to control the playing. */ // setFocusPolicy(Qt::NoFocus); progress_slider->setFocusPolicy(Qt::NoFocus); slider_speed->setFocusPolicy(Qt::NoFocus); slider_vol->setFocusPolicy(Qt::NoFocus); btn_pre->setFocusPolicy(Qt::NoFocus); btn_play->setFocusPolicy(Qt::NoFocus); btn_next->setFocusPolicy(Qt::NoFocus); btn_stop->setFocusPolicy(Qt::NoFocus); check_mute->setFocusPolicy(Qt::NoFocus); } void PlayControlWnd::volume_muted(int mute) { bool enable = !mute; label_vol->setEnabled(enable); slider_vol->setEnabled(enable); check_mute->setChecked(!enable); } void PlayControlWnd::speed_changed(int value) { int max = slider_speed->maximum(); value %= (max + 1); double speed = (value - 1) * PLAY_SPEED_STEP + PLAY_SPEED_START; QString str = QString::number(speed, 'f', 2) + "x"; // qDebug() << speed << max << "str=" << str; label_speed->setText(str); } double PlayControlWnd::get_speed() const { int value = slider_speed->value(); return (value - 1) * PLAY_SPEED_STEP + PLAY_SPEED_START; } void PlayControlWnd::speed_adjust(bool up) { int value = slider_speed->value(); int max = slider_speed->maximum(); if (up) { value += 1; } else { value -= 1; } value = value > max ? max : value; value = value < 0 ? 0 : value; slider_speed->setValue(value); } void PlayControlWnd::init_slider_speed() { int maxSpeed = (PLAY_SPEED_STOP + PLAY_SPEED_STEP - PLAY_SPEED_START) / PLAY_SPEED_STEP; // 8 slider_speed->setMaximum(maxSpeed); slider_speed->setValue((1 + PLAY_SPEED_STEP - PLAY_SPEED_START) / PLAY_SPEED_STEP); // set 1x speed } void PlayControlWnd::set_volume_slider(float volume) { enable_slider_vol(true); auto max = slider_vol->maximum(); slider_vol->setValue(int(volume * max)); } inline double PlayControlWnd::get_time_secs(int64_t hours, int64_t mins, int64_t secs) { return hours * 60 * 60 + mins * 60 + secs; } inline QSlider* PlayControlWnd::get_progress_slider() const { return progress_slider; } inline QSlider* PlayControlWnd::get_volume_slider() const { return slider_vol; } inline QSlider* PlayControlWnd::get_speed_slider() const { return slider_speed; } int PlayControlWnd::get_volum_slider_max() { return get_volume_slider()->maximum(); } int PlayControlWnd::get_progress_slider_max() { return get_progress_slider()->maximum(); } int PlayControlWnd::get_progress_slider_value() { return get_progress_slider()->value(); } void PlayControlWnd::enable_progressbar(bool enable) { get_progress_slider()->setEnabled(enable); } void PlayControlWnd::enable_slider_vol(bool enable) { slider_vol->setEnabled(enable); } void PlayControlWnd::enable_slider_speed(bool enable) { slider_speed->setEnabled(enable); } void PlayControlWnd::get_play_time_params(int64_t total_secs, int64_t& hours, int64_t& mins, int64_t& secs) { #if 1 mins = total_secs / 60; secs = total_secs % 60; hours = mins / 60; mins %= 60; #else hours = int(total_secs / 3600); mins = (total_secs - hours * 3600) / 60; secs = (total_secs - hours * 3600 - mins * 60); #endif } void PlayControlWnd::update_play_time(int64_t hours, int64_t mins, int64_t secs) { auto time_str = get_play_time(hours, mins, secs); label_curTime->setText(time_str); int percent = 0; auto total = get_total_time(); auto cur = get_time_secs(hours, mins, secs); cur = cur > total ? total : cur; if (total > 0) { percent = cur * get_progress_slider()->maximum() / total; } get_progress_slider()->setValue(percent); } void PlayControlWnd::update_play_time(int64_t total_secs) { int64_t hours = 0, mins = 0, secs = 0; double total = get_total_time(); total_secs = total_secs < 0 ? 0 : total_secs; total_secs = total_secs > total ? total : total_secs; get_play_time_params(total_secs, hours, mins, secs); // qDebug() << "total:" << total_secs << "h:" << hours << "m:" << mins << // "ses:" << secs; update_play_time(hours, mins, secs); } double PlayControlWnd::get_total_time() const { return get_time_secs(m_hours, m_mins, m_secs); } void PlayControlWnd::set_total_time(int64_t hours, int64_t mins, int64_t secs) { enable_progressbar(); enable_play_buttons(); enable_slider_vol(); enable_slider_speed(); check_mute->setEnabled(true); init_slider_speed(); m_hours = hours; m_mins = mins; m_secs = secs; set_progress_bar(get_total_time()); label_totalTime->setText(get_play_time(hours, mins, secs)); } void PlayControlWnd::set_progress_bar(double total_secs) { get_progress_slider()->setMaximum(total_secs); } QString PlayControlWnd::get_play_time(int64_t hours, int64_t mins, int64_t secs) { QString str; if (hours == 0) { str = QString("%1:%2") .arg(QString::number(mins).rightJustified(2, '0')) .arg(QString::number(secs).rightJustified(2, '0')); } else { str = QString("%1:%2:%3") .arg(QString::number(hours).rightJustified(2, '0')) .arg(QString::number(mins).rightJustified(2, '0')) .arg(QString::number(secs).rightJustified(2, '0')); } return str; } void PlayControlWnd::clear_time() { m_hours = 0; m_mins = 0; m_secs = 0; get_progress_slider()->setValue(0); label_totalTime->setText("--:--"); label_curTime->setText("--:--"); } void PlayControlWnd::clear_all() { clear_time(); enable_progressbar(false); update_btn_play(); enable_slider_speed(false); enable_slider_vol(false); enable_play_buttons(false); check_mute->setEnabled(false); init_slider_speed(); } void PlayControlWnd::update_btn_play(bool bPause) { if (bPause) { btn_play->setText("Play"); } else { btn_play->setText("Pause"); } } void PlayControlWnd::enable_play_buttons(bool enable) { btn_next->setEnabled(enable); btn_pre->setEnabled(enable); btn_play->setEnabled(enable); btn_stop->setEnabled(enable); } void PlayControlWnd::keyPressEvent(QKeyEvent* event) { if (auto pParent = (MainWindowA*) parent()) { QApplication::sendEvent(pParent, event); event->ignore(); } else { QWidget::keyPressEvent(event); } }