diff --git a/client/tp-player/bar.cpp b/client/tp-player/bar.cpp index 6d77bf4..39b052f 100644 --- a/client/tp-player/bar.cpp +++ b/client/tp-player/bar.cpp @@ -1,10 +1,11 @@ #include "bar.h" #include #include +#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); diff --git a/client/tp-player/bar.h b/client/tp-player/bar.h index a87a388..8ff8804 100644 --- a/client/tp-player/bar.h +++ b/client/tp-player/bar.h @@ -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; // 已经播放了的时长 diff --git a/client/tp-player/mainwindow.cpp b/client/tp-player/mainwindow.cpp index ae16cdb..0dbd413 100644 --- a/client/tp-player/mainwindow.cpp +++ b/client/tp-player/mainwindow.cpp @@ -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"); - // 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,26 +265,38 @@ 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) { - m_canvas = QPixmap(m_rec_hdr.basic.width, m_rec_hdr.basic.height); + + 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_win_board_w = frameGeometry().width() - geometry().width(); + //m_win_board_h = frameGeometry().height() - geometry().height(); + + QDesktopWidget *desktop = QApplication::desktop(); // =qApp->desktop();也可以 + qDebug("desktop w:%d,h:%d, this w:%d,h:%d", desktop->width(), desktop->height(), width(), height()); + //move((desktop->width() - this->width())/2, (desktop->height() - this->height())/2); + move(10, (desktop->height() - m_rec_hdr.basic.height)/2); + + //setFixedSize(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_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_win_board_w = frameGeometry().width() - geometry().width(); - //m_win_board_h = frameGeometry().height() - geometry().height(); - - QDesktopWidget *desktop = QApplication::desktop(); // =qApp->desktop();也可以 - qDebug("desktop w:%d,h:%d, this w:%d,h:%d", desktop->width(), desktop->height(), width(), height()); - //move((desktop->width() - this->width())/2, (desktop->height() - this->height())/2); - move(10, (desktop->height() - m_rec_hdr.basic.height)/2); - - //setFixedSize(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_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_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()); + } + } +} diff --git a/client/tp-player/mainwindow.h b/client/tp-player/mainwindow.h index 1f3bc6d..03aac59 100644 --- a/client/tp-player/mainwindow.h +++ b/client/tp-player/mainwindow.h @@ -2,11 +2,17 @@ #define MAINWINDOW_H #include +#include #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 diff --git a/client/tp-player/thr_play.cpp b/client/tp-player/thr_play.cpp index c083e8b..9cc820f 100644 --- a/client/tp-player/thr_play.cpp +++ b/client/tp-player/thr_play.cpp @@ -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; } diff --git a/client/tp-player/thr_play.h b/client/tp-player/thr_play.h index 3c3bb2d..c875762 100644 --- a/client/tp-player/thr_play.h +++ b/client/tp-player/thr_play.h @@ -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