presence: implement long term presence

This commit is contained in:
Gautier Pelloux-Prayer 2016-07-22 15:26:28 +02:00
parent 1f52e83715
commit 29fe24eef3
23 changed files with 2013 additions and 1756 deletions

View file

@ -25,6 +25,39 @@
if (_person) {
[self loadProperties];
const char* key = [NSString stringWithFormat:@"ab%d", ABRecordGetRecordID(aperson)].UTF8String;
// try to find friend associated with that person
_friend = linphone_friend_list_find_friend_by_ref_key(linphone_core_get_default_friend_list(LC), key);
if (!_friend) {
_friend = linphone_friend_ref(linphone_core_create_friend(LC));
linphone_friend_set_ref_key(_friend, key);
linphone_friend_set_name(_friend, [NSString stringWithFormat:@"%@ %@", _firstName, _lastName].UTF8String);
for (NSString* sipAddr in _sipAddresses) {
LinphoneAddress* addr = linphone_core_interpret_url(LC, sipAddr.UTF8String);
if (addr) {
linphone_address_set_display_name(addr, [self displayName].UTF8String);
linphone_friend_add_address(_friend, addr);
linphone_address_destroy(addr);
}
}
for (NSString* phone in _phoneNumbers) {
LOGI(@"fixme! use linphone_friend_add_phone_number for phone numbers");
char* normalized_phone = linphone_proxy_config_normalize_phone_number(linphone_core_get_default_proxy_config(LC), phone.UTF8String);
if (normalized_phone) {
LinphoneAddress* addr = linphone_core_interpret_url(LC, normalized_phone);
if (addr) {
linphone_address_set_display_name(addr, [self displayName].UTF8String);
linphone_friend_add_address(_friend, addr);
linphone_address_destroy(addr);
}
ms_free(normalized_phone);
}
// linphone_friend_add_phone_number(_friend, phone.UTF8String);
}
linphone_core_add_friend(LC, _friend);
}
linphone_friend_ref(_friend);
} else if (_friend) {
[self loadFriend];
} else {
@ -59,6 +92,12 @@
}
- (NSString *)displayName {
if (_friend) {
const char *dp = linphone_address_get_display_name(linphone_friend_get_address(_friend));
if (dp)
return [NSString stringWithUTF8String:dp];
}
if (_person != nil) {
NSString *lFirstName = CFBridgingRelease(ABRecordCopyValue(_person, kABPersonFirstNameProperty));
NSString *lLocalizedFirstName = [FastAddressBook localizedLabel:lFirstName];
@ -77,10 +116,6 @@
} else {
return (NSString *)lLocalizedOrganization;
}
} else if (_friend) {
const char *dp = linphone_address_get_display_name(linphone_friend_get_address(_friend));
if (dp)
return [NSString stringWithUTF8String:dp];
}
if (_lastName || _firstName) {

View file

@ -50,6 +50,7 @@ extern NSString *const kLinphoneBluetoothAvailabilityUpdate;
extern NSString *const kLinphoneConfiguringStateUpdate;
extern NSString *const kLinphoneGlobalStateUpdate;
extern NSString *const kLinphoneNotifyReceived;
extern NSString *const kLinphoneNotifyPresenceReceived;
extern NSString *const kLinphoneCallEncryptionChanged;
extern NSString *const kLinphoneFileTransferSendUpdate;
extern NSString *const kLinphoneFileTransferRecvUpdate;

View file

@ -66,6 +66,7 @@ NSString *const kLinphoneBluetoothAvailabilityUpdate = @"LinphoneBluetoothAvaila
NSString *const kLinphoneConfiguringStateUpdate = @"LinphoneConfiguringStateUpdate";
NSString *const kLinphoneGlobalStateUpdate = @"LinphoneGlobalStateUpdate";
NSString *const kLinphoneNotifyReceived = @"LinphoneNotifyReceived";
NSString *const kLinphoneNotifyPresenceReceived = @"LinphoneNotifyPresenceReceived";
NSString *const kLinphoneCallEncryptionChanged = @"LinphoneCallEncryptionChanged";
NSString *const kLinphoneFileTransferSendUpdate = @"LinphoneFileTransferSendUpdate";
NSString *const kLinphoneFileTransferRecvUpdate = @"LinphoneFileTransferRecvUpdate";
@ -1041,6 +1042,17 @@ static void linphone_iphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev
content:body];
}
- (void)onNotifyPresenceReceived:(LinphoneCore *)lc friend:(LinphoneFriend *)lf {
// Post event
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:[NSValue valueWithPointer:lf] forKey:@"friend"];
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneNotifyPresenceReceived object:self userInfo:dict];
}
static void linphone_iphone_notify_presence_received(LinphoneCore *lc, LinphoneFriend *lf) {
[(__bridge LinphoneManager *)linphone_core_get_user_data(lc) onNotifyPresenceReceived:lc friend:lf];
}
static void linphone_iphone_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on,
const char *authentication_token) {
[(__bridge LinphoneManager *)linphone_core_get_user_data(lc) onCallEncryptionChanged:lc
@ -1326,7 +1338,7 @@ void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReach
static LinphoneCoreVTable linphonec_vtable = {
.call_state_changed = (LinphoneCoreCallStateChangedCb)linphone_iphone_call_state,
.registration_state_changed = linphone_iphone_registration_state,
.notify_presence_received = NULL,
.notify_presence_received = linphone_iphone_notify_presence_received,
.new_subscription_requested = NULL,
.auth_info_requested = linphone_iphone_popup_password_request,
.message_received = linphone_iphone_message_received,
@ -1420,6 +1432,8 @@ static LinphoneCoreVTable linphonec_vtable = {
linphone_core_enable_video_capture(theLinphoneCore, FALSE);
}
[self enableProxyPublish:YES];
LOGI(@"Linphone [%s] started on [%s]", linphone_core_get_version(), [[UIDevice currentDevice].model UTF8String]);
// Post event
@ -1666,10 +1680,42 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
LOGI(@"Long running task started, remaining [%g s] because at least one call is paused",
[[UIApplication sharedApplication] backgroundTimeRemaining]);
}
- (void)enableProxyPublish:(BOOL)enabled {
if (linphone_core_get_global_state(LC) != LinphoneGlobalOn || !linphone_core_get_default_friend_list(LC)) {
LOGW(@"Not changing presence configuration because linphone core not ready yet");
return;
}
if ([self lpConfigBoolForKey:@"publish_presence"]) {
// set present to "tv", because "available" does not work yet
if (enabled) {
linphone_core_set_presence_model(
LC, linphone_core_create_presence_model_with_activity(LC, LinphonePresenceActivityTV, NULL));
}
const MSList *proxies = linphone_core_get_proxy_config_list(LC);
while (proxies) {
LinphoneProxyConfig *cfg = proxies->data;
linphone_proxy_config_edit(cfg);
linphone_proxy_config_enable_publish(cfg, enabled);
linphone_proxy_config_done(cfg);
proxies = proxies->next;
}
// force registration update first, then update friend list subscription
linphone_core_iterate(theLinphoneCore);
}
linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(LC), enabled);
}
- (BOOL)enterBackgroundMode {
LinphoneProxyConfig *proxyCfg = linphone_core_get_default_proxy_config(theLinphoneCore);
BOOL shouldEnterBgMode = FALSE;
// disable presence
[self enableProxyPublish:NO];
// handle proxy config if any
if (proxyCfg) {
const char *refkey = proxyCfg ? linphone_proxy_config_get_ref_key(proxyCfg) : NULL;
@ -1724,7 +1770,7 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
LOGI(@"Entering [%s] bg mode", shouldEnterBgMode ? "normal" : "lite");
if (!shouldEnterBgMode) {
const char *refkey = linphone_proxy_config_get_ref_key(proxyCfg);
const char *refkey = proxyCfg ? linphone_proxy_config_get_ref_key(proxyCfg) : NULL;
BOOL pushNotifEnabled = (refkey && strcmp(refkey, "push_notification") == 0);
if (pushNotifEnabled) {
LOGI(@"Keeping lc core to handle push");
@ -1740,6 +1786,8 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
}
- (void)becomeActive {
// enable presence
[self refreshRegisters];
if (pausedCallBgTask) {
[[UIApplication sharedApplication] endBackgroundTask:pausedCallBgTask];
@ -1765,6 +1813,8 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
LOGW(@"keepalive handler was called for the last time at %@", datestr);
}
}
[self enableProxyPublish:YES];
}
- (void)beginInterruption {

View file

@ -0,0 +1,14 @@
//
// UIAvatarPresence.h
// linphone
//
// Created by Gautier Pelloux-Prayer on 12/04/16.
//
//
@interface UIAvatarPresence : UIRoundedImageView
@property(nonatomic, setter=setFriend:) LinphoneFriend *friend;
@property(nonatomic, readonly) UIImageView *presenceImage;
@end

View file

@ -0,0 +1,85 @@
//
// UIAvatarPresence.m
// linphone
//
// Created by Gautier Pelloux-Prayer on 12/04/16.
//
//
#import "UIAvatarPresence.h"
@implementation UIAvatarPresence
INIT_WITH_COMMON_CF {
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(onPresenceChanged:)
name:kLinphoneNotifyPresenceReceived
object:nil];
if (!_presenceImage) {
_presenceImage = [[UIImageView alloc] init];
_presenceImage.tag = 883;
[self addSubview:_presenceImage];
}
CGSize s = self.frame.size;
int is = MIN(s.width, s.height);
// place it in bottom right corner
_presenceImage.frame = CGRectMake(.5 * (s.width - is) + .7 * is, .5 * (s.height - is) + .7 * is, .2 * is, .2 * is);
_presenceImage.image = [UIImage imageNamed:@"presence_unregistered"];
return self;
}
- (void)dealloc {
[NSNotificationCenter.defaultCenter removeObserver:self];
};
- (void)setFrame:(CGRect)frame {
[super setFrame:frame];
CGSize s = self.frame.size;
int is = MIN(s.width, s.height);
// place it in bottom right corner
_presenceImage.frame = CGRectMake(.5 * (s.width - is) + .7 * is, .5 * (s.height - is) + .7 * is, .2 * is, .2 * is);
}
- (void)onPresenceChanged:(NSNotification *)k {
LinphoneFriend *f = [[k.userInfo valueForKey:@"friend"] pointerValue];
// only consider event if it's about us
if (!_friend ||
!linphone_address_weak_equal(linphone_friend_get_address(f), linphone_friend_get_address(_friend))) {
return;
}
[self updatePresenceImage];
}
- (void)updatePresenceImage {
LinphonePresenceBasicStatus basic =
_friend ? linphone_presence_model_get_basic_status(linphone_friend_get_presence_model(_friend))
: LinphonePresenceBasicStatusClosed;
const LinphonePresenceModel *model = _friend ? linphone_friend_get_presence_model(_friend) : NULL;
LinphonePresenceActivity *activity =
model ? linphone_presence_model_get_activity(model) ?: LinphonePresenceActivityOffline : NULL;
LOGE(@"Friend %s status is now %s/%s since %@", _friend ? linphone_friend_get_name(_friend) : "NULL",
basic == LinphonePresenceBasicStatusOpen ? "open" : "closed", linphone_presence_activity_to_string(activity),
[NSDate dateWithTimeIntervalSince1970:linphone_presence_model_get_timestamp(model)]);
NSString *imageName;
if (basic == LinphonePresenceBasicStatusClosed) {
imageName =
(_friend && linphone_friend_is_presence_received(_friend)) ? @"presence_away" : @"presence_unregistered";
} else if (linphone_presence_activity_get_type(activity) == LinphonePresenceActivityTV) {
imageName = @"presence_online";
} else {
imageName = @"presence_away";
}
_presenceImage.image = [UIImage imageNamed:imageName];
}
- (void)setFriend:(LinphoneFriend *) friend {
_friend = friend;
[self updatePresenceImage];
}
@end

View file

@ -52,7 +52,7 @@
- (void)setContact:(Contact *)acontact {
_contact = acontact;
[ContactDisplay setDisplayNameLabel:_nameLabel forContact:_contact];
_linphoneImage.hidden = !([FastAddressBook contactHasValidSipDomain:_contact]);
_linphoneImage.hidden = ! (_contact.friend && linphone_presence_model_get_basic_status(linphone_friend_get_presence_model(_contact.friend)) == LinphonePresenceBasicStatusOpen);
}
#pragma mark -

View file

@ -170,8 +170,11 @@ static void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info
const MSList *friends = linphone_friend_list_get_friends(fl);
while (friends) {
LinphoneFriend *f = friends->data;
Contact *contact = [[Contact alloc] initWithFriend:f];
[self registerAddrsFor:contact];
// only append friends that are not native contacts (already added above)
if (linphone_friend_get_ref_key(f) == NULL) {
Contact *contact = [[Contact alloc] initWithFriend:f];
[self registerAddrsFor:contact];
}
friends = friends->next;
}
lists = lists->next;

View file

@ -445,6 +445,9 @@
else if ([machine isEqual:@"iPod7,1"])
return @"iPod touch 6G";
else if ([machine isEqual:@"x86_64"])
return @"simulator 64bits";
// none matched: cf https://www.theiphonewiki.com/wiki/Models for the whole list
LOGW(@"%s: Oops, unknown machine %@... consider completing me!", __FUNCTION__, machine);
return machine;

View file

@ -13,6 +13,12 @@
<entry name="realm" overwrite="true"></entry>
</section>
<section name="sip">
<entry name="rls_uri" overwrite="true"></entry>
<entry name="use_rls_presence" overwrite="true"></entry>
</section>
<section name="assistant">
<entry name="domain" overwrite="true"></entry>
<entry name="password_max_length" overwrite="true">-1</entry>

View file

@ -15,6 +15,11 @@
<entry name="realm" overwrite="true">sip.linphone.org</entry>
</section>
<section name="sip">
<entry name="rls_uri" overwrite="true">sip:rls@sip.linphone.org</entry>
<entry name="use_rls_presence" overwrite="true">1</entry>
</section>
<section name="assistant">
<entry name="domain" overwrite="true">sip.linphone.org</entry>
<entry name="password_max_length" overwrite="true">-1</entry>

View file

@ -15,6 +15,11 @@
<entry name="realm" overwrite="true">sip.linphone.org</entry>
</section>
<section name="sip">
<entry name="rls_uri" overwrite="true">sip:rls@sip.linphone.org</entry>
<entry name="use_rls_presence" overwrite="true">1</entry>
</section>
<section name="assistant">
<entry name="domain" overwrite="true">sip.linphone.org</entry>
<entry name="password_max_length" overwrite="true">34</entry>

View file

@ -13,6 +13,12 @@
<entry name="realm" overwrite="true"></entry>
</section>
<section name="sip">
<entry name="rls_uri" overwrite="true"></entry>
<entry name="use_rls_presence" overwrite="true"></entry>
</section>
<section name="assistant">
<entry name="domain" overwrite="true"></entry>
<entry name="password_max_length" overwrite="true">-1</entry>

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B

View file

@ -5,6 +5,7 @@
debug_popup_email=linphone-iphone@belledonne-communications.com
send_logs_include_linphonerc_and_chathistory=0
#use_phone_number=0
publish_presence=0
[assistant]
password_length=-1
@ -17,6 +18,7 @@ history_max_size=-1
[sip]
sip_random_port=0
store_ha1_passwd=0
handle_content_encoding=none
[sound]
dtmf_player_amp=0.007

File diff suppressed because it is too large Load diff

@ -1 +1 @@
Subproject commit 99b64aac55e58e885e89ed9265e6246cd16880a3
Subproject commit aa0677fcc261a0adabe315593d452e1f65c9484c