Переключатель громкоговорителя 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]);
}
}