MacroSIP
EnglishРусский中文

参与贡献

MacroSIP 采用 GPLv2 或更新版本(PJSIP 为 GPLv2+,ADR 0007);任何贡献都在该许可证下接受,任何捆绑的第三方代码必须与 GPL 兼容。错误和功能请求请提交到 https://github.com/HSMM/MacroSIP/issues。动手改代码之前,请阅读 docs/DEVELOPMENT.md(工程说明)、docs/ROADMAP.md(已交付和即将到来的内容)、docs/GLOSSARY.md(在代码和文档中使用其术语)、docs/adr/ 中的 ADR,以及 UI 规范 docs/design/SCREENS.md 和 docs/design/mockups.html。

工作流程(ADR 0008)

工作按 docs/ROADMAP.md 中的里程碑组织。每个任务从一份书面简报开始:目标、边界、文件、完成标准和已知事实;简报是自成一体的。每个里程碑都由未编写该代码的人独立评审(错误、竞争条件、泄漏、钥匙串和 TLS 处理),然后验证:构建、测试、环回自测以及在真实 SIP 账户上的一次通话。UI 代码只在样稿获批后才开始编写。已确定的决策不会被悄悄推翻:要更改一项决策,请添加新的 ADR(docs/adr/README.md:Context、Decision、Consequences;接受后除“Superseded by”一行外永不编辑)。没有 ADR 不要添加依赖。

针对 main 创建拉取请求;CI 必须在 arm64 和 Intel 两个作业上都通过(见 测试)。在同一个拉取请求中保持 docs/design/SCREENS.md、mockups.html 和 docs/DEVELOPMENT.md 与您更改的代码同步。

编码规则

添加字符串

  1. 向 L 添加一个带点分键和英文默认值的 static var 或 func,如现有的 static var tabsContacts: String { loc("tabs.contacts", "Contacts") }。插值对文本使用 %@,对整数使用 %lld;有两个或更多参数时,在两个文件中都使用 %1$@、%2$@。
  2. 将键添加到 Resources/en.lproj/Localizable.strings 和 Resources/ru.lproj/Localizable.strings。
  3. 计数(联系人、通话、条目)改放到 Localizable.stringsdict,英语用 one/other,俄语用 one/few/many/other;同一个键绝不出现在两个文件中。
  4. 运行 scripts/check-strings.sh。

产品、编解码器和协议名称(SIP、SRTP、TLS、STUN、ICE、DTMF、REGISTER)、诊断报告和日志行不翻译。检查俄语下的布局:dist/MacroSIP.app/Contents/MacOS/MacroSIP --demo-state contacts -AppleLanguages "(ru)"。

添加设置项

  1. 在 Sources/MacroSIPCore/Model/AppSettings.swift 中正确的结构体(GeneralSettings、AudioSettings、RecordingSettings、AutoAnswerSettings、NetworkSettings、CallOptions、CodecOptions、QuickKeysSettings、DirectorySettings)里添加字段,带默认值和宽容的 init(from:),并在 SettingsCompatTests 中添加一个值测试,确认旧的 settings.json 仍能解码。
  2. 应用它:引擎侧的选项通过 AppModel+Engine.swift(applyCallOptions、applyCodecOptions、scheduleNetworkApply;需要重新启动的网络字段列在 NetworkSettings.needsRestart(from:) 中)。
  3. 使用 model.updateSettings { $0... = ... } 将控件添加到 Views/Settings/ 中的面板(每个面板是一个 680 pt 宽的 PaneContainer)。
  4. 在 L 和两种语言中添加字符串;在 docs/design/SCREENS.md 中描述该控件及其状态,如果面板布局变化则更新 mockups.html。
  5. 如果该控件有值得截图的状态,在 Model/DemoState.swift 中添加一个演示状态。

添加编解码器

  1. third_party/pjsip/config_site.h:设置 PJMEDIA_HAS_<NAME>_CODEC 1(并且,如果 pjproject 的 configure 有 --disable-<name>-codec 标志,确保 scripts/build-pjsip.sh 没有传入它;当 configure 禁用了某个预期的编解码器或缺少编解码器归档时,脚本已经会失败)。重新运行 scripts/build-pjsip.sh:PJSIP 为两个架构重新构建,OpenSSL 和 Opus 保持缓存。
  2. Package.swift:将归档添加到 pjsipLibraries,保持与 third_party/pjsip/LINKFLAGS 同步;然后 rm -rf .build 和 swift build。
  3. MacroSIPCore 中的 Engine.optionalCodecs(显示在 G.711 之后的 id,启用前优先级保持为 0)和 Views/Settings/CodecsPane.swift 中的 CodecCatalog(all、onByDefault;它会追加已存储顺序中缺少的 id)。
  4. 测试:一个 id 列表测试和一个协商该编解码器的环回通话(Engine262Tests 展示了模式),加上自测的“codecs”步骤。

没有 G.729(bcg729 保持禁用);构建见 ADR 0002 和 ADR 0012。

添加目录来源类型

来自 docs/DIRECTORY.md:

  1. 向 DirectorySourceKind 添加 case,如果它有设置,则添加一个带宽容 init(from:)(每个键都可选)的 Codable 配置结构体,以及 DirectorySource 上一个用 try? 解码的字段,这样损坏的配置不会丢掉整个设置文件。
  2. 实现 DirectoryProvider(保有缓存时为 actor,否则为 struct):search 返回最多 limit 个条目,lookup 使用 DirectoryNumber.matches,test 返回 .connected(entries:),allEntries 返回用于导入的全部内容。抛出 DirectoryError;.signInRequired 将来源置于“需要登录”。对于本地列表,构建一个 DirectoryIndex。
  3. 从 DirectoryService.defaultProvider 返回它。机密通过 DirectoryCredentials,绝不进入 settings.json。
  4. 测试放在 Directory*Tests.swift 文件中;DirectoryServiceTests.swift 中的 StubDirectoryProvider 覆盖服务侧。
  5. UI:Views/Directory/DirectorySourceSheet.swift 中的类型弹出式菜单和字段、字符串、SCREENS.md 第 13 节,以及一个 directory-sheet-<kind> 演示状态。

提交信息

简明英文,现在时,说明做了什么和为什么。第一行点明领域和更改(Engine: retry REGISTER with backoff after a transport error、Settings: Network pane with the RTP port range);原因不明显时在正文中解释。不加 trailer。每完成一部分就提交,包括随之而来的文档。

另见 架构、构建、测试、发布。

其他页面:首页 · Home (English)