浮动窗淡入淡出功能完成;播放、暂停功能完成;从头播放功能完成;倍速播放功能完成;去除16倍速,没有太大意义。

pull/175/head^2
Apex Liu 2019-09-10 02:04:23 +08:00
parent 4897a6e483
commit 9bc0fcb225
6 changed files with 284 additions and 56 deletions

View File

@ -1,10 +1,11 @@
#include "bar.h"
#include <QPainter>
#include <QDebug>
#include "mainwindow.h"
#define FONT_SIZE_DEFAULT 12
#define TIME_STR_PIXEL_SIZE 16
#define FONT_SIZE_TIME 14
#define TEXT_COLOR QColor(255,255,255,153)
#define SPEED_BTN_WIDTH 42
#define CHKBOX_RIGHT_PADDING 6
@ -58,7 +59,6 @@ static SPEED_MAP speed[speed_count] = {
{speed_2x, "2x"},
{speed_4x, "4x"},
{speed_8x, "8x"},
{speed_16x, "16x"}
};
static inline int min(int a, int b){
@ -92,7 +92,7 @@ Bar::~Bar() {
}
bool Bar::init(QWidget* owner) {
bool Bar::init(MainWindow* owner) {
m_owner = owner;
// 加载所需的图像资源
@ -140,6 +140,9 @@ void Bar::start(uint32_t total_ms, int width) {
void Bar::end() {
if(m_passed_ms != m_total_ms)
update_passed_time(m_total_ms);
m_playing = false;
m_owner->update(m_rc.left()+m_rc_btn_play.left(), m_rc.top()+m_rc_btn_play.top(), m_rc_btn_play.width(), m_rc_btn_play.height());
}
void Bar::_init_imgages() {
@ -261,7 +264,7 @@ void Bar::_init_imgages() {
// 计算显示时间所需的宽高
font.setFamily("consolas");
font.setBold(true);
font.setPixelSize(TIME_STR_PIXEL_SIZE);
font.setPixelSize(FONT_SIZE_TIME);
pp.setFont(font);
{
QFontMetrics fm = pp.fontMetrics();
@ -276,7 +279,7 @@ void Bar::_init_imgages() {
QFont font = pp.font();
font.setFamily("consolas");
font.setBold(true);
font.setPixelSize(TIME_STR_PIXEL_SIZE);
font.setPixelSize(FONT_SIZE_TIME);
pp.setFont(font);
pp.drawText(m_rc_time_total, Qt::AlignLeft, m_str_total_time);
@ -287,7 +290,7 @@ void Bar::_init_imgages() {
int prog_width = m_rc_time_total.left() - PADDING_TIME_PROGRESS_BAR - PADDING_TIME_PROGRESS_BAR - m_rc_time_passed.right();
int prog_height = max(m_res[res_prgbarh_left].height(), m_img_progress_pointer->height());
m_rc_progress = QRect(0, 0, prog_width, prog_height);
m_rc_progress.moveTo(m_rc_time_passed.right() + PADDING_TIME_PROGRESS_BAR, m_rc_time_passed.height() + (m_rc_time_passed.height() - prog_height)/2);
m_rc_progress.moveTo(m_rc_time_passed.right() + PADDING_TIME_PROGRESS_BAR, m_rc_time_passed.top() + (m_rc_time_passed.height() - prog_height)/2);
}
@ -394,6 +397,60 @@ void Bar::onMouseMove(int x, int y) {
// TODO: more hover detect.
}
void Bar::onMousePress(int x, int y) {
// 映射鼠标坐标点到本浮动窗内部的相对位置
QPoint pt(x-m_rc.left(), y-m_rc.top());
if(m_rc_btn_play.contains(pt)) {
if(m_playing)
m_owner->pause();
else
m_owner->resume();
m_playing = !m_playing;
m_owner->update(m_rc.left()+m_rc_btn_play.left(), m_rc.top()+m_rc_btn_play.top(), m_rc_btn_play.width(), m_rc_btn_play.height());
return;
}
int speed_sel = speed_count;
for(int i = 0; i < speed_count; ++i) {
if(m_rc_btn_speed[i].contains(pt)) {
speed_sel = i;
break;
}
}
if(m_speed_selected != speed_sel && speed_sel != speed_count) {
int old_sel = m_speed_selected;
m_speed_selected = speed_sel;
m_owner->speed(get_speed());
m_owner->update(m_rc.left()+m_rc_btn_speed[old_sel].left(), m_rc.top()+m_rc_btn_speed[old_sel].top(), m_rc_btn_speed[old_sel].width(), m_rc_btn_speed[old_sel].height());
m_owner->update(m_rc.left()+m_rc_btn_speed[m_speed_hover].left(), m_rc.top()+m_rc_btn_speed[m_speed_hover].top(), m_rc_btn_speed[m_speed_hover].width(), m_rc_btn_speed[m_speed_hover].height());
return;
}
if(m_rc_skip.contains(pt)) {
m_skip_selected = !m_skip_selected;
m_owner->update(m_rc.left()+m_rc_skip.left(), m_rc.top()+m_rc_skip.top(), m_rc_skip.width(), m_rc_skip.height());
return;
}
}
int Bar::get_speed() {
switch (m_speed_selected) {
case speed_1x:
return 1;
case speed_2x:
return 2;
case speed_4x:
return 4;
case speed_8x:
return 8;
default:
return 1;
}
}
void Bar::draw(QPainter& painter, const QRect& rc_draw){
if(!m_width)
return;
@ -426,15 +483,15 @@ void Bar::draw(QPainter& painter, const QRect& rc_draw){
int to_x = rc.left() + from_x;
int to_y = rc.top() + from_y;
if(m_playing){
if(m_play_hover)
painter.drawPixmap(to_x, to_y, m_img_btn_play[play_running][widget_hover], from_x, from_y, w, h);
else
painter.drawPixmap(to_x, to_y, m_img_btn_play[play_running][widget_normal], from_x, from_y, w, h);
} else {
if(m_play_hover)
painter.drawPixmap(to_x, to_y, m_img_btn_play[play_paused][widget_hover], from_x, from_y, w, h);
else
painter.drawPixmap(to_x, to_y, m_img_btn_play[play_paused][widget_normal], from_x, from_y, w, h);
} else {
if(m_play_hover)
painter.drawPixmap(to_x, to_y, m_img_btn_play[play_running][widget_hover], from_x, from_y, w, h);
else
painter.drawPixmap(to_x, to_y, m_img_btn_play[play_running][widget_normal], from_x, from_y, w, h);
}
}
}
@ -452,7 +509,7 @@ void Bar::draw(QPainter& painter, const QRect& rc_draw){
QFont font = pp.font();
font.setFamily("consolas");
font.setBold(true);
font.setPixelSize(TIME_STR_PIXEL_SIZE);
font.setPixelSize(FONT_SIZE_TIME);
pp.setFont(font);
pp.drawText(QRect(0,0,m_rc_time_passed.width(), m_rc_time_passed.height()), Qt::AlignRight, m_str_passed_time);

View File

@ -55,8 +55,7 @@ typedef enum {
#define speed_2x 1
#define speed_4x 2
#define speed_8x 3
#define speed_16x 4
#define speed_count 5
#define speed_count 4
#define btnspd_normal 0
#define btnspd_sel 1
@ -67,27 +66,32 @@ typedef enum {
#define chkbox_selected 1
#define chkbox_state_count 2
class MainWindow;
class Bar {
public:
Bar();
~Bar();
bool init(QWidget* owner);
bool init(MainWindow* owner);
void start(uint32_t total_ms, int width);
void end();
void draw(QPainter& painter, const QRect& rc);
void update_passed_time(uint32_t ms);
int get_speed();
QRect rc(){return m_rc;}
void onMouseMove(int x, int y);
void onMousePress(int x, int y);
private:
void _init_imgages();
void _ms_to_str(uint32_t ms, QString& str);
private:
QWidget* m_owner;
MainWindow* m_owner;
uint32_t m_total_ms; // 录像的总时长
uint32_t m_passed_ms; // 已经播放了的时长

View File

@ -70,15 +70,19 @@ MainWindow::MainWindow(QWidget *parent) :
m_shown = false;
m_show_default = true;
m_bar_shown = false;
m_bar_fade_in = false;
m_bar_fading = false;
m_bar_opacity = 1.0;
memset(&m_pt, 0, sizeof(TS_RECORD_RDP_POINTER));
m_thr_play = nullptr;
m_play_state = PLAY_STATE_UNKNOWN;
ui->setupUi(this);
ui->centralWidget->setMouseTracking(true);
setMouseTracking(true);
//qRegisterMetaType<update_data*>("update_data");
// frame-less window.
//#ifdef __APPLE__
// setWindowFlags(Qt::FramelessWindowHint | Qt::MSWindowsFixedSizeDialogHint | Qt::Window);
@ -98,16 +102,47 @@ MainWindow::MainWindow(QWidget *parent) :
return;
}
connect(&m_thr_play, SIGNAL(signal_update_data(update_data*)), this, SLOT(on_update_data(update_data*)));
// connect(&m_thr_play, SIGNAL(signal_update_data(update_data*)), this, SLOT(_do_update_data(update_data*)));
connect(&m_timer_bar_fade, SIGNAL(timeout()), this, SLOT(_do_bar_fade()));
connect(&m_timer_bar_delay_hide, SIGNAL(timeout()), this, SLOT(_do_bar_delay_hide()));
}
MainWindow::~MainWindow()
{
m_thr_play.stop();
m_thr_play.wait();
if(m_thr_play) {
m_thr_play->stop();
m_thr_play->wait();
disconnect(m_thr_play, SIGNAL(signal_update_data(update_data*)), this, SLOT(_do_update_data(update_data*)));
delete m_thr_play;
m_thr_play = nullptr;
}
delete ui;
}
void MainWindow::_start_play_thread() {
if(m_thr_play) {
m_thr_play->stop();
m_thr_play->wait();
disconnect(m_thr_play, SIGNAL(signal_update_data(update_data*)), this, SLOT(_do_update_data(update_data*)));
delete m_thr_play;
m_thr_play = nullptr;
}
m_thr_play = new ThreadPlay;
connect(m_thr_play, SIGNAL(signal_update_data(update_data*)), this, SLOT(_do_update_data(update_data*)));
m_thr_play->speed(m_bar.get_speed());
m_thr_play->start();
}
void MainWindow::speed(int s) {
if(m_thr_play)
m_thr_play->speed(s);
}
void MainWindow::paintEvent(QPaintEvent *e)
{
QPainter painter(this);
@ -125,17 +160,40 @@ void MainWindow::paintEvent(QPaintEvent *e)
}
// 绘制浮动控制窗
if(m_bar_shown)
if(m_bar_fading) {
painter.setOpacity(m_bar_opacity);
m_bar.draw(painter, e->rect());
}
else if(m_bar_shown) {
m_bar.draw(painter, e->rect());
}
}
if(!m_shown) {
m_shown = true;
m_thr_play.start();
//m_thr_play.start();
_start_play_thread();
}
}
void MainWindow::on_update_data(update_data* dat) {
void MainWindow::pause() {
if(m_play_state != PLAY_STATE_RUNNING)
return;
m_thr_play->pause();
m_play_state = PLAY_STATE_PAUSE;
}
void MainWindow::resume() {
if(m_play_state == PLAY_STATE_PAUSE)
m_thr_play->resume();
else if(m_play_state == PLAY_STATE_STOP)
//m_thr_play->start();
_start_play_thread();
m_play_state = PLAY_STATE_RUNNING;
}
void MainWindow::_do_update_data(update_data* dat) {
if(!dat)
return;
@ -197,6 +255,7 @@ void MainWindow::on_update_data(update_data* dat) {
return;
}
// 这是播放开始时收到的第一个数据包
if(dat->data_type() == TYPE_HEADER_INFO) {
if(dat->data_len() != sizeof(TS_RECORD_HEADER)) {
qDebug() << "invalid record header.";
@ -206,8 +265,9 @@ void MainWindow::on_update_data(update_data* dat) {
qDebug() << "resize (" << m_rec_hdr.basic.width << "," << m_rec_hdr.basic.height << ")";
if(m_rec_hdr.basic.width > 0 && m_rec_hdr.basic.height > 0) {
if(m_canvas.width() != m_rec_hdr.basic.width && m_canvas.height() != m_rec_hdr.basic.height) {
m_canvas = QPixmap(m_rec_hdr.basic.width, m_rec_hdr.basic.height);
m_canvas.fill(QColor(38, 73, 111));
//m_win_board_w = frameGeometry().width() - geometry().width();
//m_win_board_h = frameGeometry().height() - geometry().height();
@ -221,11 +281,22 @@ void MainWindow::on_update_data(update_data* dat) {
//resize(m_rec_hdr.basic.width + m_win_board_w, m_rec_hdr.basic.height + m_win_board_h);
//resize(m_rec_hdr.basic.width, m_rec_hdr.basic.height);
setFixedSize(m_rec_hdr.basic.width, m_rec_hdr.basic.height);
}
m_canvas.fill(QColor(38, 73, 111));
m_show_default = false;
repaint();
m_bar.start(m_rec_hdr.info.time_ms, 640);
m_bar_shown = true;
m_play_state = PLAY_STATE_RUNNING;
update(m_bar.rc());
m_bar_fade_in = false;
m_bar_fading = true;
m_timer_bar_delay_hide.start(2000);
}
QString title;
@ -242,28 +313,80 @@ void MainWindow::on_update_data(update_data* dat) {
if(dat->data_type() == TYPE_END) {
m_bar.end();
m_play_state = PLAY_STATE_STOP;
return;
}
}
void MainWindow::_do_bar_delay_hide() {
m_bar_fading = true;
m_timer_bar_delay_hide.stop();
m_timer_bar_fade.stop();
m_timer_bar_fade.start(50);
}
void MainWindow::_do_bar_fade() {
if(m_bar_fade_in) {
if(m_bar_opacity < 1.0)
m_bar_opacity += 0.3;
if(m_bar_opacity >= 1.0) {
m_bar_opacity = 1.0;
m_bar_shown = true;
m_bar_fading = false;
m_timer_bar_fade.stop();
}
}
else {
if(m_bar_opacity > 0.0)
m_bar_opacity -= 0.2;
if(m_bar_opacity <= 0.0) {
m_bar_opacity = 0.0;
m_bar_shown = false;
m_bar_fading = false;
m_timer_bar_fade.stop();
}
}
update(m_bar.rc());
}
void MainWindow::mouseMoveEvent(QMouseEvent *e) {
if(!m_show_default) {
QRect rc = m_bar.rc();
if(e->y() > rc.top() - 20 && e->y() < rc.bottom() + 20) {
if(!m_bar_shown) {
m_bar_shown = true;
update(rc);
if((!m_bar_shown && !m_bar_fading) || (m_bar_fading && !m_bar_fade_in)) {
m_bar_fade_in = true;
m_bar_fading = true;
m_timer_bar_delay_hide.stop();
m_timer_bar_fade.stop();
m_timer_bar_fade.start(50);
}
if(rc.contains(QPoint(e->x(), e->y())))
if(rc.contains(e->pos()))
m_bar.onMouseMove(e->x(), e->y());
}
else {
if(m_bar_shown) {
m_bar_shown = false;
update(rc);
if((m_bar_shown && !m_bar_fading) || (m_bar_fading && m_bar_fade_in)) {
m_bar_fade_in = false;
m_bar_fading = true;
m_timer_bar_fade.stop();
m_timer_bar_delay_hide.stop();
if(m_bar_opacity != 1.0)
m_timer_bar_fade.start(50);
else
m_timer_bar_delay_hide.start(1000);
}
}
}
}
void MainWindow::mousePressEvent(QMouseEvent *e) {
if(!m_show_default) {
QRect rc = m_bar.rc();
if(rc.contains(e->pos())) {
m_bar.onMousePress(e->x(), e->y());
}
}
}

View File

@ -2,11 +2,17 @@
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTimer>
#include "bar.h"
#include "thr_play.h"
#include "update_data.h"
#include "record_format.h"
#define PLAY_STATE_UNKNOWN 0
#define PLAY_STATE_RUNNING 1
#define PLAY_STATE_PAUSE 2
#define PLAY_STATE_STOP 3
namespace Ui {
class MainWindow;
}
@ -19,22 +25,31 @@ public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
void pause();
void resume();
void restart();
void speed(int s);
private:
void paintEvent(QPaintEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void mousePressEvent(QMouseEvent *e);
void _start_play_thread();
private slots:
void on_update_data(update_data*);
void _do_update_data(update_data*);
void _do_bar_fade();
void _do_bar_delay_hide();
private:
Ui::MainWindow *ui;
//QImage m_bg;
bool m_shown;
bool m_show_default;
bool m_bar_shown;
QPixmap m_default_bg;
ThreadPlay m_thr_play;
ThreadPlay* m_thr_play;
QPixmap m_canvas;
@ -44,6 +59,14 @@ private:
QPixmap m_pt_normal;
TS_RECORD_RDP_POINTER m_pt;
QTimer m_timer_bar_fade;
QTimer m_timer_bar_delay_hide;
bool m_bar_fade_in;
bool m_bar_fading;
qreal m_bar_opacity;
int m_play_state;
};
#endif // MAINWINDOW_H

View File

@ -11,6 +11,8 @@ static QString REPLAY_PATH = "E:\\work\\tp4a\\teleport\\server\\share\\replay\\r
ThreadPlay::ThreadPlay()
{
m_need_stop = false;
m_need_pause = false;
m_speed = 2;
}
void ThreadPlay::stop() {
@ -23,6 +25,7 @@ void ThreadPlay::run() {
qint64 read_len = 0;
uint32_t total_pkg = 0;
uint32_t total_ms = 0;
QString hdr_filename(REPLAY_PATH);
hdr_filename += "tp-rdp.tpr";
@ -46,6 +49,7 @@ void ThreadPlay::run() {
TS_RECORD_HEADER* hdr = (TS_RECORD_HEADER*)dat->data_buf();
total_pkg = hdr->info.packages;
total_ms = hdr->info.time_ms;
emit signal_update_data(dat);
}
@ -72,6 +76,12 @@ void ThreadPlay::run() {
break;
}
if(m_need_pause) {
msleep(50);
time_begin += 50;
continue;
}
TS_RECORD_PKG pkg;
read_len = f_dat.read((char*)(&pkg), sizeof(pkg));
if(read_len != sizeof(TS_RECORD_PKG)) {
@ -90,18 +100,18 @@ void ThreadPlay::run() {
return;
}
time_pass = (uint32_t)(QDateTime::currentMSecsSinceEpoch() - time_begin);
if(time_pass - time_last_pass > 1000) {
time_pass = (uint32_t)(QDateTime::currentMSecsSinceEpoch() - time_begin) * m_speed;
if(time_pass > total_ms)
time_pass = total_ms;
if(time_pass - time_last_pass > 200) {
update_data* _passed_ms = new update_data;
_passed_ms->data_type(TYPE_TIMER);
_passed_ms->passed_ms(time_pass);
// qDebug("--- 1 %d", time_pass);
emit signal_update_data(_passed_ms);
time_last_pass = time_pass;
}
if(time_pass >= pkg.time_ms) {
//time_pass = pkg.time_ms;
emit signal_update_data(dat);
continue;
}
@ -110,6 +120,12 @@ void ThreadPlay::run() {
uint32_t time_wait = pkg.time_ms - time_pass;
uint32_t wait_this_time = 0;
for(;;) {
if(m_need_pause) {
msleep(50);
time_begin += 50;
continue;
}
wait_this_time = time_wait;
if(wait_this_time > 10)
wait_this_time = 10;
@ -121,12 +137,13 @@ void ThreadPlay::run() {
msleep(wait_this_time);
uint32_t _time_pass = (uint32_t)(QDateTime::currentMSecsSinceEpoch() - time_begin);
if(_time_pass - time_last_pass > 1000) {
uint32_t _time_pass = (uint32_t)(QDateTime::currentMSecsSinceEpoch() - time_begin) * m_speed;
if(_time_pass > total_ms)
_time_pass = total_ms;
if(_time_pass - time_last_pass > 200) {
update_data* _passed_ms = new update_data;
_passed_ms->data_type(TYPE_TIMER);
_passed_ms->passed_ms(_time_pass);
// qDebug("--- 2 %d", _time_pass);
emit signal_update_data(_passed_ms);
time_last_pass = _time_pass;
}

View File

@ -13,13 +13,17 @@ public:
virtual void run();
void stop();
void pause() {m_need_pause = true;}
void resume() {m_need_pause = false;}
void speed(int s) {if(s >= 1 && s <= 16) m_speed = s;}
signals:
void signal_update_data(update_data*);
private:
bool m_need_stop;
bool m_need_pause;
int m_speed;
};
#endif // THR_PLAY_H