# 电台 **Repository Path**: deepin20/dtbox ## Basic Information - **Project Name**: 电台 - **Description**: 电台 (dtbox):基于Qt + DTK的轻量电台播放器,专为 Deepin / 统信 UOS 桌面打造。 士无双的电台 (dtbox)仓库地址:https://gitee.com/shiwushuang9/dtbox - **Primary Language**: C++ - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-11 - **Last Updated**: 2026-09-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 电台 (dtbox) 基于 **Qt + DTK** 的轻量电台播放器,专为 Deepin / 统信 UOS 桌面打造。 士无双的电台 (dtbox)仓库地址:https://gitee.com/shiwushuang9/dtbox 一套源码同时支持两代国产桌面栈,由 CMake 自动探测: | 桌面栈 | 适用系统 | 说明 | |---|---|---| | **Qt6 + DTK6** | Deepin 23、统信 UOS 25 | 优先使用 | | **Qt5 + DTK5** | 统信 UOS 20(eagle)、Deepin 20 | 自动回落,Qt 5.11 起即可构建 | ## 特性 - 无外部播放器依赖:内置 QMediaPlayer 播放 HLS 电台流 - 原生 Deepin 界面:DMainWindow / DListView / 主题图标 - 我的收藏:点击电台行右侧星标收藏,数据保存在 `~/.config/dtbox/dtbox.conf` - 台标自动加载(QNetworkAccessManager,4 路并发 + 内存缓存) - 播放动画:正在播放的电台行显示跳动均衡条动画 - 双击电台播放,再次双击同一电台暂停/继续(默认音量 100%) ## 构建依赖(Debian / Deepin / UOS) 按目标系统择一安装即可,CMake 会自动选用: ```bash # Deepin 23 / UOS 25(Qt6 + DTK6) sudo apt install \ cmake pkg-config \ qt6-base-dev qt6-multimedia-dev \ libdtk6core-dev libdtk6gui-dev libdtk6widget-dev # UOS 20 / Deepin 20(Qt5 + DTK5) sudo apt install \ cmake pkg-config \ qtbase5-dev qtmultimedia5-dev \ libdtkcore-dev libdtkgui-dev libdtkwidget-dev ``` > `debian/control` 的 `Build-Depends` 已写成 `qt6-* | qt5-*` 备选形式, > 两代系统上都能直接 `dpkg-buildpackage`。 ## 统信 UOS 适配说明 UOS 20(eagle)自带的是 Qt 5.11.3 + DTK 5.6,与 Qt6/DTK6 存在若干 API 差异, 全部收敛在 `src/qtcompat.h`,业务代码不做版本判断: | 差异点 | Qt6 / DTK6 | Qt5 / DTK5 | 处理方式 | |---|---|---|---| | 播放源 | `setSource(QUrl)` | `setMedia(QMediaContent)` | `DtboxCompat::setPlayerSource()` | | 播放状态 | `QMediaPlayer::PlaybackState` | `QMediaPlayer::State` | 别名 `DtboxPlaybackState` | | 状态变化信号 | `playbackStateChanged` | `stateChanged` | `DtboxCompat::connectPlaybackStateChanged()` | | 播放错误信号 | `errorOccurred(err, str)` | `error(err)` + `errorString()` | `DtboxCompat::connectPlayerError()` | | 音量 | `QAudioOutput`(0.0–1.0) | `QMediaPlayer::setVolume()`(0–100) | `DtboxCompat::initAudioOutput()` | | 请求超时 | `setTransferTimeout()` | Qt 5.15 起才有,5.11 无 | 改用挂在 reply 上的单次 `QTimer` | | 命名空间 | — | `DGuiApplicationHelper` 属 Gui 命名空间 | 显式补 `DGUI_USE_NAMESPACE` | | 翻译目录 | `QLibraryInfo::path()` | `QLibraryInfo::location()`(Qt6 已移除) | `DtboxCompat::translationsPath()` | 播放后端:Qt5 构建需要 GStreamer 媒体服务插件才能出声,故包内已 `Recommends: libqt5multimedia5-plugins`。 ## 界面语言 界面默认显示**简体中文**: - 中文系统跟随系统变体(zh_CN / zh_TW / zh_HK); - 其余情况(含 `LANG` 未设置、locale 为 C/POSIX)一律使用简体中文—— 本应用的界面文字是直接写成中文的,没有任何英文改写版,混用只会更糟。 dtbox 自己的字符串不需要翻译,但**标题栏菜单**(帮助 / 关于 / 退出)和 **标准对话框按钮**(确定 / 取消)分别是 DTK、Qt 提供的词条,必须显式装载翻译文件 才会是中文,否则会回落成英文源码串(Help / About / Exit)。`main.cpp` 因此做了两件事: 1. `app.loadTranslator({界面语言})` —— 装载 DTK 词条(`/usr/share/dtk5/DWidget/translations/dtkwidget_.qm`); 2. 自己再装载 Qt 词条包 `qtbase` / `qtmultimedia` / `qt` —— Dtk 只在系统语言受支持时才加载这部分,语言未设置时会漏掉, 造成「菜单已是中文、对话框按钮还是 OK / Cancel」的混搭。 翻译必须在**创建窗口之前**装载:`DTitlebar` 的默认菜单是随窗口一起建出来的, 窗口建完再装就晚了(已建出的菜单不会自动重译)。启动日志会打印实际生效的语言: ``` 界面语言: zh_CN | 已装载 Qt 词条包: 2 ``` > 用的是系统自带翻译文件(`libqt5core5a` / `libdtkwidget5` 等包提供),本包不自带 `.qm`。 > 若日志显示的语言不是中文,检查 `LANG` / `LC_ALL` 以及上述翻译文件是否存在。 ## 构建与安装 默认安装前缀为 `/opt/dtbox`(可在 cmake 时用 `-DCMAKE_INSTALL_PREFIX=` 覆盖): ```bash cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/dtbox cmake --build build -j$(nproc) sudo cmake --install build ``` ## 打包 deb ```bash ./build-deb.sh # 自动探测桌面栈 + 编译 + 打包,产物输出到 dist/ ``` 脚本会自动识别本机是 Qt6/DTK6 还是 Qt5/DTK5,选择对应的依赖清单,并在打包后 用 `dpkg-deb -c` 逐条校验包内是否为预期的 `/opt/dtbox` 布局。 或手动执行: ```bash dpkg-buildpackage -b -us -uc # 无 dpkg 数据库的精简环境(容器/精简系统):除了 -d 跳过包依赖检查, # 还要给 dpkg-genbuildinfo 一个隔离的空数据库 —— 它必须读 /status, # 否则整条构建会在最后一步以退出码 25 中止(此时 deb 其实已经打好, # 只是 .buildinfo / .changes 出不来)。脚本已自动处理,手动时照下面写: ADM=$(mktemp -d); : > "$ADM/status" dpkg-buildpackage -b -us -uc -d --buildinfo-option=--admindir="$ADM" ``` > 自动化构建时建议加 `-nc`(跳过 `dh_clean`):如果宿主对批量删除有配额限制, > `dh_clean` 清 `obj-*/` 上百个文件可能被拦;先自己清干净再上 `-nc` 更稳。 > **只安装 `dist/dtbox_*.deb`。** 本包**不会**产出 `dtbox-dbgsym` 调试符号包。 > debhelper 13 的 `dh_strip` 默认会额外生成它,而它带有 > `Depends: dtbox (= 同一版本)`,单独安装必然报「依赖关系不满足:dtbox」; > 它本应投递到独立的调试归档(ddebs),个人自用包不需要也无处存放。 > 由 `debian/rules` 的 `override_dh_strip`(`--no-automatic-dbgsym`)保证不再生成。 > 需要符号调试时再临时去掉该 override 重新构建。 > **依赖解析不依赖 dpkg 数据库。** `debian/shlibs.local` 显式声明了本项目链接的 > Qt5/DTK5 运行库到 Debian 包的映射(版本下界即代码实际要求的 API 级别: > Qt 5.11 / DTK 5.6 / glibc 2.28)。因此在 `/var/lib/dpkg` 缺失的精简构建环境里, > `dh_shlibdeps` 依然能生成完整的 `Depends:`,不需要人工补写。该文件只覆盖列出的 > 库,未列出的(如 Qt6 构建下的 `libQt6Core.so.6`)仍走系统 shlibs。 ### 安装后的文件布局 | 路径 | 内容 | |---|---| | `/opt/dtbox/bin/dtbox` | 可执行程序 | | `/opt/dtbox/share/dtbox/radioData.json` | 电台数据 | | `/opt/dtbox/share/applications/dtbox.desktop` | 桌面入口(`Exec=/opt/dtbox/bin/dtbox`) | | `/opt/dtbox/share/icons/hicolor/scalable/apps/diantai.svg` | 图标 | | `/usr/share/applications/dtbox.desktop` | → 软链到上面对应的 desktop 文件 | | `/usr/share/icons/hicolor/scalable/apps/diantai.svg` | → 软链到上面对应的图标 | 所有实际文件都在 `/opt/dtbox` 下,`/usr/share` 里只有两个软链(由 `debian/dtbox.links` 声明),用于让桌面启动器和图标主题能发现这个应用。 不需要任何 `/usr` 条目时,删掉 `debian/dtbox.links` 即可,改为给会话设置 `XDG_DATA_DIRS=/opt/dtbox/share`。 > 说明:按 Debian 政策 `/opt` 不应用于打包(lintian 会给出 `dir-or-file-in-opt` 提示), > 本项目为个人自用包(`X-Deepin-Vendor=user-custom`),故按要求安装到 `/opt/dtbox`。 > `/usr/bin` 下未放软链,命令行调用请使用完整路径或自行把 `/opt/dtbox/bin` 加入 `PATH`。 ## 数据 电台列表内置在二进制中(`res/radioData.json`),并随包安装到 `/opt/dtbox/share/dtbox/radioData.json`。程序按以下顺序查找,先命中者生效: 1. `~/.local/share/dtbox/radioData.json`(用户自定义) 2. `/opt/dtbox/share/dtbox/radioData.json`(随包安装) 3. `/usr/share/dtbox/radioData.json`(旧版布局兼容) 4. 二进制内置资源 `:/data/radioData.json`(兜底) 当前数据含 44 个分类、699 个电台。 ## 开源许可 本项目基于 **GPL-3.0-or-later** 协议完全开源,详见 [LICENSE](LICENSE)。 ## 更新记录 ### v1.1.8-1 - **修复界面菜单显示英文**:`main.cpp` 现在会显式装载界面语言的中文翻译。 标题栏菜单(帮助 / 关于 / 退出)与标准对话框按钮(确定 / 取消)都是 DTK、Qt 提供的词条,不装载翻译就会回落成英文源码串(Help / About / Exit)—— 这是本应用"菜单是英文"的唯一原因,应用自身的字符串本来就是中文 - 界面语言默认简体中文:中文系统跟随系统变体(zh_CN / zh_TW / zh_HK), 其余情况(含 `LANG` 未设置导致 locale 为 C/POSIX)一律简体中文 - 额外显式装载 Qt 自身词条包(`qtbase` / `qtmultimedia` / `qt`):Dtk 只在系统语言 受支持时才加载这部分,语言未设置时会漏掉,造成「菜单已是中文、按钮还是 OK」的混搭 - 翻译在创建窗口之前装载(`DTitlebar` 菜单随窗口创建,晚装无效),并在启动日志 打印实际生效的语言便于排查 - `qtcompat.h` 新增 `translationsPath()`,收敛 Qt6 的 `QLibraryInfo::path()` 与 Qt5 的 `location()` 差异 ### v1.1.7-2 - **不再生成 `dtbox-dbgsym` 调试符号包**(`override_dh_strip --no-automatic-dbgsym`)。 它 `Depends: dtbox (= 同版本)`,单独安装必然报「依赖关系不满足:dtbox」, 且本应投递到独立调试归档,留在产物里只会让软件包安装器困惑;正常 strip 不受影响 - 新增 `debian/shlibs.local`,显式声明 Qt5/DTK5 运行库到包的映射。 此前的假设"没有 dpkg 数据库也能正常解析 `Depends:`"是错的——`dh_shlibdeps` 会以 `no dependency information found for ... libQt5Multimedia.so.5` 中止; 现在依赖解析与环境无关 - `build-deb.sh`:修正产物搬运的文件名匹配(原 glob `dtbox_*` 匹配不到 `dtbox-dbgsym_*`,调试包会散落到源码目录上级),并新增"只允许产出一个 deb"的自检 ### v1.1.7-1 - **适配统信 UOS 20**:一套源码同时支持 Qt6/DTK6 与 Qt5/DTK5,CMake 自动探测 - 新增 `src/qtcompat.h`,集中收敛两代 Qt/DTK 的 API 差异 - 修复 Qt 5.11 无 `setTransferTimeout` 导致的台标请求无超时问题(改用定时器) - 补 `DGUI_USE_NAMESPACE`,DTK5 下 `DGuiApplicationHelper` 才可见 - 构建依赖改为 Qt6/Qt5 备选,两代系统均可直接打包 - 修复 `dh_auto_install` 在单二进制包时安装目录与 `debian/dtbox.install` 不一致的问题 - 软链改由 `debian/dtbox.links` 声明;包内新增播放后端 `Recommends` ### v1.1.6-1 - 打包改为安装到 `/opt/dtbox`,桌面入口与图标仍在 `/usr/share` - 版本号单一来源:由 CMake 注入,不再与源码手写版本脱节 - 修复:切换分类后双击同一电台会误播列表首项 - 修复:台标下载无并发限制(现 4 路并发 / 单图重试 2 次 / 10 秒超时) - 修复:收藏星标点击未判空;空列表提示改为随窗口自适应 - 优化:台标占位图与圆角裁剪结果缓存;动画计时器仅在播放时运行 ### v1.1.5-1 - 移除底部播放条(播放/暂停按钮、音量条),音量固定 100% - 修复:暂停后恢复无声问题(直播流“暂停”改为断开连接,“恢复”重新连接直播) - 双击当前播放电台改为暂停/继续,不再重新开始