/*
|
* Copyright (c) 2010-2020 Belledonne Communications SARL.
|
*
|
* This file is part of linphone-iphone
|
*
|
* This program is free software: you can redistribute it and/or modify
|
* it under the terms of the GNU General Public License as published by
|
* the Free Software Foundation, either version 3 of the License, or
|
* (at your option) any later version.
|
*
|
* This program is distributed in the hope that it will be useful,
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* GNU General Public License for more details.
|
*
|
* You should have received a copy of the GNU General Public License
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
*/
|
|
#import "CallSideMenuView.h"
|
#import "LinphoneManager.h"
|
#import "PhoneMainView.h"
|
|
@implementation CallSideMenuView {
|
NSTimer *updateTimer;
|
}
|
|
#pragma mark - ViewController Functions
|
|
- (void)viewWillAppear:(BOOL)animated {
|
[super viewWillAppear:animated];
|
if (updateTimer != nil) {
|
[updateTimer invalidate];
|
}
|
updateTimer = [NSTimer scheduledTimerWithTimeInterval:1
|
target:self
|
selector:@selector(updateStats:)
|
userInfo:nil
|
repeats:YES];
|
|
[self updateStats:nil];
|
}
|
|
- (void)viewWillDisappear:(BOOL)animated {
|
[super viewWillDisappear:animated];
|
if (updateTimer != nil) {
|
[updateTimer invalidate];
|
updateTimer = nil;
|
}
|
}
|
|
- (IBAction)onLateralSwipe:(id)sender {
|
[PhoneMainView.instance.mainViewController hideSideMenu:YES];
|
}
|
|
+ (NSString *)iceToString:(LinphoneIceState)state {
|
switch (state) {
|
case LinphoneIceStateNotActivated:
|
return NSLocalizedString(@"Not activated", @"ICE has not been activated for this call");
|
break;
|
case LinphoneIceStateFailed:
|
return NSLocalizedString(@"Failed", @"ICE processing has failed");
|
break;
|
case LinphoneIceStateInProgress:
|
return NSLocalizedString(@"In progress", @"ICE process is in progress");
|
break;
|
case LinphoneIceStateHostConnection:
|
return NSLocalizedString(@"Direct connection",
|
@"ICE has established a direct connection to the remote host");
|
break;
|
case LinphoneIceStateReflexiveConnection:
|
return NSLocalizedString(
|
@"NAT(s) connection",
|
@"ICE has established a connection to the remote host through one or several NATs");
|
break;
|
case LinphoneIceStateRelayConnection:
|
return NSLocalizedString(@"Relay connection", @"ICE has established a connection through a relay");
|
break;
|
}
|
}
|
|
+ (NSString*)afinetToString:(int)remote_family {
|
return (remote_family == LinphoneAddressFamilyUnspec) ? @"Unspecified":(remote_family == LinphoneAddressFamilyInet) ? @"IPv4" : @"IPv6";
|
}
|
|
+ (NSString *)mediaEncryptionToString:(LinphoneMediaEncryption)enc {
|
switch (enc) {
|
case LinphoneMediaEncryptionDTLS:
|
return @"DTLS";
|
case LinphoneMediaEncryptionSRTP:
|
return @"SRTP";
|
case LinphoneMediaEncryptionZRTP:
|
return @"ZRTP";
|
case LinphoneMediaEncryptionNone:
|
break;
|
}
|
return NSLocalizedString(@"None", nil);
|
}
|
|
- (NSString *)updateStatsForCall:(LinphoneCall *)call stream:(LinphoneStreamType)stream {
|
NSMutableString *result = [[NSMutableString alloc] init];
|
const PayloadType *payload = NULL;
|
const LinphoneCallStats *stats;
|
const LinphoneCallParams *params = linphone_call_get_current_params(call);
|
NSString *name;
|
|
switch (stream) {
|
case LinphoneStreamTypeAudio:
|
name = @"Audio";
|
payload = linphone_call_params_get_used_audio_codec(params);
|
stats = linphone_call_get_audio_stats(call);
|
break;
|
case LinphoneStreamTypeText:
|
name = @"Text";
|
payload = linphone_call_params_get_used_text_codec(params);
|
stats = linphone_call_get_text_stats(call);
|
break;
|
case LinphoneStreamTypeVideo:
|
name = @"Video";
|
payload = linphone_call_params_get_used_video_codec(params);
|
stats = linphone_call_get_video_stats(call);
|
break;
|
case LinphoneStreamTypeUnknown:
|
break;
|
}
|
if (payload == NULL) {
|
return result;
|
}
|
|
[result appendString:@"\n"];
|
[result appendString:name];
|
[result appendString:@"\n"];
|
|
[result appendString:[NSString stringWithFormat:@"Codec: %s/%iHz", payload->mime_type, payload->clock_rate]];
|
if (stream == LinphoneStreamTypeAudio) {
|
[result appendString:[NSString stringWithFormat:@"/%i channels", payload->channels]];
|
}
|
[result appendString:@"\n"];
|
// Encoder & decoder descriptions
|
const char *enc_desc = ms_factory_get_encoder(linphone_core_get_ms_factory(LC), payload->mime_type)->text;
|
const char *dec_desc = ms_factory_get_decoder(linphone_core_get_ms_factory(LC), payload->mime_type)->text;
|
if (strcmp(enc_desc, dec_desc) == 0) {
|
[result appendString:[NSString stringWithFormat:@"Encoder/Decoder: %s", enc_desc]];
|
[result appendString:@"\n"];
|
} else {
|
[result appendString:[NSString stringWithFormat:@"Encoder: %s", enc_desc]];
|
[result appendString:@"\n"];
|
[result appendString:[NSString stringWithFormat:@"Decoder: %s", dec_desc]];
|
[result appendString:@"\n"];
|
}
|
|
if (stats != NULL) {
|
[result appendString:[NSString stringWithFormat:@"Download bandwidth: %1.1f kbits/s",
|
linphone_call_stats_get_download_bandwidth(stats)]];
|
[result appendString:@"\n"];
|
[result appendString:[NSString stringWithFormat:@"Upload bandwidth: %1.1f kbits/s",
|
linphone_call_stats_get_upload_bandwidth(stats)]];
|
[result appendString:@"\n"];
|
if (stream == LinphoneStreamTypeVideo) {
|
/*[result appendString:[NSString stringWithFormat:@"Estimated download bandwidth: %1.1f kbits/s",
|
linphone_call_stats_get_estimated_download_bandwidth(stats)]];
|
[result appendString:@"\n"];*/
|
}
|
[result
|
appendString:[NSString stringWithFormat:@"ICE state: %@",
|
[self.class iceToString:linphone_call_stats_get_ice_state(stats)]]];
|
[result appendString:@"\n"];
|
[result
|
appendString:[NSString
|
stringWithFormat:@"Afinet: %@",
|
[self.class afinetToString:linphone_call_stats_get_ip_family_of_remote(
|
stats)]]];
|
[result appendString:@"\n"];
|
|
// RTP stats section (packet loss count, etc)
|
const rtp_stats_t rtp_stats = *linphone_call_stats_get_rtp_stats(stats);
|
[result
|
appendString:[NSString stringWithFormat:
|
@"RTP packets: %llu total, %lld cum loss, %llu discarded, %llu OOT, %llu bad",
|
rtp_stats.packet_recv, rtp_stats.cum_packet_loss, rtp_stats.discarded,
|
rtp_stats.outoftime, rtp_stats.bad]];
|
[result appendString:@"\n"];
|
[result appendString:[NSString stringWithFormat:@"Sender loss rate: %.2f%%",
|
linphone_call_stats_get_sender_loss_rate(stats)]];
|
[result appendString:@"\n"];
|
[result appendString:[NSString stringWithFormat:@"Receiver loss rate: %.2f%%",
|
linphone_call_stats_get_receiver_loss_rate(stats)]];
|
[result appendString:@"\n"];
|
|
if (stream == LinphoneStreamTypeVideo) {
|
const LinphoneVideoDefinition *recv_definition = linphone_call_params_get_received_video_definition(params);
|
const LinphoneVideoDefinition *sent_definition = linphone_call_params_get_sent_video_definition(params);
|
float sentFPS = linphone_call_params_get_sent_framerate(params);
|
float recvFPS = linphone_call_params_get_received_framerate(params);
|
[result appendString:[NSString stringWithFormat:@"Sent video resolution: %dx%d (%.1fFPS)", linphone_video_definition_get_width(sent_definition),
|
linphone_video_definition_get_height(sent_definition), sentFPS]];
|
[result appendString:@"\n"];
|
[result appendString:[NSString stringWithFormat:@"Received video resolution: %dx%d (%.1fFPS)",
|
linphone_video_definition_get_width(recv_definition),
|
linphone_video_definition_get_height(recv_definition), recvFPS]];
|
[result appendString:@"\n"];
|
}
|
}
|
return result;
|
}
|
|
- (void)updateStats:(NSTimer *)timer {
|
LinphoneCall *call = linphone_core_get_current_call(LC);
|
|
if (!call) {
|
_statsLabel.text = NSLocalizedString(@"No call in progress", nil);
|
return;
|
}
|
|
NSMutableString *stats = [[NSMutableString alloc] init];
|
|
LinphoneMediaEncryption enc = linphone_call_params_get_media_encryption(linphone_call_get_current_params(call));
|
if (enc != LinphoneMediaEncryptionNone) {
|
[stats appendString:[NSString
|
stringWithFormat:@"Call encrypted using %@", [self.class mediaEncryptionToString:enc]]];
|
}
|
|
[stats appendString:[self updateStatsForCall:call stream:LinphoneStreamTypeAudio]];
|
[stats appendString:[self updateStatsForCall:call stream:LinphoneStreamTypeVideo]];
|
[stats appendString:[self updateStatsForCall:call stream:LinphoneStreamTypeText]];
|
|
_statsLabel.text = stats;
|
}
|
|
@end
|