Документация
ОС Аврора 5.2.1
CallFactoryInterface
Ниже приведены фрагменты кода или же цельные файлы, которые реализуют класс CallFactoryInterface. Данный класс используется вместе с AudioContext и CallManager.
-
.spec-файл:
// Указываем зависимость для сборки: требуется библиотека callservice для работы с аудио и вызовами BuildRequires: pkgconfig(callservice) -
.CMake-файл:
# Ищем модуль callservice с помощью pkg-config и создаем импортированную цель PkgConfig::CALLSERVICE pkg_check_modules(CALLSERVICE REQUIRED IMPORTED_TARGET callservice) ... # Линкуем найденную библиотеку callservice с нашим целевым проектом в приватном режиме target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::CALLSERVICE ) ... -
src/audio/audiocallmanager.cpp:using ru::auroraos::call::AudioContext; using ru::auroraos::call::Call; using ru::auroraos::call::CallManager; using ru::auroraos::call::CallFactoryInterface; // Пользовательская схема URI для идентификации вызовов данного приложения static const auto SCHEME = QStringLiteral("ruauroraoscallapicomponents.://"); // Фабрика для создания объектов вызовов. Наследуется от CallFactoryInterface. class AudioCallFactory : public CallFactoryInterface { // Переопределенный метод создания нового вызова Call *newCall(CallManager *manager, const QString &id, const QVariantMap ¶meters, QObject *parent) override { // Безопасно приводим базовый менеджер к нашему специфичному типу AudioCallManager AudioCallManager *ourManager = qobject_cast<AudioCallManager *>(manager); if (ourManager) { // Создаем и возвращаем новый экземпляр AudioCall, передавая флаг активности генератора звука return new AudioCall(manager, id, parameters, ourManager->audioGeneratorActive(), parent); } return nullptr; } }; // Создаем глобальный статический экземпляр фабрики вызовов для использования во всем приложении Q_GLOBAL_STATIC(AudioCallFactory, audioCallFactory); // Конструктор менеджера аудио-вызовов AudioCallManager::AudioCallManager(const QString &accountId, bool customIcon, QObject *parent) // Инициализируем базовый класс CallManager. Если customIcon=true, передаем путь к SVG-иконке, иначе пустую строку : CallManager(accountId, customIcon ? Aurora::Application::pathTo("qml/assets/icon-l-checksums.svg").toLocalFile() : "", parent) , m_audioContext(this) // Инициализируем контекст аудио, передавая текущий объект как родительский , m_callId(1) // Начальный идентификатор для нумерации вызовов , m_holdable(true) // По умолчанию вызовы можно ставить на удержание , m_redialable(true) // По умолчанию включена возможность повторного вызова { // Устанавливаем нашу кастомную фабрику для создания объектов вызовов setCallFactory(audioCallFactory); } // Метод создания нового вызова с заданными свойствами Call *AudioCallManager::newCall(QVariantMap &properties) { // Не разрешаем вызовы с пустым remoteHandle (неизвестно, кому звоним) QString remoteHandle = properties[QStringLiteral("remoteHandle")].value<QString>(); if (remoteHandle.isEmpty()) return nullptr; // Если не предоставлено удобочитаемое remoteName, используем в его качестве remoteHandle QString remoteName = properties[QStringLiteral("remoteName")].value<QString>(); if (remoteName.isEmpty()) properties[QStringLiteral("remoteName")] = remoteHandle; // Устанавливаем флаг, приветствуются ли вызовы метода SetHold() для этого вызова properties[QStringLiteral("holdable")] = m_holdable; // Заполняем имя и дескриптор локальной учетной записи properties[QStringLiteral("localHandle")] = QStringLiteral("CallExample"); properties[QStringLiteral("localName")] = QStringLiteral("CallExample"); // Если повторный вызов разрешен, формируем URI вызова if (m_redialable) properties[QStringLiteral("uri")] = SCHEME + remoteHandle; // Генерируем уникальный строковый идентификатор для вызова и инкрементируем счетчик QString id = QString::number(m_callId++); // Создаем вызов через базовый класс CallManager auto call = CallManager::newCall(id, properties); // Добавляем к вызову интерфейс управления аудио (audioManager) call->addInterfaces({ audioManager() }); return call; } // Метод инициирования исходящего вызова Call *AudioCallManager::initiateCall(const QVariantMap &props) { QVariantMap properties(props); // Явно указываем, что вызов является исходящим properties[QStringLiteral("incoming")] = false; return newCall(properties); } // Метод регистрации входящего вызова Call *AudioCallManager::reportIncomingCall(const QVariantMap &props) { QVariantMap properties(props); // Явно указываем, что вызов является входящим properties[QStringLiteral("incoming")] = true; return newCall(properties); } // Метод завершения и удаления всех активных вызовов void AudioCallManager::disconnectAll() { // Проходим по всем активным вызовам и удаляем их for (const auto &call : calls()) { removeCall(call); } // Сбрасываем счетчик идентификаторов вызовов m_callId = 1; } // Обработчик открытия пользовательского URI (например, при клике на ссылку или номер) void AudioCallManager::openUri(const QString &uri) { // Проверяем, соответствует ли URI нашей кастомной схеме if (uri.startsWith(SCHEME)) { QString tmp(uri); // Извлекаем номер (handle) из URI, удаляя префикс схемы const QString handle = tmp.replace(SCHEME, QStringLiteral("")); if (!handle.isEmpty()) { // Проверяем, не существует ли уже вызов с таким URI for (const auto &call : calls()) { if (uri == getCall(call)->uri()) { // Вызов уже настроен и активен. // Здесь должна быть логика показа соответствующей страницы интерфейса. qInfo() << "отображаем текущий вызов" << getCall(call)->callId(); return; } } // Если вызова нет, готовим свойства для нового исходящего вызова QVariantMap properties; properties[QStringLiteral("incoming")] = false; properties[QStringLiteral("remoteHandle")] = handle; // TODO: В будущем извлечь remoteName непосредственно из URI. properties[QStringLiteral("remoteName")] = QStringLiteral("Исходящий вызов ") + handle; // Создаем новый вызов newCall(properties); return; } } // Логируем предупреждение, если URI не соответствует ожидаемому формату qWarning() << "Неверный URI" << uri; } // Геттер: поддерживает ли менеджер постановку вызовов на удержание bool AudioCallManager::holdable() const { return m_holdable; } // Сеттер: изменяет флаг поддержки удержания и уведомляет об изменении void AudioCallManager::setHoldable(bool on) { if (on != m_holdable) { m_holdable = on; emit holdableChanged(on); } } // Геттер: поддерживает ли менеджер повторный набор номера bool AudioCallManager::redialable() const { return m_redialable; } // Сеттер: изменяет флаг поддержки повторного набора и уведомляет об изменении void AudioCallManager::setRedialable(bool on) { if (m_redialable != on) { m_redialable = on; emit redialableChanged(on); } } // Геттер: активна ли генерация тональных сигналов (читается из настроек) bool AudioCallManager::audioGeneratorActive() const { return m_settings.value("audio/generateTone", true).value<bool>(); } // Сеттер: изменяет настройку генерации тонов, сохраняет её и уведомляет об изменении void AudioCallManager::setAudioGeneratorActive(bool on) { if (on != audioGeneratorActive()) { m_settings.setValue("audio/generateTone", on); emit audioGeneratorActiveChanged(on); } } // Геттер: используется ли кастомная иконка для вызовов (читается из настроек) bool AudioCallManager::useCallIcon() const { return m_settings.value("ui/customIcon", true).value<bool>(); } // Сеттер: изменяет настройку использования иконки, сохраняет её и уведомляет об изменении void AudioCallManager::setUseCallIcon(bool on) { if (on != useCallIcon()) { m_settings.setValue("ui/customIcon", on); emit useCallIconChanged(on); } } // Метод безопасного приведения базового указателя Call к специфичному типу AudioCall AudioCall *AudioCallManager::getAudioCall(const QString &callId) const { return qobject_cast<AudioCall*>(getCall(callId)); }