MacroSIP
EnglishРусский中文

Участие

MacroSIP распространяется под GPLv2 или новее (PJSIP — GPLv2+, ADR 0007); любой вклад принимается под этой лицензией, а любой встроенный сторонний код должен быть совместим с GPL. Ошибки и пожелания — на https://github.com/HSMM/MacroSIP/issues. Прежде чем трогать код, прочитайте docs/DEVELOPMENT.md (инженерные заметки), docs/ROADMAP.md (что выпущено и что дальше), docs/GLOSSARY.md (используйте его термины в коде и документации), ADR в docs/adr/ и спецификацию UI docs/design/SCREENS.md вместе с docs/design/mockups.html.

Рабочий процесс (ADR 0008)

Работа организована по вехам из docs/ROADMAP.md. Каждая задача начинается с письменного задания: цель, границы, файлы, критерии готовности и уже известные факты; задания самодостаточны. Каждая веха проходит независимое ревью тем, кто не писал код (ошибки, гонки, утечки, работа со связкой ключей и TLS), затем проверку: сборка, тесты, самопроверка по loopback и звонок на настоящем SIP-аккаунте. Код UI начинается только после утверждения макетов. Принятые решения не пересматриваются молча: чтобы изменить одно из них, добавьте новый ADR (docs/adr/README.md: Context, Decision, Consequences; после принятия не редактируется, кроме строки «Superseded by»). Не добавляйте зависимости без ADR.

Откройте pull request в main; CI должен пройти и в задании arm64, и в задании Intel (см. Тесты). Держите docs/design/SCREENS.md, mockups.html и docs/DEVELOPMENT.md в соответствии с кодом, который вы меняете, в том же pull request.

Правила кода

Добавить строку

  1. Добавьте static var или func в L с ключом через точку и английским значением по умолчанию, как у существующего 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. Добавьте элемент управления на вкладку в Views/Settings/ (каждая вкладка — PaneContainer шириной 680 pt) через model.updateSettings { $0... = ... }.
  4. Строки в L и на обоих языках; опишите элемент и его состояния в docs/design/SCREENS.md и обновите mockups.html, если раскладка вкладки меняется.
  5. Демонстрационное состояние в Model/DemoState.swift, если у элемента есть состояние, достойное снимка.

Добавить кодек

  1. third_party/pjsip/config_site.h: задайте PJMEDIA_HAS_<NAME>_CODEC 1 (и, если у configure pjproject есть флаг --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. Engine.optionalCodecs в MacroSIPCore (идентификаторы, показываемые после G.711, с приоритетом 0, пока не включены) и CodecCatalog в Views/Settings/CodecsPane.swift (all, onByDefault; он добавляет идентификаторы, которых нет в сохранённом порядке).
  4. Тесты: тест перечисления идентификаторов и loopback-звонок, согласующий кодек (образец — Engine262Tests), плюс шаг самопроверки «codecs».

Без G.729 (bcg729 остаётся выключенным); сборка описана в ADR 0002 и ADR 0012.

Добавить тип источника справочника

Из docs/DIRECTORY.md:

  1. Добавьте вариант в DirectorySourceKind и, если у него есть настройки, структуру конфигурации Codable с терпимым init(from:) (каждый ключ необязателен) и поле в 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; StubDirectoryProvider в DirectoryServiceTests.swift покрывает сторону сервиса.
  5. UI: список типов и поля в Views/Directory/DirectorySourceSheet.swift, строки, раздел 13 SCREENS.md и демонстрационное состояние directory-sheet-<kind>.

Сообщения коммитов

Простой английский, настоящее время, что и почему. Первая строка называет область и изменение (Engine: retry REGISTER with backoff after a transport error, Settings: Network pane with the RTP port range); тело объясняет причину, когда она не очевидна. Без трейлеров. Коммитьте каждую законченную часть вместе с относящейся к ней документацией.

См. также Устройство, Сборка, Тесты, Релизы.

Другие страницы: Главная · Home (English)