From a4c49304bb982491a50826ac7b9b8ace96815f68 Mon Sep 17 00:00:00 2001 From: xfangfang <2553041586@qq.com> Date: Fri, 23 Sep 2022 21:19:07 +0800 Subject: [PATCH] Release 0.4.0 --- library/borealis | 2 +- resources/i18n/zh-Hans/wiliwili.json | 4 +- wiliwili/include/view/mpv_core.hpp | 18 ++++++-- wiliwili/source/view/mpv_core.cpp | 24 +++++++--- wiliwili/source/view/video_view.cpp | 68 +++++++++++++++++++--------- 5 files changed, 82 insertions(+), 34 deletions(-) diff --git a/library/borealis b/library/borealis index 780bd59c0..a88b835d7 160000 --- a/library/borealis +++ b/library/borealis @@ -1 +1 @@ -Subproject commit 780bd59c004323f4e00f518ad796ddf54fa9e12d +Subproject commit a88b835d72093c28020e282ae64aacfbf3f7f42a diff --git a/resources/i18n/zh-Hans/wiliwili.json b/resources/i18n/zh-Hans/wiliwili.json index 7065ed176..d39b662d2 100644 --- a/resources/i18n/zh-Hans/wiliwili.json +++ b/resources/i18n/zh-Hans/wiliwili.json @@ -167,10 +167,10 @@ "player": { "intro": "查看简介", "p": "分集", - "related": "推薦", + "related": "推荐", "uploaded": "投稿", "qr": "手机扫码观看/分享", - "comment": "評論", + "comment": "评论", "current": "人正在看", "share": "分享", "rights": "未经作者授权,禁止转载", diff --git a/wiliwili/include/view/mpv_core.hpp b/wiliwili/include/view/mpv_core.hpp index 4c8463aeb..1c54c5a7d 100644 --- a/wiliwili/include/view/mpv_core.hpp +++ b/wiliwili/include/view/mpv_core.hpp @@ -50,7 +50,7 @@ class DanmakuItem { bool showing = false; bool canShow = true; float length = 0; - int line = 0; + int line = 0; // 弹幕在屏幕上的行数 float speed = 0; int64_t startTime = 0; NVGcolor color = nvgRGBA(255, 255, 255, 160); @@ -63,6 +63,10 @@ class DanmakuItem { inline static std::vector> lines = std::vector>(20, {0, 0}); + + bool operator<(const DanmakuItem &item) const { + return this->time < item.time; + } }; class MPVCore : public Singleton { @@ -103,6 +107,11 @@ class MPVCore : public Singleton { return ret == 1; } + double getPlaybackTime() { + get_property("pause", MPV_FORMAT_DOUBLE, &this->playback_time); + return this->playback_time; + } + void setUrl(std::string url) { const char *cmd[] = {"loadfile", url.c_str(), NULL}; command_async(cmd); @@ -133,15 +142,18 @@ class MPVCore : public Singleton { void reset(); + void resetDanmakuPosition(); + // core states int core_idle = 0; int64_t duration = 0; // second int64_t cache_speed = 0; // Bps double playback_time = 0; int64_t video_progress = 0; + bool showDanmaku = false; + bool danmakuLoaded = false; + size_t danmakuIndex = 0; // 当前显示的第一条弹幕序号 std::vector danmakuData; - bool showDanmaku = false; - bool danmakuLoaded = false; // Bottom progress bar inline static bool BOTTOM_BAR = true; diff --git a/wiliwili/source/view/mpv_core.cpp b/wiliwili/source/view/mpv_core.cpp index 40a28f94a..789600d95 100644 --- a/wiliwili/source/view/mpv_core.cpp +++ b/wiliwili/source/view/mpv_core.cpp @@ -535,9 +535,9 @@ void MPVCore::eventMainLoop() { void MPVCore::loadDanmakuData(const std::vector &data) { this->danmakuData.clear(); - danmakuLoaded = true; - //todo: 可能出现异步问题 + danmakuLoaded = true; this->danmakuData = std::move(data); + std::sort(danmakuData.begin(), danmakuData.end()); mpvCoreEvent.fire(MpvEventEnum::DANMAKU_LOADED); } @@ -553,14 +553,26 @@ void MPVCore::reset() { this->danmakuLoaded = false; } +void MPVCore::resetDanmakuPosition() { + danmakuIndex = 0; + for (auto &i : danmakuData) { + i.showing = false; + i.canShow = true; + } + for (int k = 0; k < 20; k++) { + DanmakuItem::lines[k].first = 0; + DanmakuItem::lines[k].second = 0; + } +} + /// Danmaku DanmakuItem::DanmakuItem(const std::string &content, const char *attributes) : msg(std::move(content)) { #ifdef OPENCC - static bool skip = brls::Application::getLocale() == brls::LOCALE_ZH_HANS || - brls::Application::getLocale() == brls::LOCALE_ZH_CN; - if (!skip && brls::Label::OPENCC_ON) msg = brls::Label::STConverter(msg); + static bool ZH_T = brls::Application::getLocale() == brls::LOCALE_ZH_HANT || + brls::Application::getLocale() == brls::LOCALE_ZH_TW; + if (ZH_T && brls::Label::OPENCC_ON) msg = brls::Label::STConverter(msg); #endif auto attrs = pystring::split(attributes, ",", 3); time = atof(attrs[0].c_str()); @@ -569,7 +581,7 @@ DanmakuItem::DanmakuItem(const std::string &content, const char *attributes) fontColor = atoi(attrs[3].c_str()); int r = (fontColor >> 16) & 0xff, g = (fontColor >> 8) & 0xff, b = fontColor & 0xff; - color = nvgRGBA(r, g, b, 220); + color = nvgRGBA(r, g, b, 200); if ((r * 299 + g * 587 + b * 114) < 60000) { borderColor = nvgRGBA(255, 255, 255, 160); } diff --git a/wiliwili/source/view/video_view.cpp b/wiliwili/source/view/video_view.cpp index 69a1ac119..727ecfa44 100644 --- a/wiliwili/source/view/video_view.cpp +++ b/wiliwili/source/view/video_view.cpp @@ -38,7 +38,7 @@ VideoView::VideoView() { }); this->registerAction( - "-10s", brls::ControllerButton::BUTTON_LB, + "\uE08F", brls::ControllerButton::BUTTON_LB, [this](brls::View* view) -> bool { mpvCore->command_str("seek -10"); return true; @@ -46,7 +46,7 @@ VideoView::VideoView() { false, true); this->registerAction( - "+10s", brls::ControllerButton::BUTTON_RB, + "\uE08E", brls::ControllerButton::BUTTON_RB, [this](brls::View* view) -> bool { mpvCore->command_str("seek +10"); return true; @@ -210,45 +210,65 @@ void VideoView::draw(NVGcontext* vg, float x, float y, float width, //取出需要的弹幕 uint64_t currentTime = getCPUTimeUsec(); float bounds[4]; - for (auto& i : mpvCore->danmakuData) { - if (i.isShown) continue; - if (!i.canShow) continue; - if (i.showing) { - float position = - i.speed * (currentTime - i.startTime) / 1000000; - if (position > width + i.length) { - i.isShown = true; + for (size_t j = mpvCore->danmakuIndex; j < mpvCore->danmakuData.size(); + j++) { + auto& i = mpvCore->danmakuData[j]; + if (!i.canShow) continue; // 溢出屏幕外 + if (i.showing) { // 正在展示中 + float position = 0; + if (mpvCore->core_idle) { + // 暂停状态弹幕也要暂停 + position = i.speed * (mpvCore->playback_time - i.time); + i.startTime = + currentTime - (mpvCore->playback_time - i.time) * 1e6; + } else { + position = i.speed * (currentTime - i.startTime) / 1e6; + } + + // 根据时间或位置判断是否显示弹幕 + if (position > width + i.length || + i.time + SECOND < mpvCore->playback_time) { + i.showing = false; + mpvCore->danmakuIndex = j + 1; continue; } + // 画弹幕文字包边 nvgFillColor(vg, a(i.borderColor)); nvgText(vg, x + width - position + 1, y + i.line * LINE_HEIGHT + 1, i.msg.c_str(), nullptr); + // 画弹幕文字 nvgFillColor(vg, a(i.color)); nvgText(vg, x + width - position, y + i.line * LINE_HEIGHT, i.msg.c_str(), nullptr); continue; } - if (mpvCore->playback_time > i.time) { + if (i.time < mpvCore->playback_time) { + if (i.time + SECOND < mpvCore->playback_time) { + mpvCore->danmakuIndex = j + 1; + continue; + } i.showing = true; nvgTextBounds(vg, 0, 0, i.msg.c_str(), nullptr, bounds); i.length = bounds[2] - bounds[0]; i.speed = (width + i.length) / SECOND; i.canShow = false; for (int k = 0; k < LINES; k++) { - if (i.time > DanmakuItem::lines[k].first && - i.time + width / i.speed > - DanmakuItem::lines[k].second) { - i.line = k; - DanmakuItem::lines[k].first = - i.time + i.length / i.speed; - DanmakuItem::lines[k].second = i.time + SECOND; - i.canShow = true; - i.startTime = getCPUTimeUsec(); - break; - } + if (i.time < DanmakuItem::lines[k].first || + i.time + width / i.speed < DanmakuItem::lines[k].second) + continue; + i.line = k; + DanmakuItem::lines[k].first = i.time + i.length / i.speed; + DanmakuItem::lines[k].second = i.time + SECOND; + i.canShow = true; + i.startTime = getCPUTimeUsec(); + if (mpvCore->playback_time - i.time > 0.2) + i.startTime -= (mpvCore->playback_time - i.time) * 1e6; + break; } + } else { + break; } } @@ -423,6 +443,9 @@ void VideoView::setFullScreen(bool fs) { return; } + // 让下一次显示弹幕时刷新正在显示的弹幕位置 + mpvCore->resetDanmakuPosition(); + brls::Logger::info("VideoView set fullscreen state: {}", fs); if (fs) { this->unRegisterMpvEvent(); @@ -529,6 +552,7 @@ void VideoView::registerMpvEvent() { break; case MpvEventEnum::LOADING_END: this->hideLoading(); + mpvCore->resetDanmakuPosition(); break; case MpvEventEnum::MPV_STOP: // todo: 当前播放结束,尝试播放下一个视频