Документация
ОС Аврора 5.2.1

CallFactoryInterface

Ниже приведены фрагменты кода или же цельные файлы, которые реализуют класс CallFactoryInterface. Данный класс используется вместе с AudioContext и CallManager.

  1. .spec-файл:

    // Указываем зависимость для сборки: требуется библиотека callservice для работы с аудио и вызовами
    BuildRequires:  pkgconfig(callservice)
    
  2. .CMake-файл:

    # Ищем модуль callservice с помощью pkg-config и создаем импортированную цель PkgConfig::CALLSERVICE
    pkg_check_modules(CALLSERVICE REQUIRED IMPORTED_TARGET callservice)
    ...
    # Линкуем найденную библиотеку callservice с нашим целевым проектом в приватном режиме
    target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::CALLSERVICE )
    ...
    
  3. 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 &parameters,
                    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));
    }
    

Мы используем cookies для персонализации сайта и его более удобного использования. Вы можете запретить cookies в настройках браузера.

Пожалуйста ознакомьтесь с политикой использования файлов cookies.