Переключатель громкоговорителя iOS pjsip 2.2 не работает

Во время разговора я пытаюсь переключить голос с внутреннего динамика на громкий на устройстве iOS с помощью библиотеки pjsip 2.2. Он возвращает TRUE как успех, но физически он не меняет назначение звука.

Я использую следующий код

- (BOOL)setLoud:(BOOL)loud {
if (loud) {
    @try {

        pjmedia_aud_dev_route route = PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER;

        pj_status_t pj_status =   pjsua_snd_set_setting(PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE,
                                                        &route, PJ_TRUE);
        if (pj_status == PJ_SUCCESS) {
          return YES;
        }
        else
        {
            return NO;
        }

    }
    @catch (NSException *exception) {
        return NO;
    }
} else {
    @try {
        pjmedia_aud_dev_route route = PJMEDIA_AUD_DEV_ROUTE_EARPIECE;

        pj_status_t pj_status =   pjsua_snd_set_setting(PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE,
                                                        &route, PJ_TRUE);
        if (pj_status == PJ_SUCCESS) {
            return YES;
        }
        else
        {
            return NO;
        }
    }
    @catch (NSException *exception) {
        return NO;
    }
}
}

Не могли бы вы предложить, как мы можем сделать эту работу?

1 ответ

С появлением iOS 7 теперь вы должны использовать AVAudioSession для управления любым аудио менеджментом. Мне потребовалось много времени, чтобы наконец заставить это работать, но я наконец понял проблему, почему мой звук не был автоматически направлен на динамик iPhone. Проблема в том, что когда вы отвечаете на вызов, pjsip автоматически переопределяет AVAudioSessionPortOverride, который я выполнял до ответа на вызов. Чтобы решить эту проблему, вам просто нужно переопределить выходной аудиопорт ПОСЛЕ ответа на вызов.

Чтобы приложение VoIP работало эффективно в фоновом режиме, я решил обработать маршрутизацию звука с помощью специального метода обратного вызова с именем on_call_state. Этот метод on_call_state вызывается pjsip, когда состояние вызова изменилось. Как вы можете прочитать здесь, http://www.pjsip.org/pjsip/docs/html/group__PJSIP__INV.htm, есть много разных флагов, которые вы можете проверить при изменении состояния вызова. Состояния, которые я использовал в этом примере: PJSIP_INV_STATE_CONNECTING и PJSIP_INV_STATE_DISCONNECTED.

PJSIP_INV_STATE_CONNECTING вызывается, когда аудиовызов соединяется с другим узлом.

PJSIP_INV_STATE_DISCONNECTED вызывается, когда аудиовызов заканчивается другим партнером.

static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
{
    pjsua_call_info ci;

    PJ_UNUSED_ARG(e);

    pjsua_call_get_info(call_id, &ci);
    PJ_LOG(3,(THIS_FILE, "Call %d state=%.*s", call_id,
              (int)ci.state_text.slen,
              ci.state_text.ptr));
    if (ci.state == PJSIP_INV_STATE_CONNECTING) {
        BOOL success;
        AVAudioSession *session = [AVAudioSession sharedInstance];
        NSError *error = nil;

        success = [session setCategory:AVAudioSessionCategoryPlayAndRecord
                           withOptions:AVAudioSessionCategoryOptionMixWithOthers
                                 error:&error];
        if (!success) NSLog(@"AVAudioSession error setCategory: %@", [error localizedDescription]);

        success = [session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&error];
        if (!success) NSLog(@"AVAudioSession error overrideOutputAudioPort: %@", [error localizedDescription]);

        success = [session setActive:YES error:&error];
        if (!success) NSLog(@"AVAudioSession error setActive: %@", [error localizedDescription]);
    } else if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
        BOOL success;
        AVAudioSession *session = [AVAudioSession sharedInstance];
        NSError *error = nil;

        success = [session setActive:NO error:&error];
        if (!success) NSLog(@"AVAudioSession error setActive: %@", [error localizedDescription]);
    }
}
Другие вопросы по тегам