[源码级解析]解决Aegisub3.2.2 MacOS版本音量/缩放滑块无法使用的BUG
本文完整阅读约需 26 分钟,如时间较长请考虑收藏后慢慢阅读~
Aegisub是一款简单好用的开源字幕制作软件,广受字幕制作者欢迎。但Aegisub官方最新版本是2014年更新的3.2.2版本,距今已有6年历史,存在着大量未修复的BUG与兼容性问题。其中MacOS下的Aegisub存在一个致命的BUG,即波形视图右侧的音量/缩放滑块无法正常使用,只能在0%和100%两者间调整,导致要么看不到波形(听不到音频),要么波形爆满(严重削波)。本文将分析该问题存在的原因,并给出一个修复该问题的编译版本,便于字幕制作者正常使用。
0x01 问题重现
正常情况下,波形图右边的滑块应该如图所示,从左至右分别为水平缩放、垂直缩放与音量。
但在最新的MacOS系统中,使用3.2.2版本的Aegisub会发现滑块变成了如图所示的样子,不仅无法正常滑动,而且只有0%与100%两个状态,严重影响使用。
0x02 分析问题
Aegisub是一款开放源代码软件,因此我首先想到的是查看其源代码。在它的GitHub页面中,我找到了这三个滑块所在的源码:src/audio_box.cpp。
其中新建这三个滑块的代码如下所示:
AudioBox::AudioBox(wxWindow *parent, agi::Context *context)
: wxSashWindow(parent, -1, wxDefaultPosition, wxDefaultSize, wxSW_3D | wxCLIP_CHILDREN)
, controller(context->audioController.get())
, context(context)
, audio_open_connection(context->audioController->AddAudioPlayerOpenListener(&AudioBox::OnAudioOpen, this))
, panel(new wxPanel(this, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxBORDER_RAISED))
, audioDisplay(new AudioDisplay(panel, context->audioController.get(), context))
, HorizontalZoom(new wxSlider(panel, Audio_Horizontal_Zoom, -OPT_GET("Audio/Zoom/Horizontal")->GetInt(), -50, 30, wxDefaultPosition, wxSize(-1, 20), wxSL_VERTICAL|wxSL_BOTH))
, VerticalZoom(new wxSlider(panel, Audio_Vertical_Zoom, OPT_GET("Audio/Zoom/Vertical")->GetInt(), 0, 100, wxDefaultPosition, wxSize(-1, 20), wxSL_VERTICAL|wxSL_BOTH|wxSL_INVERSE))
, VolumeBar(new wxSlider(panel, Audio_Volume, OPT_GET("Audio/Volume")->GetInt(), 0, 100, wxDefaultPosition, wxSize(-1, 20), wxSL_VERTICAL|wxSL_BOTH|wxSL_INVERSE))
{
// Other codes
}
可以看到控制三个滑块的属性名称分别为HorizontalZoom
、VerticalZoom
和VolumeBar
,都是wxWidget
中的wxSlider
控件。
为了重现故障,我新建了一个wxWidgets
工程,使用了类似的方法放置了三个控件,代码如下所示:
Simple::Simple(const wxString& title)
: wxFrame(nullptr, wxID_ANY, title, wxDefaultPosition, wxSize(250, 150))
{
Centre();
this->SetBackgroundColour(wxColour(47, 47, 47));
auto *panel = new wxPanel(this, -1, wxDefaultPosition, wxDefaultSize);
auto *HorizontalZoom = new wxSlider(panel, -1, 0, -50, 50, wxDefaultPosition, wxSize(-1, 20), wxSL_VERTICAL|wxSL_BOTH);
HorizontalZoom->SetBackgroundColour(wxColour(255, 255, 255));
}
得到如图所示的结果:
因为我在这里特别给滑块设置了白色的背景,可以直观看到,滑块的轨道已经完全不可见,难怪无法滑动。
参考wxSlider
控件的手册,设置该控件宽高的参数为第七个参数,即上面代码中的wxSize(-1, 20)
,其类型为wxSize
类型,接受宽度和高度两个参数。
继续参考wxSize
控件的手册,我们可以看到这两个参数都可以为-1,即表示默认宽高。那我们不妨将两个值都设置为-1
试试看?设置后我得到了如下图所示的结果:
滑块居然恢复正常了!
0x03 思考问题
上面我们提到了,将wxSlider
控件的宽高都设置为-1即默认后,滑块的宽高恢复了正常。那么为什么将高度设置为20的时候就缩小了呢?
为了继续探索,我将20修改为了100,即尺寸参数变为了wxSize(-1, 100)
,得到了如下图所示的结果:
这个时候滑块的实际高度是多少呢?我使用QQ的截图工具测量了一下它的尺寸:
可以看到,高度是100个像素,和我们所设置的完全一致。
如果将宽度设置成50个像素,我们可以得到如下图所示的结果,这进一步验证了我们的想法:
继续阅读Aegisub相关源码,可以发现它使用了BoxSizer布局模式(类似于CSS中盒式布局)。于是我仿造着继续撰写了如下代码:
Centre();
this->SetBackgroundColour(wxColour(47, 47, 47));
auto *panel = new wxPanel(this, -1, wxDefaultPosition, wxSize(40, 100));
auto *HorizontalZoom = new wxSlider(panel, -1, 0, -50, 50, wxDefaultPosition, wxSize(-1, 20),
wxSL_VERTICAL | wxSL_BOTH | wxSL_INVERSE);
HorizontalZoom->SetBackgroundColour(wxColour(255, 255, 255));
wxSizer *box = new wxBoxSizer(wxHORIZONTAL);
box->Add(HorizontalZoom, 1, wxEXPAND, 0);
panel->SetSizer(box);
此处可以清晰看到,滑块的样式为横向。但我们的的确确设置的样式参数为wxSL_VERTICAL
。文档中并未看到关于样式改变的内容,那么这极有可能是一个BUG。
为证实猜想,我继续参考Aegisub的源码,补全了另外两个滑块,得到的结果与Aegisub的BUG极为相似:
上面的实验充分说明了Aegisub波形图右侧滑块的故障原因,即使用wxSize()
设置滑块尺寸情况下滑块变为横向,且宽高均为最小值导致其滑轨消失。
由于我手头没有找到2014年发布的Mac OS X Yosemite可供测试,无法证实其故障出现的时间。但既然知道问题出现的原因,不妨先解决它。
0x04 解决问题
继续阅读wxSlider
的文档,可以看到第七个参数的默认值为wxDefaultSize
,其含义同wxSize(-1, -1)
,我们将前文代码中的尺寸参数设置为wxDefaultSize
后运行,看到了正常的结果:
由于在BoxSizer布局情况下,控件默认填充到盒内,因此设置尺寸不是必需项。而设置为wxDefaultSize
或wxSize(-1, -1)
能保证该BUG不再出现,这就是解决问题的最简单方法。
知道了解决问题的方法,我将Aegisub3.2.2版本的源码下载了下来,修改了三个滑块的尺寸配置为wxDefaultSize
,然后配置编译环境进行编译,最终得到了正常的结果,问题得到解决。
0x05 软件分享
由于该软件使用C++开发,编译环境配置较为复杂,且考虑到Aegisub的用户大多不是程序员,因此我将修复后的软件进行构建与打包,分享给需要的读者:链接
0x06 后记
本篇文章撰写完成后,我尝试着搜索了一下此BUG,在Aegisub的GitHub Issues中找到了一个Issue:macOS: Audio volume/zoom sliders are broken。这个Issue最终被一个Patch解决,但由于未发布新版本,未能在正式版中得到修复,其diff如下所示:
From 3bc5e8f04f097ce70056be18f9919f643c0e37cb Mon Sep 17 00:00:00 2001
From: Thomas Goyne <[email protected]>
Date: Fri, 7 Jul 2017 16:46:52 -0700
Subject: [PATCH] Remove pointless explicit heights for the audio sliders
The containing sizer overrides them instantly, but for whatever reason
supplying them breaks things on macOS.
---
src/audio_box.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/audio_box.cpp b/src/audio_box.cpp
index 8d45c83bb..4d1f1518f 100644
--- a/src/audio_box.cpp
+++ b/src/audio_box.cpp
@@ -63,9 +63,9 @@ AudioBox::AudioBox(wxWindow *parent, agi::Context *context)
, audio_open_connection(context->audioController->AddAudioPlayerOpenListener(&AudioBox::OnAudioOpen, this))
, panel(new wxPanel(this, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxBORDER_RAISED))
, audioDisplay(new AudioDisplay(panel, context->audioController.get(), context))
-, HorizontalZoom(new wxSlider(panel, Audio_Horizontal_Zoom, -OPT_GET("Audio/Zoom/Horizontal")->GetInt(), -50, 30, wxDefaultPosition, wxSize(-1, 20), wxSL_VERTICAL|wxSL_BOTH))
-, VerticalZoom(new wxSlider(panel, Audio_Vertical_Zoom, OPT_GET("Audio/Zoom/Vertical")->GetInt(), 0, 100, wxDefaultPosition, wxSize(-1, 20), wxSL_VERTICAL|wxSL_BOTH|wxSL_INVERSE))
-, VolumeBar(new wxSlider(panel, Audio_Volume, OPT_GET("Audio/Volume")->GetInt(), 0, 100, wxDefaultPosition, wxSize(-1, 20), wxSL_VERTICAL|wxSL_BOTH|wxSL_INVERSE))
+, HorizontalZoom(new wxSlider(panel, Audio_Horizontal_Zoom, -OPT_GET("Audio/Zoom/Horizontal")->GetInt(), -50, 30, wxDefaultPosition, wxDefaultSize, wxSL_VERTICAL|wxSL_BOTH))
+, VerticalZoom(new wxSlider(panel, Audio_Vertical_Zoom, OPT_GET("Audio/Zoom/Vertical")->GetInt(), 0, 100, wxDefaultPosition, wxDefaultSize, wxSL_VERTICAL|wxSL_BOTH|wxSL_INVERSE))
+, VolumeBar(new wxSlider(panel, Audio_Volume, OPT_GET("Audio/Volume")->GetInt(), 0, 100, wxDefaultPosition, wxDefaultSize, wxSL_VERTICAL|wxSL_BOTH|wxSL_INVERSE))
{
SetSashVisible(wxSASH_BOTTOM, true);
Bind(wxEVT_SASH_DRAGGED, &AudioBox::OnSashDrag, this);
可以看到,该Patch的解决方法与本文所述完全一致,不同的是本文在修复后进行了构建打包,便于用户直接使用。
太太太太!太感谢了!编程小白自己真的无法解决,感谢大佬分享
站主下载链接打不开啦,502 Bad Gateway。T_T
你好,最近在做服务器迁移,我发到您的邮箱。
高手高手之高高手,我也遇到了,苦于不懂编程,多谢大佬