clangformat: reformat all code style convention defined in .clang-format

This commit is contained in:
Gautier Pelloux-Prayer 2015-07-09 11:50:14 +02:00
parent c86c615044
commit 540a47a53a
81 changed files with 9323 additions and 9356 deletions

View file

@ -4,18 +4,18 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "AboutViewController.h"
#import "LinphoneManager.h"
@ -34,123 +34,122 @@
@synthesize licenseLabel;
@synthesize copyrightLabel;
#pragma mark - Lifecycle Functions
- (id)init {
self = [super initWithNibName:@"AboutViewController" bundle:[NSBundle mainBundle]];
if (self != nil) {
self->linkTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onLinkTap:)];
}
return self;
self = [super initWithNibName:@"AboutViewController" bundle:[NSBundle mainBundle]];
if (self != nil) {
self->linkTapGestureRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onLinkTap:)];
}
return self;
}
#pragma mark - ViewController Functions
- (void)viewDidLoad {
[super viewDidLoad];
[linkLabel addGestureRecognizer:linkTapGestureRecognizer];
UIScrollView *scrollView = (UIScrollView *)self.view;
[scrollView addSubview:contentView];
[scrollView setContentSize:[contentView bounds].size];
[super viewDidLoad];
[linkLabel addGestureRecognizer:linkTapGestureRecognizer];
UIScrollView *scrollView = (UIScrollView *)self.view;
[scrollView addSubview:contentView];
[scrollView setContentSize:[contentView bounds].size];
[linphoneLabel setText:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]];
[linphoneIphoneVersionLabel setText:[NSString stringWithFormat:@"%@ iPhone %@",
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"],
[NSString stringWithUTF8String:LINPHONE_IOS_VERSION]]
];
[linphoneCoreVersionLabel setText:[NSString stringWithFormat:@"%@ Core %s", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"], linphone_core_get_version()]];
if([LinphoneManager runningOnIpad]) {
[LinphoneUtils adjustFontSize:self.view mult:2.22f];
}
[AboutViewController removeBackground:licensesView];
// Create a request to the resource
NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:[LinphoneManager bundleFile:@"licenses.html"]]] ;
// Load the resource using the request
[licensesView setDelegate:self];
[licensesView loadRequest:request];
[[AboutViewController defaultScrollView:licensesView] setScrollEnabled:FALSE];
[linphoneIphoneVersionLabel
setText:[NSString stringWithFormat:@"%@ iPhone %@",
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"],
[NSString stringWithUTF8String:LINPHONE_IOS_VERSION]]];
[linphoneCoreVersionLabel
setText:[NSString stringWithFormat:@"%@ Core %s",
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"],
linphone_core_get_version()]];
if ([LinphoneManager runningOnIpad]) {
[LinphoneUtils adjustFontSize:self.view mult:2.22f];
}
[AboutViewController removeBackground:licensesView];
// Create a request to the resource
NSURLRequest *request =
[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[LinphoneManager bundleFile:@"licenses.html"]]];
// Load the resource using the request
[licensesView setDelegate:self];
[licensesView loadRequest:request];
[[AboutViewController defaultScrollView:licensesView] setScrollEnabled:FALSE];
}
#pragma mark - UICompositeViewDelegate Functions
static UICompositeViewDescription *compositeDescription = nil;
+ (UICompositeViewDescription *)compositeViewDescription {
if(compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"About"
content:@"AboutViewController"
stateBar:nil
stateBarEnabled:false
tabBar:@"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
}
return compositeDescription;
if (compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"About"
content:@"AboutViewController"
stateBar:nil
stateBarEnabled:false
tabBar:@"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
}
return compositeDescription;
}
#pragma mark -
+ (void)removeBackground:(UIView *)view {
for (UIView *subview in [view subviews]) {
[subview setOpaque:NO];
[subview setBackgroundColor:[UIColor clearColor]];
}
[view setOpaque:NO];
[view setBackgroundColor:[UIColor clearColor]];
for (UIView *subview in [view subviews]) {
[subview setOpaque:NO];
[subview setBackgroundColor:[UIColor clearColor]];
}
[view setOpaque:NO];
[view setBackgroundColor:[UIColor clearColor]];
}
+ (UIScrollView *)defaultScrollView:(UIWebView *)webView {
return webView.scrollView;
return webView.scrollView;
}
#pragma mark - Action Functions
- (IBAction)onLinkTap:(id)sender {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:linkLabel.text]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:linkLabel.text]];
}
#pragma mark - UIWebViewDelegate Functions
- (void)webViewDidFinishLoad:(UIWebView *)webView {
CGSize size = [webView sizeThatFits:CGSizeMake(self.view.bounds.size.width, 10000.0f)];
float diff = size.height - webView.bounds.size.height;
UIScrollView *scrollView = (UIScrollView *)self.view;
CGRect contentFrame = [contentView bounds];
contentFrame.size.height += diff;
[contentView setAutoresizesSubviews:FALSE];
[contentView setFrame:contentFrame];
[contentView setAutoresizesSubviews:TRUE];
[scrollView setContentSize:contentFrame.size];
CGRect licensesViewFrame = [licensesView frame];
licensesViewFrame.size.height += diff;
[licensesView setFrame:licensesViewFrame];
CGSize size = [webView sizeThatFits:CGSizeMake(self.view.bounds.size.width, 10000.0f)];
float diff = size.height - webView.bounds.size.height;
UIScrollView *scrollView = (UIScrollView *)self.view;
CGRect contentFrame = [contentView bounds];
contentFrame.size.height += diff;
[contentView setAutoresizesSubviews:FALSE];
[contentView setFrame:contentFrame];
[contentView setAutoresizesSubviews:TRUE];
[scrollView setContentSize:contentFrame.size];
CGRect licensesViewFrame = [licensesView frame];
licensesViewFrame.size.height += diff;
[licensesView setFrame:licensesViewFrame];
}
- (BOOL)webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if (inType == UIWebViewNavigationTypeLinkClicked) {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
return YES;
}
- (BOOL)webView:(UIWebView *)inWeb
shouldStartLoadWithRequest:(NSURLRequest *)inRequest
navigationType:(UIWebViewNavigationType)inType {
if (inType == UIWebViewNavigationTypeLinkClicked) {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
return YES;
}
@end

View file

@ -32,35 +32,35 @@
#pragma mark - Lifecycle Functions
- (void)dealloc {
[self clearMessageList];
[self clearMessageList];
}
#pragma mark - ViewController Functions
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[TUNinePatchCache flushCache]; // Clear cache
[super viewWillDisappear:animated];
[TUNinePatchCache flushCache]; // Clear cache
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.tableView.accessibilityIdentifier = @"Chat list";
self.tableView.accessibilityIdentifier = @"Chat list";
[self reloadData];
}
#pragma mark -
- (void)clearMessageList {
if (messageList){
ms_list_free_with_data(messageList, (void(*)(void*))linphone_chat_message_unref);
messageList = nil;
}
if (messageList) {
ms_list_free_with_data(messageList, (void (*)(void *))linphone_chat_message_unref);
messageList = nil;
}
}
- (void)updateData {
if( !chatRoom ) return;
[self clearMessageList];
self->messageList = linphone_chat_room_get_history(chatRoom, 0);
if (!chatRoom)
return;
[self clearMessageList];
self->messageList = linphone_chat_room_get_history(chatRoom, 0);
// also append transient upload messages because they are not in history yet!
for (FileTransferDelegate *ftd in [[LinphoneManager instance] fileTransferDelegates]) {
@ -74,15 +74,15 @@
}
- (void)reloadData {
[self updateData];
[self.tableView reloadData];
[self scrollToLastUnread:false];
[self updateData];
[self.tableView reloadData];
[self scrollToLastUnread:false];
}
- (void)addChatEntry:(LinphoneChatMessage*)chat {
- (void)addChatEntry:(LinphoneChatMessage *)chat {
messageList = ms_list_append(messageList, linphone_chat_message_ref(chat));
int pos = ms_list_size(messageList) - 1;
messageList = ms_list_append(messageList, linphone_chat_message_ref(chat));
int pos = ms_list_size(messageList) - 1;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:pos inSection:0];
[self.tableView beginUpdates];
@ -90,28 +90,29 @@
[self.tableView endUpdates];
}
- (void)updateChatEntry:(LinphoneChatMessage*)chat {
NSInteger index = ms_list_index(self->messageList, chat);
if (index<0) {
- (void)updateChatEntry:(LinphoneChatMessage *)chat {
NSInteger index = ms_list_index(self->messageList, chat);
if (index < 0) {
LOGW(@"chat entry doesn't exist");
return;
}
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:index inSection:0]] withRowAnimation:FALSE]; //just reload
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:index inSection:0]]
withRowAnimation:FALSE]; // just reload
return;
}
- (void)scrollToBottom:(BOOL)animated {
[self.tableView reloadData];
int count = ms_list_size(messageList);
if( count ){
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:(count - 1) inSection:0]
atScrollPosition:UITableViewScrollPositionBottom
animated:YES];
}
[self.tableView reloadData];
int count = ms_list_size(messageList);
if (count) {
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:(count - 1)inSection:0]
atScrollPosition:UITableViewScrollPositionBottom
animated:YES];
}
}
- (void)debugMessages {
if( !messageList ){
if (!messageList) {
LOGE(@"No data to debug");
return;
}
@ -125,94 +126,96 @@
}
- (void)scrollToLastUnread:(BOOL)animated {
if(messageList == nil || chatRoom == nil) {
return;
}
if (messageList == nil || chatRoom == nil) {
return;
}
int index = -1;
int count = ms_list_size(messageList);
// Find first unread & set all entry read
for(int i = 0; i <count; ++i) {
int read = linphone_chat_message_is_read(ms_list_nth_data(messageList, i));
if(read == 0) {
if(index == -1)
index = i;
}
}
if(index == -1) {
index = count - 1;
}
int index = -1;
int count = ms_list_size(messageList);
// Find first unread & set all entry read
for (int i = 0; i < count; ++i) {
int read = linphone_chat_message_is_read(ms_list_nth_data(messageList, i));
if (read == 0) {
if (index == -1)
index = i;
}
}
if (index == -1) {
index = count - 1;
}
linphone_chat_room_mark_as_read(chatRoom);
linphone_chat_room_mark_as_read(chatRoom);
// Scroll to unread
if(index >= 0) {
[self.tableView.layer removeAllAnimations];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]
atScrollPosition:UITableViewScrollPositionTop
animated:animated];
}
// Scroll to unread
if (index >= 0) {
[self.tableView.layer removeAllAnimations];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]
atScrollPosition:UITableViewScrollPositionTop
animated:animated];
}
}
#pragma mark - Property Functions
- (void)setChatRoom:(LinphoneChatRoom*)room {
chatRoom = room;
[self reloadData];
- (void)setChatRoom:(LinphoneChatRoom *)room {
chatRoom = room;
[self reloadData];
}
#pragma mark - UITableViewDataSource Functions
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return ms_list_size(self->messageList);
return ms_list_size(self->messageList);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *kCellId = @"UIChatRoomCell";
UIChatRoomCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId];
if (cell == nil) {
cell = [[UIChatRoomCell alloc] initWithIdentifier:kCellId];
}
static NSString *kCellId = @"UIChatRoomCell";
UIChatRoomCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId];
if (cell == nil) {
cell = [[UIChatRoomCell alloc] initWithIdentifier:kCellId];
}
LinphoneChatMessage* chat = ms_list_nth_data(self->messageList, (int)[indexPath row]);
[cell setChatMessage:chat];
[cell setChatRoomDelegate:chatRoomDelegate];
return cell;
LinphoneChatMessage *chat = ms_list_nth_data(self->messageList, (int)[indexPath row]);
[cell setChatMessage:chat];
[cell setChatRoomDelegate:chatRoomDelegate];
return cell;
}
#pragma mark - UITableViewDelegate Functions
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if(editingStyle == UITableViewCellEditingStyleDelete) {
[tableView beginUpdates];
LinphoneChatMessage *chat = ms_list_nth_data(self->messageList, (int)[indexPath row]);
if( chat ){
linphone_chat_room_delete_message(chatRoom, chat);
messageList = ms_list_remove(messageList, chat);
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[tableView beginUpdates];
LinphoneChatMessage *chat = ms_list_nth_data(self->messageList, (int)[indexPath row]);
if (chat) {
linphone_chat_room_delete_message(chatRoom, chat);
messageList = ms_list_remove(messageList, chat);
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationBottom];
}
[tableView endUpdates];
}
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationBottom];
}
[tableView endUpdates];
}
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
// Detemine if it's in editing mode
if (self.editing) {
return UITableViewCellEditingStyleDelete;
}
return UITableViewCellEditingStyleNone;
- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView
editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
// Detemine if it's in editing mode
if (self.editing) {
return UITableViewCellEditingStyleDelete;
}
return UITableViewCellEditingStyleNone;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
LinphoneChatMessage* message = ms_list_nth_data(self->messageList, (int)[indexPath row]);
return [UIChatRoomCell height:message width:[self.view frame].size.width];
LinphoneChatMessage *message = ms_list_nth_data(self->messageList, (int)[indexPath row]);
return [UIChatRoomCell height:message width:[self.view frame].size.width];
}
@end

File diff suppressed because it is too large Load diff

View file

@ -4,18 +4,18 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "ChatTableViewController.h"
#import "UIChatCell.h"
@ -29,43 +29,40 @@
#import "Utils.h"
@implementation ChatTableViewController {
MSList* data;
MSList *data;
}
#pragma mark - Lifecycle Functions
-(instancetype)init {
- (instancetype)init {
self = super.init;
if( self ){
if (self) {
self->data = nil;
}
return self;
}
- (void)dealloc {
if( data != nil ) {
if (data != nil) {
ms_list_free_with_data(data, chatTable_free_chatrooms);
}
}
#pragma mark - ViewController Functions
#pragma mark - ViewController Functions
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.tableView.accessibilityIdentifier = @"ChatRoom list";
[self loadData];
[super viewDidAppear:animated];
self.tableView.accessibilityIdentifier = @"ChatRoom list";
[self loadData];
}
#pragma mark -
static int sorted_history_comparison(LinphoneChatRoom *to_insert, LinphoneChatRoom *elem) {
LinphoneChatMessage *last_new_message = linphone_chat_room_get_user_data(to_insert);
LinphoneChatMessage *last_elem_message = linphone_chat_room_get_user_data(elem);
#pragma mark -
static int sorted_history_comparison(LinphoneChatRoom *to_insert, LinphoneChatRoom *elem){
LinphoneChatMessage* last_new_message = linphone_chat_room_get_user_data(to_insert);
LinphoneChatMessage* last_elem_message = linphone_chat_room_get_user_data(elem);
if( last_new_message && last_elem_message ){
if (last_new_message && last_elem_message) {
time_t new = linphone_chat_message_get_time(last_new_message);
time_t old = linphone_chat_message_get_time(last_elem_message);
if (new < old)
@ -76,7 +73,7 @@ static int sorted_history_comparison(LinphoneChatRoom *to_insert, LinphoneChatRo
return 0;
}
- (MSList*)sortChatRooms {
- (MSList *)sortChatRooms {
MSList *sorted = nil;
MSList *unsorted = linphone_core_get_chat_rooms([LinphoneManager getLc]);
MSList *iter = unsorted;
@ -98,7 +95,7 @@ static int sorted_history_comparison(LinphoneChatRoom *to_insert, LinphoneChatRo
return sorted;
}
static void chatTable_free_chatrooms(void *data){
static void chatTable_free_chatrooms(void *data) {
LinphoneChatMessage *lastMsg = linphone_chat_room_get_user_data(data);
if (lastMsg) {
linphone_chat_message_unref(lastMsg);
@ -107,69 +104,73 @@ static void chatTable_free_chatrooms(void *data){
}
- (void)loadData {
if( data != NULL ){
ms_list_free_with_data(data, chatTable_free_chatrooms);
}
data = [self sortChatRooms];
[[self tableView] reloadData];
if (data != NULL) {
ms_list_free_with_data(data, chatTable_free_chatrooms);
}
data = [self sortChatRooms];
[[self tableView] reloadData];
}
#pragma mark - UITableViewDataSource Functions
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return ms_list_size(data);
return ms_list_size(data);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *kCellId = @"UIChatCell";
UIChatCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId];
if (cell == nil) {
cell = [[UIChatCell alloc] initWithIdentifier:kCellId];
// Background View
UACellBackgroundView *selectedBackgroundView = [[UACellBackgroundView alloc] initWithFrame:CGRectZero];
cell.selectedBackgroundView = selectedBackgroundView;
[selectedBackgroundView setBackgroundColor:LINPHONE_TABLE_CELL_BACKGROUND_COLOR];
}
[cell setChatRoom:(LinphoneChatRoom*)ms_list_nth_data(data, (int)[indexPath row])];
return cell;
}
static NSString *kCellId = @"UIChatCell";
UIChatCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId];
if (cell == nil) {
cell = [[UIChatCell alloc] initWithIdentifier:kCellId];
// Background View
UACellBackgroundView *selectedBackgroundView = [[UACellBackgroundView alloc] initWithFrame:CGRectZero];
cell.selectedBackgroundView = selectedBackgroundView;
[selectedBackgroundView setBackgroundColor:LINPHONE_TABLE_CELL_BACKGROUND_COLOR];
}
[cell setChatRoom:(LinphoneChatRoom *)ms_list_nth_data(data, (int)[indexPath row])];
return cell;
}
#pragma mark - UITableViewDelegate Functions
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
LinphoneChatRoom *chatRoom = (LinphoneChatRoom*)ms_list_nth_data(data, (int)[indexPath row]);
// Go to ChatRoom view
ChatRoomViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ChatRoomViewController compositeViewDescription] push:TRUE], ChatRoomViewController);
if(controller != nil) {
[controller setChatRoom:chatRoom];
}
[tableView deselectRowAtIndexPath:indexPath animated:NO];
LinphoneChatRoom *chatRoom = (LinphoneChatRoom *)ms_list_nth_data(data, (int)[indexPath row]);
// Go to ChatRoom view
ChatRoomViewController *controller = DYNAMIC_CAST(
[[PhoneMainView instance] changeCurrentView:[ChatRoomViewController compositeViewDescription] push:TRUE],
ChatRoomViewController);
if (controller != nil) {
[controller setChatRoom:chatRoom];
}
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
// Detemine if it's in editing mode
if (self.editing) {
return UITableViewCellEditingStyleDelete;
}
return UITableViewCellEditingStyleNone;
- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView
editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
// Detemine if it's in editing mode
if (self.editing) {
return UITableViewCellEditingStyleDelete;
}
return UITableViewCellEditingStyleNone;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if(editingStyle == UITableViewCellEditingStyleDelete) {
[tableView beginUpdates];
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[tableView beginUpdates];
LinphoneChatRoom *chatRoom = (LinphoneChatRoom*)ms_list_nth_data(data, (int)[indexPath row]);
LinphoneChatMessage* last_msg = linphone_chat_room_get_user_data(chatRoom);
if( last_msg ){
LinphoneChatRoom *chatRoom = (LinphoneChatRoom *)ms_list_nth_data(data, (int)[indexPath row]);
LinphoneChatMessage *last_msg = linphone_chat_room_get_user_data(chatRoom);
if (last_msg) {
linphone_chat_message_unref(last_msg);
linphone_chat_room_set_user_data(chatRoom, NULL);
}
@ -183,12 +184,13 @@ static void chatTable_free_chatrooms(void *data){
linphone_chat_room_unref(chatRoom);
data = ms_list_remove(data, chatRoom);
// will force a call to [self loadData]
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneTextReceived object:self];
// will force a call to [self loadData]
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneTextReceived object:self];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
}
@end

View file

@ -4,18 +4,18 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "ChatViewController.h"
#import "PhoneMainView.h"
@ -29,122 +29,117 @@
#pragma mark - Lifecycle Functions
- (id)init {
return [super initWithNibName:@"ChatViewController" bundle:[NSBundle mainBundle]];
return [super initWithNibName:@"ChatViewController" bundle:[NSBundle mainBundle]];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - ViewController Functions
- (void)viewDidLoad {
[super viewDidLoad];
// Set selected+over background: IB lack !
[editButton setBackgroundImage:[UIImage imageNamed:@"chat_ok_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:editButton];
[super viewDidLoad];
[tableController.tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4
[tableController.tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
// Set selected+over background: IB lack !
[editButton setBackgroundImage:[UIImage imageNamed:@"chat_ok_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:editButton];
[tableController.tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4
[tableController.tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(textReceivedEvent:)
name:kLinphoneTextReceived
object:nil];
if([tableController isEditing])
[tableController setEditing:FALSE animated:FALSE];
[editButton setOff];
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(textReceivedEvent:)
name:kLinphoneTextReceived
object:nil];
if ([tableController isEditing])
[tableController setEditing:FALSE animated:FALSE];
[editButton setOff];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneTextReceived
object:nil];
}
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneTextReceived object:nil];
}
#pragma mark - Event Functions
- (void)textReceivedEvent:(NSNotification *)notif {
[tableController loadData];
[tableController loadData];
}
#pragma mark - UICompositeViewDelegate Functions
static UICompositeViewDescription *compositeDescription = nil;
+ (UICompositeViewDescription *)compositeViewDescription {
if(compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"Chat"
content:@"ChatViewController"
stateBar:nil
stateBarEnabled:false
tabBar: @"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
}
return compositeDescription;
if (compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"Chat"
content:@"ChatViewController"
stateBar:nil
stateBarEnabled:false
tabBar:@"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
}
return compositeDescription;
}
#pragma mark - Action Functions
-(void) startChatRoom {
//Push ChatRoom
LinphoneChatRoom* room = linphone_core_get_or_create_chat_room([LinphoneManager getLc], [addressField.text UTF8String]);
if( room != nil ){
ChatRoomViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ChatRoomViewController compositeViewDescription] push:TRUE], ChatRoomViewController);
if(controller != nil) {
LinphoneChatRoom* room = linphone_core_get_or_create_chat_room([LinphoneManager getLc], [addressField.text UTF8String]);
[controller setChatRoom:room];
- (void)startChatRoom {
// Push ChatRoom
LinphoneChatRoom *room =
linphone_core_get_or_create_chat_room([LinphoneManager getLc], [addressField.text UTF8String]);
if (room != nil) {
ChatRoomViewController *controller = DYNAMIC_CAST(
[[PhoneMainView instance] changeCurrentView:[ChatRoomViewController compositeViewDescription] push:TRUE],
ChatRoomViewController);
if (controller != nil) {
LinphoneChatRoom *room =
linphone_core_get_or_create_chat_room([LinphoneManager getLc], [addressField.text UTF8String]);
[controller setChatRoom:room];
}
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Invalid address", nil)
message:@"Please specify the entire SIP address for the chat"
delegate:nil
cancelButtonTitle:NSLocalizedString(@"Cancel", nil)
otherButtonTitles:nil];
[alert show];
}
} else {
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Invalid address", nil)
message:@"Please specify the entire SIP address for the chat"
delegate:nil
cancelButtonTitle:NSLocalizedString(@"Cancel", nil)
otherButtonTitles:nil];
[alert show];
}
addressField.text = @"";
}
- (IBAction)onAddClick:(id)event {
if ([[addressField text ]length] == 0) { // if no address is manually set, lauch address book
if ([[addressField text] length] == 0) { // if no address is manually set, lauch address book
[ContactSelection setSelectionMode:ContactSelectionModeMessage];
[ContactSelection setAddAddress:nil];
[ContactSelection setSipFilter: [LinphoneManager instance].contactFilter];
[ContactSelection setSipFilter:[LinphoneManager instance].contactFilter];
[ContactSelection enableEmailFilter:FALSE];
[ContactSelection setNameOrEmailFilter:nil];
[[PhoneMainView instance] changeCurrentView:[ContactsViewController compositeViewDescription] push:TRUE];
} else {
[self startChatRoom];
[self startChatRoom];
}
}
- (IBAction)onEditClick:(id)event {
[tableController setEditing:![tableController isEditing] animated:TRUE];
[tableController setEditing:![tableController isEditing] animated:TRUE];
}
#pragma mark - UITextFieldDelegate Functions
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[addressField resignFirstResponder];
if ([[addressField text ]length]> 0)
[addressField resignFirstResponder];
if ([[addressField text] length] > 0)
[self startChatRoom];
return YES;
}

View file

@ -4,18 +4,18 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "ContactDetailsLabelViewController.h"
@ -30,109 +30,100 @@
@synthesize selectedData;
@synthesize delegate;
#pragma mark - Lifecycle Functions
#pragma mark - ViewController Functions
- (void)viewDidLoad {
[super viewDidLoad];
[tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4
[tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
[super viewDidLoad];
[tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4
[tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
}
#pragma mark - UICompositeViewDelegate Functions
static UICompositeViewDescription *compositeDescription = nil;
+ (UICompositeViewDescription *)compositeViewDescription {
if(compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"ContactDetailsLabel"
content:@"ContactDetailsLabelViewController"
stateBar:nil
stateBarEnabled:false
tabBar:@"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
}
return compositeDescription;
if (compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"ContactDetailsLabel"
content:@"ContactDetailsLabelViewController"
stateBar:nil
stateBarEnabled:false
tabBar:@"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
}
return compositeDescription;
}
#pragma mark -
- (void)dismiss {
if([[[PhoneMainView instance] currentView] equal:[ContactDetailsLabelViewController compositeViewDescription]]) {
[[PhoneMainView instance] popCurrentView];
}
if ([[[PhoneMainView instance] currentView] equal:[ContactDetailsLabelViewController compositeViewDescription]]) {
[[PhoneMainView instance] popCurrentView];
}
}
#pragma mark - Property Functions
- (void)setDataList:(NSDictionary *)adatalist {
if([dataList isEqualToDictionary:adatalist]) {
return;
}
dataList = adatalist;
[tableView reloadData];
if ([dataList isEqualToDictionary:adatalist]) {
return;
}
dataList = adatalist;
[tableView reloadData];
}
- (void)setSelectedData:(NSString *)aselectedData {
selectedData = [[NSString alloc] initWithString:aselectedData];
[tableView reloadData];
selectedData = [[NSString alloc] initWithString:aselectedData];
[tableView reloadData];
}
#pragma mark - UITableViewDataSource Functions
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [dataList count];
return [dataList count];
}
- (UITableViewCell *)tableView:(UITableView *)atableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *kCellId = @"ContactDetailsLabelCell";
UITableViewCell *cell = [atableView dequeueReusableCellWithIdentifier:kCellId];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:kCellId];
// Background View
UACellBackgroundView *selectedBackgroundView = [[UACellBackgroundView alloc] initWithFrame:CGRectZero];
cell.selectedBackgroundView = selectedBackgroundView;
[selectedBackgroundView setBackgroundColor:LINPHONE_TABLE_CELL_BACKGROUND_COLOR];
}
NSString* key = [[dataList allKeys] objectAtIndex:[indexPath row]];
[cell.textLabel setText:[dataList objectForKey:key]];
if ([key compare:selectedData]==0) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
} else {
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
return cell;
static NSString *kCellId = @"ContactDetailsLabelCell";
UITableViewCell *cell = [atableView dequeueReusableCellWithIdentifier:kCellId];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:kCellId];
// Background View
UACellBackgroundView *selectedBackgroundView = [[UACellBackgroundView alloc] initWithFrame:CGRectZero];
cell.selectedBackgroundView = selectedBackgroundView;
[selectedBackgroundView setBackgroundColor:LINPHONE_TABLE_CELL_BACKGROUND_COLOR];
}
NSString *key = [[dataList allKeys] objectAtIndex:[indexPath row]];
[cell.textLabel setText:[dataList objectForKey:key]];
if ([key compare:selectedData] == 0) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
} else {
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString* key = [[dataList allKeys] objectAtIndex:[indexPath row]];
[self setSelectedData:key];
[delegate changeContactDetailsLabel:key];
[self dismiss];
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *key = [[dataList allKeys] objectAtIndex:[indexPath row]];
[self setSelectedData:key];
[delegate changeContactDetailsLabel:key];
[self dismiss];
}
#pragma mark - Action Functions
- (IBAction)onBackClick:(id)event {
[self dismiss];
[self dismiss];
}
@end

View file

@ -28,118 +28,114 @@
@synthesize backButton;
@synthesize cancelButton;
static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef info, void *context);
static void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info, void *context);
#pragma mark - Lifecycle Functions
- (id)init {
self = [super initWithNibName:@"ContactDetailsViewController" bundle:[NSBundle mainBundle]];
if(self != nil) {
inhibUpdate = FALSE;
addressBook = ABAddressBookCreateWithOptions(nil, nil);
ABAddressBookRegisterExternalChangeCallback(addressBook, sync_address_book, (__bridge void *)(self));
}
return self;
- (id)init {
self = [super initWithNibName:@"ContactDetailsViewController" bundle:[NSBundle mainBundle]];
if (self != nil) {
inhibUpdate = FALSE;
addressBook = ABAddressBookCreateWithOptions(nil, nil);
ABAddressBookRegisterExternalChangeCallback(addressBook, sync_address_book, (__bridge void *)(self));
}
return self;
}
- (void)dealloc {
ABAddressBookUnregisterExternalChangeCallback(addressBook, sync_address_book, (__bridge void *)(self));
CFRelease(addressBook);
ABAddressBookUnregisterExternalChangeCallback(addressBook, sync_address_book, (__bridge void *)(self));
CFRelease(addressBook);
}
#pragma mark -
- (void)resetData {
[self disableEdit:FALSE];
if(contact == NULL) {
ABAddressBookRevert(addressBook);
return;
}
[self disableEdit:FALSE];
if (contact == NULL) {
ABAddressBookRevert(addressBook);
return;
}
LOGI(@"Reset data to contact %p", contact);
ABRecordID recordID = ABRecordGetRecordID(contact);
ABAddressBookRevert(addressBook);
contact = ABAddressBookGetPersonWithRecordID(addressBook, recordID);
if(contact == NULL) {
[[PhoneMainView instance] popCurrentView];
return;
}
[tableController setContact:contact];
LOGI(@"Reset data to contact %p", contact);
ABRecordID recordID = ABRecordGetRecordID(contact);
ABAddressBookRevert(addressBook);
contact = ABAddressBookGetPersonWithRecordID(addressBook, recordID);
if (contact == NULL) {
[[PhoneMainView instance] popCurrentView];
return;
}
[tableController setContact:contact];
}
static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef info, void *context) {
ContactDetailsViewController* controller = (__bridge ContactDetailsViewController*)context;
if(!controller->inhibUpdate && ![[controller tableController] isEditing]) {
[controller resetData];
}
static void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info, void *context) {
ContactDetailsViewController *controller = (__bridge ContactDetailsViewController *)context;
if (!controller->inhibUpdate && ![[controller tableController] isEditing]) {
[controller resetData];
}
}
- (void)removeContact {
if(contact == NULL) {
[[PhoneMainView instance] popCurrentView];
return;
}
if (contact == NULL) {
[[PhoneMainView instance] popCurrentView];
return;
}
// Remove contact from book
if(ABRecordGetRecordID(contact) != kABRecordInvalidID) {
CFErrorRef error = NULL;
ABAddressBookRemoveRecord(addressBook, contact, (CFErrorRef*)&error);
if (error != NULL) {
LOGE(@"Remove contact %p: Fail(%@)", contact, [(__bridge NSError*)error localizedDescription]);
} else {
LOGI(@"Remove contact %p: Success!", contact);
}
contact = NULL;
// Remove contact from book
if (ABRecordGetRecordID(contact) != kABRecordInvalidID) {
CFErrorRef error = NULL;
ABAddressBookRemoveRecord(addressBook, contact, (CFErrorRef *)&error);
if (error != NULL) {
LOGE(@"Remove contact %p: Fail(%@)", contact, [(__bridge NSError *)error localizedDescription]);
} else {
LOGI(@"Remove contact %p: Success!", contact);
}
contact = NULL;
// Save address book
error = NULL;
inhibUpdate = TRUE;
ABAddressBookSave(addressBook, (CFErrorRef*)&error);
inhibUpdate = FALSE;
if (error != NULL) {
LOGE(@"Save AddressBook: Fail(%@)", [(__bridge NSError*)error localizedDescription]);
} else {
LOGI(@"Save AddressBook: Success!");
}
// Save address book
error = NULL;
inhibUpdate = TRUE;
ABAddressBookSave(addressBook, (CFErrorRef *)&error);
inhibUpdate = FALSE;
if (error != NULL) {
LOGE(@"Save AddressBook: Fail(%@)", [(__bridge NSError *)error localizedDescription]);
} else {
LOGI(@"Save AddressBook: Success!");
}
[[LinphoneManager instance].fastAddressBook reload];
}
}
}
- (void)saveData {
if(contact == NULL) {
[[PhoneMainView instance] popCurrentView];
return;
}
if (contact == NULL) {
[[PhoneMainView instance] popCurrentView];
return;
}
// Add contact to book
CFErrorRef error = NULL;
if(ABRecordGetRecordID(contact) == kABRecordInvalidID) {
ABAddressBookAddRecord(addressBook, contact, (CFErrorRef*)&error);
if (error != NULL) {
LOGE(@"Add contact %p: Fail(%@)", contact, [(__bridge NSError*)error localizedDescription]);
} else {
LOGI(@"Add contact %p: Success!", contact);
}
}
// Add contact to book
CFErrorRef error = NULL;
if (ABRecordGetRecordID(contact) == kABRecordInvalidID) {
ABAddressBookAddRecord(addressBook, contact, (CFErrorRef *)&error);
if (error != NULL) {
LOGE(@"Add contact %p: Fail(%@)", contact, [(__bridge NSError *)error localizedDescription]);
} else {
LOGI(@"Add contact %p: Success!", contact);
}
}
// Save address book
error = NULL;
inhibUpdate = TRUE;
ABAddressBookSave(addressBook, (CFErrorRef*)&error);
inhibUpdate = FALSE;
if (error != NULL) {
LOGE(@"Save AddressBook: Fail(%@)", [(__bridge NSError*)error localizedDescription]);
} else {
LOGI(@"Save AddressBook: Success!");
}
[[LinphoneManager instance].fastAddressBook reload];
// Save address book
error = NULL;
inhibUpdate = TRUE;
ABAddressBookSave(addressBook, (CFErrorRef *)&error);
inhibUpdate = FALSE;
if (error != NULL) {
LOGE(@"Save AddressBook: Fail(%@)", [(__bridge NSError *)error localizedDescription]);
} else {
LOGI(@"Save AddressBook: Success!");
}
[[LinphoneManager instance].fastAddressBook reload];
}
- (void) selectContact:(ABRecordRef)acontact andReload:(BOOL)reload {
- (void)selectContact:(ABRecordRef)acontact andReload:(BOOL)reload {
contact = NULL;
[self resetData];
contact = acontact;
@ -151,9 +147,10 @@ static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef inf
}
}
- (void) addCurrentContactContactField:(NSString*)address {
- (void)addCurrentContactContactField:(NSString *)address {
LinphoneAddress *linphoneAddress = linphone_address_new([address cStringUsingEncoding:[NSString defaultCStringEncoding]]);
LinphoneAddress *linphoneAddress =
linphone_address_new([address cStringUsingEncoding:[NSString defaultCStringEncoding]]);
NSString *username = [NSString stringWithUTF8String:linphone_address_get_username(linphoneAddress)];
if (([username rangeOfString:@"@"].length > 0) &&
@ -175,7 +172,7 @@ static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef inf
[self selectContact:ABPersonCreate() andReload:YES];
}
- (void)newContact:(NSString*)address {
- (void)newContact:(NSString *)address {
[self selectContact:ABPersonCreate() andReload:NO];
[self addCurrentContactContactField:address];
}
@ -184,7 +181,7 @@ static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef inf
[self selectContact:ABAddressBookGetPersonWithRecordID(addressBook, ABRecordGetRecordID(acontact)) andReload:YES];
}
- (void)editContact:(ABRecordRef)acontact address:(NSString*)address {
- (void)editContact:(ABRecordRef)acontact address:(NSString *)address {
[self selectContact:ABAddressBookGetPersonWithRecordID(addressBook, ABRecordGetRecordID(acontact)) andReload:NO];
[self addCurrentContactContactField:address];
}
@ -195,31 +192,31 @@ static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef inf
#pragma mark - ViewController Functions
- (void)viewDidLoad{
[super viewDidLoad];
- (void)viewDidLoad {
[super viewDidLoad];
// Set selected+over background: IB lack !
[editButton setBackgroundImage:[UIImage imageNamed:@"contact_ok_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+over background: IB lack !
[editButton setBackgroundImage:[UIImage imageNamed:@"contact_ok_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+disabled background: IB lack !
[editButton setBackgroundImage:[UIImage imageNamed:@"contact_ok_disabled.png"]
forState:(UIControlStateDisabled | UIControlStateSelected)];
// Set selected+disabled background: IB lack !
[editButton setBackgroundImage:[UIImage imageNamed:@"contact_ok_disabled.png"]
forState:(UIControlStateDisabled | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:editButton];
[LinphoneUtils buttonFixStates:editButton];
[tableController.tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4
[tableController.tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
[tableController.tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4
[tableController.tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if([ContactSelection getSelectionMode] == ContactSelectionModeEdit ||
[ContactSelection getSelectionMode] == ContactSelectionModeNone) {
[editButton setHidden:FALSE];
} else {
[editButton setHidden:TRUE];
}
[super viewWillAppear:animated];
if ([ContactSelection getSelectionMode] == ContactSelectionModeEdit ||
[ContactSelection getSelectionMode] == ContactSelectionModeNone) {
[editButton setHidden:FALSE];
} else {
[editButton setHidden:TRUE];
}
}
#pragma mark - UICompositeViewDelegate Functions
@ -227,79 +224,77 @@ static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef inf
static UICompositeViewDescription *compositeDescription = nil;
+ (UICompositeViewDescription *)compositeViewDescription {
if(compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"ContactDetails"
content:@"ContactDetailsViewController"
stateBar:nil
stateBarEnabled:false
tabBar:@"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
}
return compositeDescription;
if (compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"ContactDetails"
content:@"ContactDetailsViewController"
stateBar:nil
stateBarEnabled:false
tabBar:@"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
}
return compositeDescription;
}
#pragma mark -
- (void)enableEdit:(BOOL)animated {
if(![tableController isEditing]) {
[tableController setEditing:TRUE animated:animated];
}
[editButton setOn];
[cancelButton setHidden:FALSE];
[backButton setHidden:TRUE];
if (![tableController isEditing]) {
[tableController setEditing:TRUE animated:animated];
}
[editButton setOn];
[cancelButton setHidden:FALSE];
[backButton setHidden:TRUE];
}
- (void)disableEdit:(BOOL)animated {
if([tableController isEditing]) {
[tableController setEditing:FALSE animated:animated];
}
[editButton setOff];
[cancelButton setHidden:TRUE];
[backButton setHidden:FALSE];
if ([tableController isEditing]) {
[tableController setEditing:FALSE animated:animated];
}
[editButton setOff];
[cancelButton setHidden:TRUE];
[backButton setHidden:FALSE];
}
#pragma mark - Action Functions
- (IBAction)onCancelClick:(id)event {
[self disableEdit:TRUE];
[self resetData];
[self disableEdit:TRUE];
[self resetData];
}
- (IBAction)onBackClick:(id)event {
if([ContactSelection getSelectionMode] == ContactSelectionModeEdit) {
[ContactSelection setSelectionMode:ContactSelectionModeNone];
}
[[PhoneMainView instance] popCurrentView];
if ([ContactSelection getSelectionMode] == ContactSelectionModeEdit) {
[ContactSelection setSelectionMode:ContactSelectionModeNone];
}
[[PhoneMainView instance] popCurrentView];
}
- (IBAction)onEditClick:(id)event {
if([tableController isEditing]) {
if([tableController isValid]) {
[self disableEdit:TRUE];
[self saveData];
}
} else {
[self enableEdit:TRUE];
}
if ([tableController isEditing]) {
if ([tableController isValid]) {
[self disableEdit:TRUE];
[self saveData];
}
} else {
[self enableEdit:TRUE];
}
}
- (void)onRemove:(id)event {
[self disableEdit:FALSE];
[self removeContact];
[[PhoneMainView instance] popCurrentView];
[self disableEdit:FALSE];
[self removeContact];
[[PhoneMainView instance] popCurrentView];
}
- (void)onModification:(id)event {
if(![tableController isEditing] || [tableController isValid]) {
[editButton setEnabled:TRUE];
} else {
[editButton setEnabled:FALSE];
}
if (![tableController isEditing] || [tableController isValid]) {
[editButton setEnabled:TRUE];
} else {
[editButton setEnabled:FALSE];
}
}
@end

View file

@ -27,13 +27,12 @@
@implementation ContactsTableViewController
static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef info, void *context);
static void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info, void *context);
#pragma mark - Lifecycle Functions
- (void)initContactsTableViewController {
addressBookMap = [[OrderedDictionary alloc] init];
addressBookMap = [[OrderedDictionary alloc] init];
avatarMap = [[NSMutableDictionary alloc] init];
addressBook = ABAddressBookCreateWithOptions(nil, nil);
@ -62,35 +61,35 @@ static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef inf
CFRelease(addressBook);
}
#pragma mark -
- (BOOL)contactHasValidSipDomain:(ABRecordRef)person {
// Check if one of the contact' sip URI matches the expected SIP filter
ABMultiValueRef personSipAddresses = ABRecordCopyValue(person, kABPersonInstantMessageProperty);
BOOL match = false;
NSString * filter = [ContactSelection getSipFilter];
NSString *filter = [ContactSelection getSipFilter];
for(int i = 0; i < ABMultiValueGetCount(personSipAddresses) && !match; ++i) {
for (int i = 0; i < ABMultiValueGetCount(personSipAddresses) && !match; ++i) {
CFDictionaryRef lDict = ABMultiValueCopyValueAtIndex(personSipAddresses, i);
if(CFDictionaryContainsKey(lDict, kABPersonInstantMessageServiceKey)) {
if (CFDictionaryContainsKey(lDict, kABPersonInstantMessageServiceKey)) {
CFStringRef serviceKey = CFDictionaryGetValue(lDict, kABPersonInstantMessageServiceKey);
if (CFStringCompare((CFStringRef)[LinphoneManager instance].contactSipField, serviceKey, kCFCompareCaseInsensitive) == 0) {
if (CFStringCompare((CFStringRef)[LinphoneManager instance].contactSipField, serviceKey,
kCFCompareCaseInsensitive) == 0) {
match = true;
}
} else {
//check domain
LinphoneAddress* address = linphone_address_new([(NSString*)CFDictionaryGetValue(lDict,kABPersonInstantMessageUsernameKey) UTF8String]);
} else {
// check domain
LinphoneAddress *address = linphone_address_new(
[(NSString *)CFDictionaryGetValue(lDict, kABPersonInstantMessageUsernameKey) UTF8String]);
if (address) {
const char* dom =linphone_address_get_domain(address);
if( dom != NULL ){
NSString* domain = [NSString stringWithCString:dom
encoding:[NSString defaultCStringEncoding]];
const char *dom = linphone_address_get_domain(address);
if (dom != NULL) {
NSString *domain = [NSString stringWithCString:dom encoding:[NSString defaultCStringEncoding]];
if (([filter compare:@"*" options:NSCaseInsensitiveSearch] == NSOrderedSame)
|| ([filter compare:domain options:NSCaseInsensitiveSearch] == NSOrderedSame)) {
if (([filter compare:@"*" options:NSCaseInsensitiveSearch] == NSOrderedSame) ||
([filter compare:domain options:NSCaseInsensitiveSearch] == NSOrderedSame)) {
match = true;
}
}
@ -103,12 +102,12 @@ static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef inf
return match;
}
static int ms_strcmpfuz(const char * fuzzy_word, const char * sentence) {
if (! fuzzy_word || !sentence) {
static int ms_strcmpfuz(const char *fuzzy_word, const char *sentence) {
if (!fuzzy_word || !sentence) {
return fuzzy_word == sentence;
}
const char * c = fuzzy_word;
const char * within_sentence = sentence;
const char *c = fuzzy_word;
const char *within_sentence = sentence;
for (; c != NULL && *c != '\0' && within_sentence != NULL; ++c) {
within_sentence = strchr(within_sentence, *c);
// Could not find c character in sentence. Abort.
@ -125,7 +124,7 @@ static int ms_strcmpfuz(const char * fuzzy_word, const char * sentence) {
- (void)loadData {
LOGI(@"Load contact list");
@synchronized (addressBookMap) {
@synchronized(addressBookMap) {
// Reset Address book
[addressBookMap removeAllObjects];
@ -136,10 +135,10 @@ static int ms_strcmpfuz(const char * fuzzy_word, const char * sentence) {
ABRecordRef person = (__bridge ABRecordRef)lPerson;
// Do not add the contact directly if we set some filter
if([ContactSelection getSipFilter] || [ContactSelection emailFilterEnabled]) {
if ([ContactSelection getSipFilter] || [ContactSelection emailFilterEnabled]) {
add = false;
}
if([ContactSelection getSipFilter] && [self contactHasValidSipDomain:person]) {
if ([ContactSelection getSipFilter] && [self contactHasValidSipDomain:person]) {
add = true;
}
if (!add && [ContactSelection emailFilterEnabled]) {
@ -150,44 +149,50 @@ static int ms_strcmpfuz(const char * fuzzy_word, const char * sentence) {
CFRelease(personEmailAddresses);
}
if(add) {
NSString* lFirstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString* lLocalizedFirstName = [FastAddressBook localizedLabel:lFirstName];
NSString* lLastName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
NSString* lLocalizedLastName = [FastAddressBook localizedLabel:lLastName];
NSString* lOrganization = CFBridgingRelease(ABRecordCopyValue(person, kABPersonOrganizationProperty));
NSString* lLocalizedlOrganization = [FastAddressBook localizedLabel:lOrganization];
if (add) {
NSString *lFirstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lLocalizedFirstName = [FastAddressBook localizedLabel:lFirstName];
NSString *lLastName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
NSString *lLocalizedLastName = [FastAddressBook localizedLabel:lLastName];
NSString *lOrganization = CFBridgingRelease(ABRecordCopyValue(person, kABPersonOrganizationProperty));
NSString *lLocalizedlOrganization = [FastAddressBook localizedLabel:lOrganization];
NSString *name = nil;
if(lLocalizedFirstName.length && lLocalizedLastName.length ) {
name=[NSString stringWithFormat:@"%@ %@", lLocalizedFirstName, lLocalizedLastName];
} else if(lLocalizedLastName.length) {
name=[NSString stringWithFormat:@"%@",lLocalizedLastName];
} else if(lLocalizedFirstName.length) {
name=[NSString stringWithFormat:@"%@",lLocalizedFirstName];
} else if(lLocalizedlOrganization.length) {
name=[NSString stringWithFormat:@"%@",lLocalizedlOrganization];
if (lLocalizedFirstName.length && lLocalizedLastName.length) {
name = [NSString stringWithFormat:@"%@ %@", lLocalizedFirstName, lLocalizedLastName];
} else if (lLocalizedLastName.length) {
name = [NSString stringWithFormat:@"%@", lLocalizedLastName];
} else if (lLocalizedFirstName.length) {
name = [NSString stringWithFormat:@"%@", lLocalizedFirstName];
} else if (lLocalizedlOrganization.length) {
name = [NSString stringWithFormat:@"%@", lLocalizedlOrganization];
}
if(name != nil && [name length] > 0) {
if (name != nil && [name length] > 0) {
// Add the contact only if it fuzzy match filter too (if any)
if ([ContactSelection getNameOrEmailFilter] == nil ||
(ms_strcmpfuz([[[ContactSelection getNameOrEmailFilter] lowercaseString] UTF8String], [[name lowercaseString] UTF8String]) == 0)) {
(ms_strcmpfuz([[[ContactSelection getNameOrEmailFilter] lowercaseString] UTF8String],
[[name lowercaseString] UTF8String]) == 0)) {
//Sort contacts by first letter. We need to translate the name to ASCII first, because of UTF-8 issues. For instance
// Sort contacts by first letter. We need to translate the name to ASCII first, because of UTF-8
// issues. For instance
// we expect order: Alberta(A tilde) before ASylvano.
NSData *name2ASCIIdata = [name dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *name2ASCII = [[NSString alloc] initWithData:name2ASCIIdata encoding:NSASCIIStringEncoding];
NSData *name2ASCIIdata =
[name dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *name2ASCII =
[[NSString alloc] initWithData:name2ASCIIdata encoding:NSASCIIStringEncoding];
NSString *firstChar = [[name2ASCII substringToIndex:1] uppercaseString];
// Put in correct subDic
if([firstChar characterAtIndex:0] < 'A' || [firstChar characterAtIndex:0] > 'Z') {
if ([firstChar characterAtIndex:0] < 'A' || [firstChar characterAtIndex:0] > 'Z') {
firstChar = @"#";
}
OrderedDictionary *subDic =[addressBookMap objectForKey: firstChar];
if(subDic == nil) {
OrderedDictionary *subDic = [addressBookMap objectForKey:firstChar];
if (subDic == nil) {
subDic = [[OrderedDictionary alloc] init];
[addressBookMap insertObject:subDic forKey:firstChar selector:@selector(caseInsensitiveCompare:)];
[addressBookMap insertObject:subDic
forKey:firstChar
selector:@selector(caseInsensitiveCompare:)];
}
[subDic insertObject:lPerson forKey:name2ASCII selector:@selector(caseInsensitiveCompare:)];
}
@ -198,8 +203,8 @@ static int ms_strcmpfuz(const char * fuzzy_word, const char * sentence) {
[self.tableView reloadData];
}
static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef info, void *context) {
ContactsTableViewController* controller = (__bridge ContactsTableViewController*)context;
static void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info, void *context) {
ContactsTableViewController *controller = (__bridge ContactsTableViewController *)context;
ABAddressBookRevert(addressBook);
[controller->avatarMap removeAllObjects];
[controller loadData];
@ -216,8 +221,7 @@ static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef inf
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [(OrderedDictionary *)[addressBookMap objectForKey: [addressBookMap keyAtIndex: section]] count];
return [(OrderedDictionary *)[addressBookMap objectForKey:[addressBookMap keyAtIndex:section]] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
@ -231,45 +235,47 @@ static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef inf
cell.selectedBackgroundView = selectedBackgroundView;
[selectedBackgroundView setBackgroundColor:LINPHONE_TABLE_CELL_BACKGROUND_COLOR];
}
OrderedDictionary *subDic = [addressBookMap objectForKey: [addressBookMap keyAtIndex: [indexPath section]]];
OrderedDictionary *subDic = [addressBookMap objectForKey:[addressBookMap keyAtIndex:[indexPath section]]];
NSString *key = [[subDic allKeys] objectAtIndex:[indexPath row]];
ABRecordRef contact = (__bridge ABRecordRef)([subDic objectForKey:key]);
// Cached avatar
UIImage *image = nil;
id data = [avatarMap objectForKey:[NSNumber numberWithInt: ABRecordGetRecordID(contact)]];
if(data == nil) {
id data = [avatarMap objectForKey:[NSNumber numberWithInt:ABRecordGetRecordID(contact)]];
if (data == nil) {
image = [FastAddressBook getContactImage:contact thumbnail:true];
if(image != nil) {
[avatarMap setObject:image forKey:[NSNumber numberWithInt: ABRecordGetRecordID(contact)]];
if (image != nil) {
[avatarMap setObject:image forKey:[NSNumber numberWithInt:ABRecordGetRecordID(contact)]];
} else {
[avatarMap setObject:[NSNull null] forKey:[NSNumber numberWithInt: ABRecordGetRecordID(contact)]];
[avatarMap setObject:[NSNull null] forKey:[NSNumber numberWithInt:ABRecordGetRecordID(contact)]];
}
} else if(data != [NSNull null]) {
} else if (data != [NSNull null]) {
image = data;
}
if(image == nil) {
if (image == nil) {
image = [UIImage imageNamed:@"avatar_unknown_small.png"];
}
[[cell avatarImage] setImage:image];
[cell setContact: contact];
[cell setContact:contact];
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [addressBookMap keyAtIndex: section];
return [addressBookMap keyAtIndex:section];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
OrderedDictionary *subDic = [addressBookMap objectForKey: [addressBookMap keyAtIndex: [indexPath section]]];
ABRecordRef lPerson = (__bridge ABRecordRef)([subDic objectForKey: [subDic keyAtIndex:[indexPath row]]]);
OrderedDictionary *subDic = [addressBookMap objectForKey:[addressBookMap keyAtIndex:[indexPath section]]];
ABRecordRef lPerson = (__bridge ABRecordRef)([subDic objectForKey:[subDic keyAtIndex:[indexPath row]]]);
// Go to Contact details view
ContactDetailsViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ContactDetailsViewController compositeViewDescription] push:TRUE], ContactDetailsViewController);
if(controller != nil) {
if([ContactSelection getSelectionMode] != ContactSelectionModeEdit) {
ContactDetailsViewController *controller = DYNAMIC_CAST(
[[PhoneMainView instance] changeCurrentView:[ContactDetailsViewController compositeViewDescription] push:TRUE],
ContactDetailsViewController);
if (controller != nil) {
if ([ContactSelection getSelectionMode] != ContactSelectionModeEdit) {
[controller setContact:lPerson];
} else {
[controller editContact:lPerson address:[ContactSelection getAddAddress]];
@ -277,10 +283,10 @@ static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef inf
}
}
#pragma mark - UITableViewDelegate Functions
- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView
editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
// Detemine if it's in editing mode
if (self.editing) {
return UITableViewCellEditingStyleDelete;

View file

@ -26,10 +26,10 @@
@implementation ContactSelection
static ContactSelectionMode sSelectionMode = ContactSelectionModeNone;
static NSString* sAddAddress = nil;
static NSString* sSipFilter = nil;
static NSString *sAddAddress = nil;
static NSString *sSipFilter = nil;
static BOOL sEnableEmailFilter = FALSE;
static NSString* sNameOrEmailFilter;
static NSString *sNameOrEmailFilter;
+ (void)setSelectionMode:(ContactSelectionMode)selectionMode {
sSelectionMode = selectionMode;
@ -39,24 +39,24 @@ static NSString* sNameOrEmailFilter;
return sSelectionMode;
}
+ (void)setAddAddress:(NSString*)address {
if(sAddAddress != nil) {
sAddAddress= nil;
+ (void)setAddAddress:(NSString *)address {
if (sAddAddress != nil) {
sAddAddress = nil;
}
if(address != nil) {
if (address != nil) {
sAddAddress = address;
}
}
+ (NSString*)getAddAddress {
+ (NSString *)getAddAddress {
return sAddAddress;
}
+ (void)setSipFilter:(NSString*)domain {
+ (void)setSipFilter:(NSString *)domain {
sSipFilter = domain;
}
+ (NSString*)getSipFilter {
+ (NSString *)getSipFilter {
return sSipFilter;
}
@ -68,15 +68,14 @@ static NSString* sNameOrEmailFilter;
return sEnableEmailFilter;
}
+ (void)setNameOrEmailFilter:(NSString*)fuzzyName {
+ (void)setNameOrEmailFilter:(NSString *)fuzzyName {
sNameOrEmailFilter = fuzzyName;
}
+ (NSString*)getNameOrEmailFilter {
+ (NSString *)getNameOrEmailFilter {
return sNameOrEmailFilter;
}
@end
@implementation ContactsViewController
@ -92,13 +91,7 @@ static NSString* sNameOrEmailFilter;
@synthesize addButton;
@synthesize toolBar;
typedef enum _HistoryView {
History_All,
History_Linphone,
History_Search,
History_MAX
} HistoryView;
typedef enum _HistoryView { History_All, History_Linphone, History_Search, History_MAX } HistoryView;
#pragma mark - Lifecycle Functions
@ -106,27 +99,25 @@ typedef enum _HistoryView {
return [super initWithNibName:@"ContactsViewController" bundle:[NSBundle mainBundle]];
}
#pragma mark - UICompositeViewDelegate Functions
static UICompositeViewDescription *compositeDescription = nil;
+ (UICompositeViewDescription *)compositeViewDescription {
if(compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"Contacts"
content:@"ContactsViewController"
stateBar:nil
stateBarEnabled:false
tabBar:@"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
if (compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"Contacts"
content:@"ContactsViewController"
stateBar:nil
stateBarEnabled:false
tabBar:@"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
}
return compositeDescription;
}
#pragma mark - ViewController Functions
- (void)viewWillDisappear:(BOOL)animated {
@ -134,27 +125,29 @@ static UICompositeViewDescription *compositeDescription = nil;
}
- (void)relayoutTableView {
CGRect subViewFrame= self.view.frame;
CGRect subViewFrame = self.view.frame;
// let the toolBar be visible
subViewFrame.origin.y += self.toolBar.frame.size.height;
subViewFrame.size.height -= self.toolBar.frame.size.height;
[UIView animateWithDuration:0.2 animations:^{
self.tableView.frame = subViewFrame;
}];
[UIView animateWithDuration:0.2
animations:^{
self.tableView.frame = subViewFrame;
}];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// cannot change search bar icon nor text font from the interface builder...
// [_searchBar setImage:[UIImage imageNamed:@"contact_search.png" ] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
// [_searchBar setImage:[UIImage imageNamed:@"contact_search.png" ] forSearchBarIcon:UISearchBarIconSearch
// state:UIControlStateNormal];
// UITextField *searchText = [_searchBar valueForKey:@"_searchField"];
// [searchText setFont:[UIFont fontWithName:@"CustomFont" size:12]];
_searchBar.showsCancelButton = (_searchBar.text.length > 0);
BOOL use_system = [[LinphoneManager instance] lpConfigBoolForKey:@"use_system_contacts"];
if( use_system && !self.sysViewController){// use system contacts
ABPeoplePickerNavigationController* picker = [[ABPeoplePickerNavigationController alloc] init];
if (use_system && !self.sysViewController) { // use system contacts
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
picker.view.frame = self.view.frame;
@ -163,8 +156,7 @@ static UICompositeViewDescription *compositeDescription = nil;
self.sysViewController = picker;
self.searchBar.hidden = TRUE;
} else if( !use_system && !self.tableController ){
} else if (!use_system && !self.tableController) {
self.tableController = [[ContactsTableViewController alloc] init];
self.tableView = [[UITableView alloc] init];
@ -174,14 +166,11 @@ static UICompositeViewDescription *compositeDescription = nil;
[self relayoutTableView];
self.tableView.dataSource = self.tableController;
self.tableView.delegate = self.tableController;
self.tableView.delegate = self.tableController;
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight |
UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleTopMargin |
UIViewAutoresizingFlexibleBottomMargin |
UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin;
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin |
UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
[self.view addSubview:tableView];
[self update];
@ -193,13 +182,15 @@ static UICompositeViewDescription *compositeDescription = nil;
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if(![FastAddressBook isAuthorized]) {
UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Address book",nil)
message:NSLocalizedString(@"You must authorize the application to have access to address book.\n"
"Toggle the application in Settings > Privacy > Contacts",nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(@"Continue",nil)
otherButtonTitles:nil];
if (![FastAddressBook isAuthorized]) {
UIAlertView *error = [[UIAlertView alloc]
initWithTitle:NSLocalizedString(@"Address book", nil)
message:NSLocalizedString(@"You must authorize the application to have access to address book.\n"
"Toggle the application in Settings > Privacy > Contacts",
nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(@"Continue", nil)
otherButtonTitles:nil];
[error show];
[[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]];
}
@ -218,7 +209,7 @@ static UICompositeViewDescription *compositeDescription = nil;
// Set selected+over background: IB lack !
[linphoneButton setBackgroundImage:[UIImage imageNamed:@"contacts_linphone_selected.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[linphoneButton setTitle:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]
forState:UIControlStateNormal];
@ -227,19 +218,18 @@ static UICompositeViewDescription *compositeDescription = nil;
// Set selected+over background: IB lack !
[allButton setBackgroundImage:[UIImage imageNamed:@"contacts_all_selected.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:allButton];
[tableController.tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4
[tableController.tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
[tableController.tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
}
#pragma mark -
- (void)changeView:(HistoryView)view {
if(view == History_All) {
if (view == History_All) {
[ContactSelection setSipFilter:nil];
[ContactSelection enableEmailFilter:FALSE];
[tableController loadData];
@ -248,7 +238,7 @@ static UICompositeViewDescription *compositeDescription = nil;
allButton.selected = FALSE;
}
if(view == History_Linphone) {
if (view == History_Linphone) {
[ContactSelection setSipFilter:[LinphoneManager instance].contactFilter];
[ContactSelection enableEmailFilter:FALSE];
[tableController loadData];
@ -260,17 +250,17 @@ static UICompositeViewDescription *compositeDescription = nil;
- (void)refreshButtons {
switch ([ContactSelection getSelectionMode]) {
case ContactSelectionModePhone:
case ContactSelectionModeMessage:
[addButton setHidden:TRUE];
[backButton setHidden:FALSE];
break;
default:
[addButton setHidden:FALSE];
[backButton setHidden:TRUE];
break;
case ContactSelectionModePhone:
case ContactSelectionModeMessage:
[addButton setHidden:TRUE];
[backButton setHidden:FALSE];
break;
default:
[addButton setHidden:FALSE];
[backButton setHidden:TRUE];
break;
}
if([ContactSelection getSipFilter]) {
if ([ContactSelection getSipFilter]) {
allButton.selected = FALSE;
linphoneButton.selected = TRUE;
} else {
@ -284,22 +274,23 @@ static UICompositeViewDescription *compositeDescription = nil;
[tableController loadData];
}
#pragma mark - Action Functions
- (IBAction)onAllClick:(id)event {
[self changeView: History_All];
[self changeView:History_All];
}
- (IBAction)onLinphoneClick:(id)event {
[self changeView: History_Linphone];
[self changeView:History_Linphone];
}
- (IBAction)onAddContactClick:(id)event {
// Go to Contact details view
ContactDetailsViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ContactDetailsViewController compositeViewDescription] push:TRUE], ContactDetailsViewController);
if(controller != nil) {
if([ContactSelection getAddAddress] == nil) {
ContactDetailsViewController *controller = DYNAMIC_CAST(
[[PhoneMainView instance] changeCurrentView:[ContactDetailsViewController compositeViewDescription] push:TRUE],
ContactDetailsViewController);
if (controller != nil) {
if ([ContactSelection getAddAddress] == nil) {
[controller newContact];
} else {
[controller newContact:[ContactSelection getAddAddress]];
@ -311,7 +302,6 @@ static UICompositeViewDescription *compositeDescription = nil;
[[PhoneMainView instance] popCurrentView];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[self searchBar:searchBar textDidChange:nil];
[searchBar resignFirstResponder];
@ -325,11 +315,9 @@ static UICompositeViewDescription *compositeDescription = nil;
[self relayoutTableView];
}
#pragma mark - ABPeoplePickerDelegate
-(void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
{
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker {
[[PhoneMainView instance] popCurrentView];
return;
}
@ -337,7 +325,6 @@ static UICompositeViewDescription *compositeDescription = nil;
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person {
return true;
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
@ -346,12 +333,14 @@ static UICompositeViewDescription *compositeDescription = nil;
identifier:(ABMultiValueIdentifier)identifier {
CFTypeRef multiValue = ABRecordCopyValue(person, property);
CFIndex valueIdx = ABMultiValueGetIndexForIdentifier(multiValue,identifier);
CFIndex valueIdx = ABMultiValueGetIndexForIdentifier(multiValue, identifier);
NSString *phoneNumber = (NSString *)CFBridgingRelease(ABMultiValueCopyValueAtIndex(multiValue, valueIdx));
// Go to dialer view
DialerViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]], DialerViewController);
if(controller != nil) {
[controller call:phoneNumber displayName:(NSString*)CFBridgingRelease(ABRecordCopyCompositeName(person))];
DialerViewController *controller =
DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]],
DialerViewController);
if (controller != nil) {
[controller call:phoneNumber displayName:(NSString *)CFBridgingRelease(ABRecordCopyCompositeName(person))];
}
CFRelease(multiValue);
return false;
@ -368,15 +357,15 @@ static UICompositeViewDescription *compositeDescription = nil;
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
[searchBar setShowsCancelButton:FALSE animated:TRUE];
[searchBar setShowsCancelButton:FALSE animated:TRUE];
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
[searchBar setShowsCancelButton:TRUE animated:TRUE];
[searchBar setShowsCancelButton:TRUE animated:TRUE];
}
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[searchBar resignFirstResponder];
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[searchBar resignFirstResponder];
}
- (void)viewDidUnload {

View file

@ -29,7 +29,6 @@
#include "linphone/linphonecore.h"
@implementation DialerViewController
@synthesize transferMode;
@ -62,209 +61,199 @@
#pragma mark - Lifecycle Functions
- (id)init {
self = [super initWithNibName:@"DialerViewController" bundle:[NSBundle mainBundle]];
if(self) {
self->transferMode = FALSE;
}
return self;
self = [super initWithNibName:@"DialerViewController" bundle:[NSBundle mainBundle]];
if (self) {
self->transferMode = FALSE;
}
return self;
}
- (void)dealloc {
// Remove all observers
[[NSNotificationCenter defaultCenter] removeObserver:self];
// Remove all observers
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - UICompositeViewDelegate Functions
static UICompositeViewDescription *compositeDescription = nil;
+ (UICompositeViewDescription *)compositeViewDescription {
if(compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"Dialer"
content:@"DialerViewController"
stateBar:@"UIStateBar"
stateBarEnabled:true
tabBar:@"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
compositeDescription.darkBackground = true;
}
return compositeDescription;
if (compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"Dialer"
content:@"DialerViewController"
stateBar:@"UIStateBar"
stateBarEnabled:true
tabBar:@"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
compositeDescription.darkBackground = true;
}
return compositeDescription;
}
#pragma mark - ViewController Functions
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[super viewWillAppear:animated];
// Set observer
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(callUpdateEvent:)
name:kLinphoneCallUpdate
object:nil];
// Set observer
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(callUpdateEvent:)
name:kLinphoneCallUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(coreUpdateEvent:)
name:kLinphoneCoreUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(coreUpdateEvent:)
name:kLinphoneCoreUpdate
object:nil];
// technically not needed, but older versions of linphone had this button
// disabled by default. In this case, updating by pushing a new version with
// xcode would result in the callbutton being disabled all the time.
// We force it enabled anyway now.
[callButton setEnabled:TRUE];
// technically not needed, but older versions of linphone had this button
// disabled by default. In this case, updating by pushing a new version with
// xcode would result in the callbutton being disabled all the time.
// We force it enabled anyway now.
[callButton setEnabled:TRUE];
// Update on show
LinphoneManager *mgr = [LinphoneManager instance];
LinphoneCore* lc = [LinphoneManager getLc];
LinphoneCall* call = linphone_core_get_current_call(lc);
LinphoneCallState state = (call != NULL)?linphone_call_get_state(call): 0;
[self callUpdate:call state:state];
// Update on show
LinphoneManager *mgr = [LinphoneManager instance];
LinphoneCore *lc = [LinphoneManager getLc];
LinphoneCall *call = linphone_core_get_current_call(lc);
LinphoneCallState state = (call != NULL) ? linphone_call_get_state(call) : 0;
[self callUpdate:call state:state];
if([LinphoneManager runningOnIpad]) {
BOOL videoEnabled = linphone_core_video_enabled(lc);
BOOL previewPref = [mgr lpConfigBoolForKey:@"preview_preference"];
if ([LinphoneManager runningOnIpad]) {
BOOL videoEnabled = linphone_core_video_enabled(lc);
BOOL previewPref = [mgr lpConfigBoolForKey:@"preview_preference"];
if( videoEnabled && previewPref ) {
linphone_core_set_native_preview_window_id(lc, (unsigned long)videoPreview);
if (videoEnabled && previewPref) {
linphone_core_set_native_preview_window_id(lc, (unsigned long)videoPreview);
if( !linphone_core_video_preview_enabled(lc)){
if (!linphone_core_video_preview_enabled(lc)) {
linphone_core_enable_video_preview(lc, TRUE);
}
[backgroundView setHidden:FALSE];
[videoCameraSwitch setHidden:FALSE];
} else {
linphone_core_set_native_preview_window_id(lc, (unsigned long)NULL);
linphone_core_enable_video_preview(lc, FALSE);
[backgroundView setHidden:TRUE];
[videoCameraSwitch setHidden:TRUE];
}
}
[addressField setText:@""];
[backgroundView setHidden:FALSE];
[videoCameraSwitch setHidden:FALSE];
} else {
linphone_core_set_native_preview_window_id(lc, (unsigned long)NULL);
linphone_core_enable_video_preview(lc, FALSE);
[backgroundView setHidden:TRUE];
[videoCameraSwitch setHidden:TRUE];
}
}
[addressField setText:@""];
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_6_0 // attributed string only available since iOS6
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
// fix placeholder bar color in iOS7
UIColor *color = [UIColor grayColor];
NSAttributedString* placeHolderString = [[NSAttributedString alloc]
initWithString:NSLocalizedString(@"Enter an address", @"Enter an address")
attributes:@{NSForegroundColorAttributeName: color}];
addressField.attributedPlaceholder = placeHolderString;
}
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
// fix placeholder bar color in iOS7
UIColor *color = [UIColor grayColor];
NSAttributedString *placeHolderString =
[[NSAttributedString alloc] initWithString:NSLocalizedString(@"Enter an address", @"Enter an address")
attributes:@{NSForegroundColorAttributeName : color}];
addressField.attributedPlaceholder = placeHolderString;
}
#endif
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[super viewWillDisappear:animated];
// Remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneCallUpdate
object:nil];
// Remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneCallUpdate object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneCoreUpdate
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneCoreUpdate object:nil];
}
- (void)viewDidLoad {
[super viewDidLoad];
[super viewDidLoad];
[zeroButton setDigit:'0'];
[oneButton setDigit:'1'];
[twoButton setDigit:'2'];
[threeButton setDigit:'3'];
[fourButton setDigit:'4'];
[fiveButton setDigit:'5'];
[sixButton setDigit:'6'];
[sevenButton setDigit:'7'];
[eightButton setDigit:'8'];
[nineButton setDigit:'9'];
[starButton setDigit:'*'];
[sharpButton setDigit:'#'];
[zeroButton setDigit:'0'];
[oneButton setDigit:'1'];
[twoButton setDigit:'2'];
[threeButton setDigit:'3'];
[fourButton setDigit:'4'];
[fiveButton setDigit:'5'];
[sixButton setDigit:'6'];
[sevenButton setDigit:'7'];
[eightButton setDigit:'8'];
[nineButton setDigit:'9'];
[starButton setDigit:'*'];
[sharpButton setDigit:'#'];
[addressField setAdjustsFontSizeToFitWidth:TRUE]; // Not put it in IB: issue with placeholder size
[addressField setAdjustsFontSizeToFitWidth:TRUE]; // Not put it in IB: issue with placeholder size
if([LinphoneManager runningOnIpad]) {
if ([LinphoneManager instance].frontCamId != nil) {
// only show camera switch button if we have more than 1 camera
[videoCameraSwitch setHidden:FALSE];
}
}
if ([LinphoneManager runningOnIpad]) {
if ([LinphoneManager instance].frontCamId != nil) {
// only show camera switch button if we have more than 1 camera
[videoCameraSwitch setHidden:FALSE];
}
}
}
- (void)viewDidUnload {
[super viewDidUnload];
[super viewDidUnload];
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
CGRect frame = [videoPreview frame];
switch (toInterfaceOrientation) {
case UIInterfaceOrientationPortrait:
[videoPreview setTransform: CGAffineTransformMakeRotation(0)];
break;
case UIInterfaceOrientationPortraitUpsideDown:
[videoPreview setTransform: CGAffineTransformMakeRotation(M_PI)];
break;
case UIInterfaceOrientationLandscapeLeft:
[videoPreview setTransform: CGAffineTransformMakeRotation(M_PI / 2)];
break;
case UIInterfaceOrientationLandscapeRight:
[videoPreview setTransform: CGAffineTransformMakeRotation(-M_PI / 2)];
break;
default:
break;
}
[videoPreview setFrame:frame];
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
CGRect frame = [videoPreview frame];
switch (toInterfaceOrientation) {
case UIInterfaceOrientationPortrait:
[videoPreview setTransform:CGAffineTransformMakeRotation(0)];
break;
case UIInterfaceOrientationPortraitUpsideDown:
[videoPreview setTransform:CGAffineTransformMakeRotation(M_PI)];
break;
case UIInterfaceOrientationLandscapeLeft:
[videoPreview setTransform:CGAffineTransformMakeRotation(M_PI / 2)];
break;
case UIInterfaceOrientationLandscapeRight:
[videoPreview setTransform:CGAffineTransformMakeRotation(-M_PI / 2)];
break;
default:
break;
}
[videoPreview setFrame:frame];
}
#pragma mark - Event Functions
- (void)callUpdateEvent:(NSNotification*)notif {
LinphoneCall *call = [[notif.userInfo objectForKey: @"call"] pointerValue];
LinphoneCallState state = [[notif.userInfo objectForKey: @"state"] intValue];
[self callUpdate:call state:state];
- (void)callUpdateEvent:(NSNotification *)notif {
LinphoneCall *call = [[notif.userInfo objectForKey:@"call"] pointerValue];
LinphoneCallState state = [[notif.userInfo objectForKey:@"state"] intValue];
[self callUpdate:call state:state];
}
- (void)coreUpdateEvent:(NSNotification*)notif {
if([LinphoneManager runningOnIpad]) {
LinphoneCore* lc = [LinphoneManager getLc];
if(linphone_core_video_enabled(lc) && linphone_core_video_preview_enabled(lc)) {
linphone_core_set_native_preview_window_id(lc, (unsigned long)videoPreview);
[backgroundView setHidden:FALSE];
[videoCameraSwitch setHidden:FALSE];
} else {
linphone_core_set_native_preview_window_id(lc, (unsigned long)NULL);
[backgroundView setHidden:TRUE];
[videoCameraSwitch setHidden:TRUE];
}
}
- (void)coreUpdateEvent:(NSNotification *)notif {
if ([LinphoneManager runningOnIpad]) {
LinphoneCore *lc = [LinphoneManager getLc];
if (linphone_core_video_enabled(lc) && linphone_core_video_preview_enabled(lc)) {
linphone_core_set_native_preview_window_id(lc, (unsigned long)videoPreview);
[backgroundView setHidden:FALSE];
[videoCameraSwitch setHidden:FALSE];
} else {
linphone_core_set_native_preview_window_id(lc, (unsigned long)NULL);
[backgroundView setHidden:TRUE];
[videoCameraSwitch setHidden:TRUE];
}
}
}
#pragma mark - Debug Functions
-(void)presentMailViewWithTitle:(NSString*)subject forRecipients:(NSArray*)recipients attachLogs:(BOOL)attachLogs {
if( [MFMailComposeViewController canSendMail] ){
MFMailComposeViewController* controller = [[MFMailComposeViewController alloc] init];
if( controller ){
- (void)presentMailViewWithTitle:(NSString *)subject forRecipients:(NSArray *)recipients attachLogs:(BOOL)attachLogs {
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
if (controller) {
controller.mailComposeDelegate = self;
[controller setSubject:subject];
[controller setToRecipients:recipients];
if( attachLogs ){
char * filepath = linphone_core_compress_log_collection([LinphoneManager getLc]);
if (attachLogs) {
char *filepath = linphone_core_compress_log_collection([LinphoneManager getLc]);
if (filepath == NULL) {
LOGE(@"Cannot sent logs: file is NULL");
return;
@ -282,51 +271,60 @@ static UICompositeViewDescription *compositeDescription = nil;
return;
}
[controller setMessageBody:NSLocalizedString(@"Application logs", nil) isHTML:NO];
[controller addAttachmentData:[NSData dataWithContentsOfFile:[NSString stringWithUTF8String:filepath]] mimeType:mimeType fileName:filename];
[controller addAttachmentData:[NSData dataWithContentsOfFile:[NSString stringWithUTF8String:filepath]]
mimeType:mimeType
fileName:filename];
ms_free(filepath);
}
self.modalPresentationStyle = UIModalPresentationPageSheet;
[self.view.window.rootViewController presentViewController:controller animated:TRUE completion:^{}];
[self.view.window.rootViewController presentViewController:controller
animated:TRUE
completion:^{
}];
}
} else {
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:subject
message:NSLocalizedString(@"Error: no mail account configured", nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles: nil];
UIAlertView *alert =
[[UIAlertView alloc] initWithTitle:subject
message:NSLocalizedString(@"Error: no mail account configured", nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil];
[alert show];
}
}
- (BOOL)displayDebugPopup:(NSString *)address {
LinphoneManager *mgr = [LinphoneManager instance];
NSString *debugAddress = [mgr lpConfigStringForKey:@"debug_popup_magic" withDefault:@""];
if (![debugAddress isEqualToString:@""] && [address isEqualToString:debugAddress]) {
- (BOOL)displayDebugPopup:(NSString*)address {
LinphoneManager* mgr = [LinphoneManager instance];
NSString* debugAddress = [mgr lpConfigStringForKey:@"debug_popup_magic" withDefault:@""];
if( ![debugAddress isEqualToString:@""] && [address isEqualToString:debugAddress]){
DTAlertView* alertView = [[DTAlertView alloc] initWithTitle:NSLocalizedString(@"Debug", nil)
DTAlertView *alertView = [[DTAlertView alloc] initWithTitle:NSLocalizedString(@"Debug", nil)
message:NSLocalizedString(@"Choose an action", nil)];
[alertView addCancelButtonWithTitle:NSLocalizedString(@"Cancel", nil) block:nil];
[alertView addButtonWithTitle:NSLocalizedString(@"Send logs", nil) block:^{
NSString* appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
NSString* logsAddress = [mgr lpConfigStringForKey:@"debug_popup_email" withDefault:@"linphone-ios@linphone.org"];
[self presentMailViewWithTitle:appName forRecipients:@[logsAddress] attachLogs:true];
}];
[alertView
addButtonWithTitle:NSLocalizedString(@"Send logs", nil)
block:^{
NSString *appName =
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
NSString *logsAddress =
[mgr lpConfigStringForKey:@"debug_popup_email" withDefault:@"linphone-ios@linphone.org"];
[self presentMailViewWithTitle:appName forRecipients:@[ logsAddress ] attachLogs:true];
}];
BOOL debugEnabled = [[LinphoneManager instance] lpConfigBoolForKey:@"debugenable_preference"];
NSString* actionLog = (debugEnabled ? NSLocalizedString(@"Disable logs", nil) : NSLocalizedString(@"Enable logs", nil));
[alertView addButtonWithTitle:actionLog block:^{
// enable / disable
BOOL enableDebug = ![mgr lpConfigBoolForKey:@"debugenable_preference"];
[mgr lpConfigSetBool:enableDebug forKey:@"debugenable_preference"];
[mgr setLogsEnabled:enableDebug];
}];
BOOL debugEnabled = [[LinphoneManager instance] lpConfigBoolForKey:@"debugenable_preference"];
NSString *actionLog =
(debugEnabled ? NSLocalizedString(@"Disable logs", nil) : NSLocalizedString(@"Enable logs", nil));
[alertView addButtonWithTitle:actionLog
block:^{
// enable / disable
BOOL enableDebug = ![mgr lpConfigBoolForKey:@"debugenable_preference"];
[mgr lpConfigSetBool:enableDebug forKey:@"debugenable_preference"];
[mgr setLogsEnabled:enableDebug];
}];
[alertView show];
return true;
@ -334,111 +332,115 @@ static UICompositeViewDescription *compositeDescription = nil;
return false;
}
#pragma mark -
- (void)callUpdate:(LinphoneCall*)call state:(LinphoneCallState)state {
LinphoneCore *lc = [LinphoneManager getLc];
if(linphone_core_get_calls_nb(lc) > 0) {
if(transferMode) {
[addCallButton setHidden:true];
[transferButton setHidden:false];
} else {
[addCallButton setHidden:false];
[transferButton setHidden:true];
}
[callButton setHidden:true];
[backButton setHidden:false];
[addContactButton setHidden:true];
} else {
[addCallButton setHidden:true];
[callButton setHidden:false];
[backButton setHidden:true];
[addContactButton setHidden:false];
[transferButton setHidden:true];
}
- (void)callUpdate:(LinphoneCall *)call state:(LinphoneCallState)state {
LinphoneCore *lc = [LinphoneManager getLc];
if (linphone_core_get_calls_nb(lc) > 0) {
if (transferMode) {
[addCallButton setHidden:true];
[transferButton setHidden:false];
} else {
[addCallButton setHidden:false];
[transferButton setHidden:true];
}
[callButton setHidden:true];
[backButton setHidden:false];
[addContactButton setHidden:true];
} else {
[addCallButton setHidden:true];
[callButton setHidden:false];
[backButton setHidden:true];
[addContactButton setHidden:false];
[transferButton setHidden:true];
}
}
- (void)setAddress:(NSString*) address {
[addressField setText:address];
- (void)setAddress:(NSString *)address {
[addressField setText:address];
}
- (void)setTransferMode:(BOOL)atransferMode {
transferMode = atransferMode;
LinphoneCall* call = linphone_core_get_current_call([LinphoneManager getLc]);
LinphoneCallState state = (call != NULL)?linphone_call_get_state(call): 0;
[self callUpdate:call state:state];
transferMode = atransferMode;
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
LinphoneCallState state = (call != NULL) ? linphone_call_get_state(call) : 0;
[self callUpdate:call state:state];
}
- (void)call:(NSString*)address {
NSString *displayName = nil;
ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:address];
if(contact) {
displayName = [FastAddressBook getContactDisplayName:contact];
}
[self call:address displayName:displayName];
- (void)call:(NSString *)address {
NSString *displayName = nil;
ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:address];
if (contact) {
displayName = [FastAddressBook getContactDisplayName:contact];
}
[self call:address displayName:displayName];
}
- (void)call:(NSString*)address displayName:(NSString *)displayName {
[[LinphoneManager instance] call:address displayName:displayName transfer:transferMode];
- (void)call:(NSString *)address displayName:(NSString *)displayName {
[[LinphoneManager instance] call:address displayName:displayName transfer:transferMode];
}
#pragma mark - UITextFieldDelegate Functions
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
//[textField performSelector:@selector() withObject:nil afterDelay:0];
return YES;
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
//[textField performSelector:@selector() withObject:nil afterDelay:0];
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if (textField == addressField) {
[addressField resignFirstResponder];
}
return YES;
if (textField == addressField) {
[addressField resignFirstResponder];
}
return YES;
}
#pragma mark - MFComposeMailDelegate
-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
[controller dismissViewControllerAnimated:TRUE completion:^{}];
- (void)mailComposeController:(MFMailComposeViewController *)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError *)error {
[controller dismissViewControllerAnimated:TRUE
completion:^{
}];
[self.navigationController setNavigationBarHidden:TRUE animated:FALSE];
}
#pragma mark - Action Functions
- (IBAction)onAddContactClick: (id) event {
[ContactSelection setSelectionMode:ContactSelectionModeEdit];
[ContactSelection setAddAddress:[addressField text]];
[ContactSelection setSipFilter:nil];
[ContactSelection setNameOrEmailFilter:nil];
[ContactSelection enableEmailFilter:FALSE];
ContactsViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ContactsViewController compositeViewDescription] push:TRUE], ContactsViewController);
if(controller != nil) {
}
- (IBAction)onAddContactClick:(id)event {
[ContactSelection setSelectionMode:ContactSelectionModeEdit];
[ContactSelection setAddAddress:[addressField text]];
[ContactSelection setSipFilter:nil];
[ContactSelection setNameOrEmailFilter:nil];
[ContactSelection enableEmailFilter:FALSE];
ContactsViewController *controller = DYNAMIC_CAST(
[[PhoneMainView instance] changeCurrentView:[ContactsViewController compositeViewDescription] push:TRUE],
ContactsViewController);
if (controller != nil) {
}
}
- (IBAction)onBackClick: (id) event {
[[PhoneMainView instance] changeCurrentView:[InCallViewController compositeViewDescription]];
- (IBAction)onBackClick:(id)event {
[[PhoneMainView instance] changeCurrentView:[InCallViewController compositeViewDescription]];
}
- (IBAction)onAddressChange: (id)sender {
if( [self displayDebugPopup:self.addressField.text] ){
- (IBAction)onAddressChange:(id)sender {
if ([self displayDebugPopup:self.addressField.text]) {
self.addressField.text = @"";
}
if([[addressField text] length] > 0) {
[addContactButton setEnabled:TRUE];
[eraseButton setEnabled:TRUE];
[addCallButton setEnabled:TRUE];
[transferButton setEnabled:TRUE];
} else {
[addContactButton setEnabled:FALSE];
[eraseButton setEnabled:FALSE];
[addCallButton setEnabled:FALSE];
[transferButton setEnabled:FALSE];
}
if ([[addressField text] length] > 0) {
[addContactButton setEnabled:TRUE];
[eraseButton setEnabled:TRUE];
[addCallButton setEnabled:TRUE];
[transferButton setEnabled:TRUE];
} else {
[addContactButton setEnabled:FALSE];
[eraseButton setEnabled:FALSE];
[addCallButton setEnabled:FALSE];
[transferButton setEnabled:FALSE];
}
}
@end

View file

@ -4,18 +4,18 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "LinphoneManager.h"
#import "FirstLoginViewController.h"
@ -33,154 +33,147 @@
#pragma mark - Lifecycle Functions
- (id)init {
return [super initWithNibName:@"FirstLoginViewController" bundle:[NSBundle mainBundle]];
return [super initWithNibName:@"FirstLoginViewController" bundle:[NSBundle mainBundle]];
}
- (void)dealloc {
// Remove all observer
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
// Remove all observer
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - UICompositeViewDelegate Functions
static UICompositeViewDescription *compositeDescription = nil;
+ (UICompositeViewDescription *)compositeViewDescription {
if(compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"FirstLogin"
content:@"FirstLoginViewController"
stateBar:nil
stateBarEnabled:false
tabBar:nil
tabBarEnabled:false
fullscreen:false
landscapeMode:false
portraitMode:true];
}
return compositeDescription;
if (compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"FirstLogin"
content:@"FirstLoginViewController"
stateBar:nil
stateBarEnabled:false
tabBar:nil
tabBarEnabled:false
fullscreen:false
landscapeMode:false
portraitMode:true];
}
return compositeDescription;
}
#pragma mark - ViewController Functions
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Set observer
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(registrationUpdateEvent:)
name:kLinphoneRegistrationUpdate
object:nil];
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Set observer
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(registrationUpdateEvent:)
name:kLinphoneRegistrationUpdate
object:nil];
[usernameField setText:[[LinphoneManager instance] lpConfigStringForKey:@"wizard_username"]];
[passwordField setText:[[LinphoneManager instance] lpConfigStringForKey:@"wizard_password"]];
// Update on show
const MSList* list = linphone_core_get_proxy_config_list([LinphoneManager getLc]);
if(list != NULL) {
LinphoneProxyConfig *config = (LinphoneProxyConfig*) list->data;
if(config) {
[self registrationUpdate:linphone_proxy_config_get_state(config)];
}
}
// Update on show
const MSList *list = linphone_core_get_proxy_config_list([LinphoneManager getLc]);
if (list != NULL) {
LinphoneProxyConfig *config = (LinphoneProxyConfig *)list->data;
if (config) {
[self registrationUpdate:linphone_proxy_config_get_state(config)];
}
}
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
// Remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneRegistrationUpdate
object:nil];
[super viewWillDisappear:animated];
// Remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneRegistrationUpdate object:nil];
}
- (void)viewDidLoad {
[super viewDidLoad];
NSString* siteUrl = [[LinphoneManager instance] lpConfigStringForKey:@"first_login_view_url"];
if (siteUrl==nil) {
siteUrl=@"http://www.linphone.org";
[super viewDidLoad];
NSString *siteUrl = [[LinphoneManager instance] lpConfigStringForKey:@"first_login_view_url"];
if (siteUrl == nil) {
siteUrl = @"http://www.linphone.org";
}
[siteButton setTitle:siteUrl forState:UIControlStateNormal];
}
#pragma mark - Event Functions
- (void)registrationUpdateEvent:(NSNotification*)notif {
[self registrationUpdate:[[notif.userInfo objectForKey: @"state"] intValue]];
- (void)registrationUpdateEvent:(NSNotification *)notif {
[self registrationUpdate:[[notif.userInfo objectForKey:@"state"] intValue]];
}
#pragma mark -
#pragma mark -
- (void)registrationUpdate:(LinphoneRegistrationState)state {
switch (state) {
case LinphoneRegistrationOk: {
[[LinphoneManager instance] lpConfigSetBool:FALSE forKey:@"enable_first_login_view_preference"];
[waitView setHidden:true];
[[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]];
break;
}
case LinphoneRegistrationNone:
case LinphoneRegistrationCleared: {
[waitView setHidden:true];
break;
}
case LinphoneRegistrationFailed: {
[waitView setHidden:true];
//erase uername passwd
[[LinphoneManager instance] lpConfigSetString:nil forKey:@"wizard_username"];
[[LinphoneManager instance] lpConfigSetString:nil forKey:@"wizard_password"];
break;
}
case LinphoneRegistrationProgress: {
[waitView setHidden:false];
break;
}
default: break;
}
switch (state) {
case LinphoneRegistrationOk: {
[[LinphoneManager instance] lpConfigSetBool:FALSE forKey:@"enable_first_login_view_preference"];
[waitView setHidden:true];
[[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]];
break;
}
case LinphoneRegistrationNone:
case LinphoneRegistrationCleared: {
[waitView setHidden:true];
break;
}
case LinphoneRegistrationFailed: {
[waitView setHidden:true];
// erase uername passwd
[[LinphoneManager instance] lpConfigSetString:nil forKey:@"wizard_username"];
[[LinphoneManager instance] lpConfigSetString:nil forKey:@"wizard_password"];
break;
}
case LinphoneRegistrationProgress: {
[waitView setHidden:false];
break;
}
default:
break;
}
}
#pragma mark - Action Functions
- (void)onSiteClick:(id)sender {
NSURL *url = [NSURL URLWithString:siteButton.titleLabel.text];
[[UIApplication sharedApplication] openURL:url];
return;
NSURL *url = [NSURL URLWithString:siteButton.titleLabel.text];
[[UIApplication sharedApplication] openURL:url];
return;
}
- (void)onLoginClick:(id)sender {
NSString* errorMessage=nil;
if ([usernameField.text length]==0 ) {
errorMessage=NSLocalizedString(@"Enter your username",nil);
} else if ([passwordField.text length]==0 ) {
errorMessage=NSLocalizedString(@"Enter your password",nil);
}
NSString *errorMessage = nil;
if ([usernameField.text length] == 0) {
errorMessage = NSLocalizedString(@"Enter your username", nil);
} else if ([passwordField.text length] == 0) {
errorMessage = NSLocalizedString(@"Enter your password", nil);
}
if (errorMessage != nil) {
UIAlertView* error=nil;
error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Alert",nil)
message:errorMessage
delegate:nil
cancelButtonTitle:NSLocalizedString(@"Continue",nil)
UIAlertView *error = nil;
error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Alert", nil)
message:errorMessage
delegate:nil
cancelButtonTitle:NSLocalizedString(@"Continue", nil)
otherButtonTitles:nil];
[error show];
} else {
linphone_core_clear_all_auth_info([LinphoneManager getLc]);
linphone_core_clear_proxy_config([LinphoneManager getLc]);
LinphoneProxyConfig* proxyCfg = linphone_core_create_proxy_config([LinphoneManager getLc]);
LinphoneProxyConfig *proxyCfg = linphone_core_create_proxy_config([LinphoneManager getLc]);
/*default domain is supposed to be preset from linphonerc*/
NSString* identity = [NSString stringWithFormat:@"sip:%@@%s",usernameField.text, linphone_proxy_config_get_addr(proxyCfg)];
linphone_proxy_config_set_identity(proxyCfg,[identity UTF8String]);
LinphoneAuthInfo* auth_info =linphone_auth_info_new([usernameField.text UTF8String]
,[usernameField.text UTF8String]
,[passwordField.text UTF8String]
,NULL
,NULL
,linphone_proxy_config_get_domain(proxyCfg));
NSString *identity =
[NSString stringWithFormat:@"sip:%@@%s", usernameField.text, linphone_proxy_config_get_addr(proxyCfg)];
linphone_proxy_config_set_identity(proxyCfg, [identity UTF8String]);
LinphoneAuthInfo *auth_info = linphone_auth_info_new(
[usernameField.text UTF8String], [usernameField.text UTF8String], [passwordField.text UTF8String], NULL,
NULL, linphone_proxy_config_get_domain(proxyCfg));
linphone_core_add_auth_info([LinphoneManager getLc], auth_info);
linphone_core_add_proxy_config([LinphoneManager getLc], proxyCfg);
linphone_core_set_default_proxy_config([LinphoneManager getLc], proxyCfg);
@ -190,13 +183,12 @@ static UICompositeViewDescription *compositeDescription = nil;
};
}
#pragma mark - UITextFieldDelegate Functions
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
// When the user presses return, take focus away from the text field so that the keyboard is dismissed.
[theTextField resignFirstResponder];
return YES;
// When the user presses return, take focus away from the text field so that the keyboard is dismissed.
[theTextField resignFirstResponder];
return YES;
}
@end

View file

@ -23,7 +23,6 @@
#import "Utils.h"
@implementation HistoryDetailsViewController {
}
@synthesize callLogId;
@ -44,339 +43,337 @@
#pragma mark - LifeCycle Functions
- (id)init {
self = [super initWithNibName:@"HistoryDetailsViewController" bundle:[NSBundle mainBundle]];
if(self != nil) {
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSLocale *locale = [NSLocale currentLocale];
[dateFormatter setLocale:locale];
}
return self;
self = [super initWithNibName:@"HistoryDetailsViewController" bundle:[NSBundle mainBundle]];
if (self != nil) {
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSLocale *locale = [NSLocale currentLocale];
[dateFormatter setLocale:locale];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - UICompositeViewDelegate Functions
static UICompositeViewDescription *compositeDescription = nil;
+ (UICompositeViewDescription *)compositeViewDescription {
if(compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"HistoryDetails"
content:@"HistoryDetailsViewController"
stateBar:nil
stateBarEnabled:false
tabBar:@"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
}
return compositeDescription;
if (compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"HistoryDetails"
content:@"HistoryDetailsViewController"
stateBar:nil
stateBarEnabled:false
tabBar:@"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
}
return compositeDescription;
}
#pragma mark - Property Functions
- (void)setCallLogId:(NSString *)acallLogId {
self->callLogId = [acallLogId copy];
[self update];
self->callLogId = [acallLogId copy];
[self update];
}
#pragma mark - ViewController Functions
- (void)viewDidLoad {
[super viewDidLoad];
[HistoryDetailsViewController adaptSize:dateHeaderLabel field:dateLabel];
[HistoryDetailsViewController adaptSize:durationHeaderLabel field:durationLabel];
[HistoryDetailsViewController adaptSize:typeHeaderLabel field:typeLabel];
[HistoryDetailsViewController adaptSize:plainAddressHeaderLabel field:plainAddressLabel];
[super viewDidLoad];
[HistoryDetailsViewController adaptSize:dateHeaderLabel field:dateLabel];
[HistoryDetailsViewController adaptSize:durationHeaderLabel field:durationLabel];
[HistoryDetailsViewController adaptSize:typeHeaderLabel field:typeLabel];
[HistoryDetailsViewController adaptSize:plainAddressHeaderLabel field:plainAddressLabel];
[addContactButton.titleLabel setAdjustsFontSizeToFitWidth:TRUE]; // Auto shrink: IB lack!
[callButton.titleLabel setAdjustsFontSizeToFitWidth:TRUE]; // Auto shrink: IB lack!
[messageButton.titleLabel setAdjustsFontSizeToFitWidth:TRUE]; // Auto shrink: IB lack!
[callButton.titleLabel setAdjustsFontSizeToFitWidth:TRUE]; // Auto shrink: IB lack!
[messageButton.titleLabel setAdjustsFontSizeToFitWidth:TRUE]; // Auto shrink: IB lack!
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[super viewWillAppear:animated];
BOOL use_system = [[LinphoneManager instance] lpConfigBoolForKey:@"use_system_contacts"];
if( use_system ){
[addContactButton setHidden:TRUE];
}
BOOL use_system = [[LinphoneManager instance] lpConfigBoolForKey:@"use_system_contacts"];
if (use_system) {
[addContactButton setHidden:TRUE];
}
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(update)
name:kLinphoneAddressBookUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(update)
name:kLinphoneAddressBookUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(coreUpdateEvent:)
name:kLinphoneCoreUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(coreUpdateEvent:)
name:kLinphoneCoreUpdate
object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneAddressBookUpdate
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneAddressBookUpdate object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneCoreUpdate
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneCoreUpdate object:nil];
}
#pragma mark - Event Functions
- (void)coreUpdateEvent:(NSNotification*)notif {
[self update];
- (void)coreUpdateEvent:(NSNotification *)notif {
[self update];
}
#pragma mark -
+ (void)adaptSize:(UILabel*)label field:(UIView*)field {
//
// Adapt size
//
CGRect labelFrame = [label frame];
CGRect fieldFrame = [field frame];
+ (void)adaptSize:(UILabel *)label field:(UIView *)field {
//
// Adapt size
//
CGRect labelFrame = [label frame];
CGRect fieldFrame = [field frame];
fieldFrame.origin.x -= labelFrame.size.width;
fieldFrame.origin.x -= labelFrame.size.width;
// Compute firstName size
CGSize contraints;
contraints.height = [label frame].size.height;
contraints.width = ([field frame].size.width + [field frame].origin.x) - [label frame].origin.x;
CGSize firstNameSize = [[label text] sizeWithFont:[label font] constrainedToSize: contraints];
labelFrame.size.width = firstNameSize.width;
// Compute firstName size
CGSize contraints;
contraints.height = [label frame].size.height;
contraints.width = ([field frame].size.width + [field frame].origin.x) - [label frame].origin.x;
CGSize firstNameSize = [[label text] sizeWithFont:[label font] constrainedToSize:contraints];
labelFrame.size.width = firstNameSize.width;
// Compute lastName size & position
fieldFrame.origin.x += labelFrame.size.width;
fieldFrame.size.width = (contraints.width + [label frame].origin.x) - fieldFrame.origin.x;
// Compute lastName size & position
fieldFrame.origin.x += labelFrame.size.width;
fieldFrame.size.width = (contraints.width + [label frame].origin.x) - fieldFrame.origin.x;
[label setFrame: labelFrame];
[field setFrame: fieldFrame];
[label setFrame:labelFrame];
[field setFrame:fieldFrame];
}
- (void)update {
// Look for the call log
callLog = NULL;
const MSList *list = linphone_core_get_call_logs([LinphoneManager getLc]);
while(list != NULL) {
LinphoneCallLog *log = (LinphoneCallLog *)list->data;
const char *cid = linphone_call_log_get_call_id(log);
if(cid != NULL && [callLogId isEqualToString:[NSString stringWithUTF8String:cid]]) {
callLog = log;
break;
}
list = list->next;
}
// Look for the call log
callLog = NULL;
const MSList *list = linphone_core_get_call_logs([LinphoneManager getLc]);
while (list != NULL) {
LinphoneCallLog *log = (LinphoneCallLog *)list->data;
const char *cid = linphone_call_log_get_call_id(log);
if (cid != NULL && [callLogId isEqualToString:[NSString stringWithUTF8String:cid]]) {
callLog = log;
break;
}
list = list->next;
}
// Pop if callLog is null
if(callLog == NULL) {
[[PhoneMainView instance] popCurrentView];
return;
}
// Pop if callLog is null
if (callLog == NULL) {
[[PhoneMainView instance] popCurrentView];
return;
}
LinphoneAddress* addr =linphone_call_log_get_remote_address(callLog);
LinphoneAddress *addr = linphone_call_log_get_remote_address(callLog);
UIImage *image = nil;
NSString* address = nil;
if(addr != NULL) {
BOOL useLinphoneAddress = true;
// contact name
char* lAddress = linphone_address_as_string_uri_only(addr);
if(lAddress) {
NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:[NSString stringWithUTF8String:lAddress]];
contact = [[[LinphoneManager instance] fastAddressBook] getContact:normalizedSipAddress];
if(contact) {
image = [FastAddressBook getContactImage:contact thumbnail:true];
address = [FastAddressBook getContactDisplayName:contact];
useLinphoneAddress = false;
}
ms_free(lAddress);
}
if(useLinphoneAddress) {
const char* lDisplayName = linphone_address_get_display_name(addr);
const char* lUserName = linphone_address_get_username(addr);
if (lDisplayName)
address = [NSString stringWithUTF8String:lDisplayName];
else if(lUserName)
address = [NSString stringWithUTF8String:lUserName];
}
}
UIImage *image = nil;
NSString *address = nil;
if (addr != NULL) {
BOOL useLinphoneAddress = true;
// contact name
char *lAddress = linphone_address_as_string_uri_only(addr);
if (lAddress) {
NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:[NSString stringWithUTF8String:lAddress]];
contact = [[[LinphoneManager instance] fastAddressBook] getContact:normalizedSipAddress];
if (contact) {
image = [FastAddressBook getContactImage:contact thumbnail:true];
address = [FastAddressBook getContactDisplayName:contact];
useLinphoneAddress = false;
}
ms_free(lAddress);
}
if (useLinphoneAddress) {
const char *lDisplayName = linphone_address_get_display_name(addr);
const char *lUserName = linphone_address_get_username(addr);
if (lDisplayName)
address = [NSString stringWithUTF8String:lDisplayName];
else if (lUserName)
address = [NSString stringWithUTF8String:lUserName];
}
}
// Set Image
if(image == nil) {
image = [UIImage imageNamed:@"avatar_unknown.png"];
}
[avatarImage setImage:image];
// Set Image
if (image == nil) {
image = [UIImage imageNamed:@"avatar_unknown.png"];
}
[avatarImage setImage:image];
// Set Address
if(address == nil) {
address = NSLocalizedString(@"Unknown", nil);
}
[addressLabel setText:address];
// Set Address
if (address == nil) {
address = NSLocalizedString(@"Unknown", nil);
}
[addressLabel setText:address];
// Hide/Show add button
BOOL use_system = [[LinphoneManager instance] lpConfigBoolForKey:@"use_system_contacts"];
if(contact) {
[addContactButton setHidden:TRUE];
} else if (!use_system) {
[addContactButton setHidden:FALSE];
}
// Hide/Show add button
BOOL use_system = [[LinphoneManager instance] lpConfigBoolForKey:@"use_system_contacts"];
if (contact) {
[addContactButton setHidden:TRUE];
} else if (!use_system) {
[addContactButton setHidden:FALSE];
}
// State
NSMutableString *state = [NSMutableString string];
// State
NSMutableString *state = [NSMutableString string];
if (linphone_call_log_get_dir(callLog) == LinphoneCallIncoming) {
[state setString:NSLocalizedString(@"Incoming call", nil)];
} else {
[state setString:NSLocalizedString(@"Outgoing call", nil)];
}
switch (linphone_call_log_get_status(callLog)) {
case LinphoneCallSuccess:
break;
case LinphoneCallAborted:
[state appendString:NSLocalizedString(@" (Aborted)", nil)];
break;
case LinphoneCallMissed:
[state appendString:NSLocalizedString(@" (Missed)", nil)];
break;
case LinphoneCallDeclined:
[state appendString:NSLocalizedString(@" (Declined)", nil)];
break;
}
[typeLabel setText:state];
switch (linphone_call_log_get_status(callLog)) {
case LinphoneCallSuccess:
break;
case LinphoneCallAborted:
[state appendString:NSLocalizedString(@" (Aborted)", nil)];
break;
case LinphoneCallMissed:
[state appendString:NSLocalizedString(@" (Missed)", nil)];
break;
case LinphoneCallDeclined:
[state appendString:NSLocalizedString(@" (Declined)", nil)];
break;
}
[typeLabel setText:state];
// Date
NSDate *startData = [NSDate dateWithTimeIntervalSince1970:linphone_call_log_get_start_date(callLog)];
[dateLabel setText:[dateFormatter stringFromDate:startData]];
// Date
NSDate *startData = [NSDate dateWithTimeIntervalSince1970:linphone_call_log_get_start_date(callLog)];
[dateLabel setText:[dateFormatter stringFromDate:startData]];
// Duration
int duration = linphone_call_log_get_duration(callLog);
[durationLabel setText:[NSString stringWithFormat:@"%02i:%02i", (duration/60), duration - 60 * (duration / 60), nil]];
// Duration
int duration = linphone_call_log_get_duration(callLog);
[durationLabel
setText:[NSString stringWithFormat:@"%02i:%02i", (duration / 60), duration - 60 * (duration / 60), nil]];
// contact name
[plainAddressLabel setText:@""];
if (addr != NULL) {
if ([[LinphoneManager instance] lpConfigBoolForKey:@"contact_display_username_only"]) {
[plainAddressLabel setText:[NSString stringWithUTF8String:linphone_address_get_username(addr)?linphone_address_get_username(addr):""]];
// contact name
[plainAddressLabel setText:@""];
if (addr != NULL) {
if ([[LinphoneManager instance] lpConfigBoolForKey:@"contact_display_username_only"]) {
[plainAddressLabel setText:[NSString stringWithUTF8String:linphone_address_get_username(addr)
? linphone_address_get_username(addr)
: ""]];
} else {
char* lAddress = linphone_address_as_string_uri_only(addr);
if(lAddress != NULL) {
char *lAddress = linphone_address_as_string_uri_only(addr);
if (lAddress != NULL) {
[plainAddressLabel setText:[NSString stringWithUTF8String:lAddress]];
ms_free(lAddress);
}
}
}
if (addr != NULL) {
[callButton setHidden:FALSE];
[messageButton setHidden:FALSE];
} else {
[callButton setHidden:TRUE];
[messageButton setHidden:TRUE];
}
}
if (addr != NULL) {
[callButton setHidden:FALSE];
[messageButton setHidden:FALSE];
} else {
[callButton setHidden:TRUE];
[messageButton setHidden:TRUE];
}
}
#pragma mark - Action Functions
- (IBAction)onBackClick:(id)event {
[[PhoneMainView instance] popCurrentView];
[[PhoneMainView instance] popCurrentView];
}
- (IBAction)onContactClick:(id)event {
if(contact) {
ContactDetailsViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ContactDetailsViewController compositeViewDescription] push:TRUE], ContactDetailsViewController);
if(controller != nil) {
[ContactSelection setSelectionMode:ContactSelectionModeNone];
[controller setContact:contact];
}
}
if (contact) {
ContactDetailsViewController *controller = DYNAMIC_CAST(
[[PhoneMainView instance] changeCurrentView:[ContactDetailsViewController compositeViewDescription]
push:TRUE],
ContactDetailsViewController);
if (controller != nil) {
[ContactSelection setSelectionMode:ContactSelectionModeNone];
[controller setContact:contact];
}
}
}
- (IBAction)onAddContactClick:(id)event {
LinphoneAddress* addr;
LinphoneAddress *addr;
addr=linphone_call_log_get_remote_address(callLog);
if (addr != NULL) {
char* lAddress = linphone_address_as_string_uri_only(addr);
if(lAddress != NULL) {
[ContactSelection setAddAddress:[NSString stringWithUTF8String:lAddress]];
[ContactSelection setSelectionMode:ContactSelectionModeEdit];
addr = linphone_call_log_get_remote_address(callLog);
if (addr != NULL) {
char *lAddress = linphone_address_as_string_uri_only(addr);
if (lAddress != NULL) {
[ContactSelection setAddAddress:[NSString stringWithUTF8String:lAddress]];
[ContactSelection setSelectionMode:ContactSelectionModeEdit];
[ContactSelection setSipFilter:nil];
[ContactSelection enableEmailFilter:FALSE];
[ContactSelection setNameOrEmailFilter:nil];
ContactsViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ContactsViewController compositeViewDescription] push:TRUE], ContactsViewController);
if(controller != nil) {
}
ms_free(lAddress);
}
}
[ContactSelection setSipFilter:nil];
[ContactSelection enableEmailFilter:FALSE];
[ContactSelection setNameOrEmailFilter:nil];
ContactsViewController *controller = DYNAMIC_CAST(
[[PhoneMainView instance] changeCurrentView:[ContactsViewController compositeViewDescription]
push:TRUE],
ContactsViewController);
if (controller != nil) {
}
ms_free(lAddress);
}
}
}
- (IBAction)onCallClick:(id)event {
LinphoneAddress* addr;
addr=linphone_call_log_get_remote_address(callLog);
LinphoneAddress *addr;
addr = linphone_call_log_get_remote_address(callLog);
char* lAddress = linphone_address_as_string_uri_only(addr);
if(lAddress == NULL)
return;
char *lAddress = linphone_address_as_string_uri_only(addr);
if (lAddress == NULL)
return;
NSString *displayName = nil;
if(contact != nil) {
displayName = [FastAddressBook getContactDisplayName:contact];
} else {
const char* lDisplayName = linphone_address_get_display_name(addr);
const char* lUserName = linphone_address_get_username(addr);
if (lDisplayName)
displayName = [NSString stringWithUTF8String:lDisplayName];
else if(lUserName)
displayName = [NSString stringWithUTF8String:lUserName];
}
NSString *displayName = nil;
if (contact != nil) {
displayName = [FastAddressBook getContactDisplayName:contact];
} else {
const char *lDisplayName = linphone_address_get_display_name(addr);
const char *lUserName = linphone_address_get_username(addr);
if (lDisplayName)
displayName = [NSString stringWithUTF8String:lDisplayName];
else if (lUserName)
displayName = [NSString stringWithUTF8String:lUserName];
}
DialerViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]], DialerViewController);
if(controller != nil) {
if(displayName != nil) {
[controller call:[NSString stringWithUTF8String:lAddress] displayName:displayName];
} else {
[controller call:[NSString stringWithUTF8String:lAddress]];
}
}
ms_free(lAddress);
DialerViewController *controller =
DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]],
DialerViewController);
if (controller != nil) {
if (displayName != nil) {
[controller call:[NSString stringWithUTF8String:lAddress] displayName:displayName];
} else {
[controller call:[NSString stringWithUTF8String:lAddress]];
}
}
ms_free(lAddress);
}
- (IBAction)onMessageClick:(id)event {
LinphoneAddress* addr;
addr=linphone_call_log_get_remote_address(callLog);
LinphoneAddress *addr;
addr = linphone_call_log_get_remote_address(callLog);
char* lAddress = linphone_address_as_string_uri_only(addr);
if(lAddress == NULL)
return;
// Go to ChatRoom view
[[PhoneMainView instance] changeCurrentView:[ChatViewController compositeViewDescription]];
ChatRoomViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ChatRoomViewController compositeViewDescription] push:TRUE], ChatRoomViewController);
if(controller != nil) {
LinphoneChatRoom* room = linphone_core_get_or_create_chat_room([LinphoneManager getLc], lAddress);
[controller setChatRoom:room];
}
ms_free(lAddress);
char *lAddress = linphone_address_as_string_uri_only(addr);
if (lAddress == NULL)
return;
// Go to ChatRoom view
[[PhoneMainView instance] changeCurrentView:[ChatViewController compositeViewDescription]];
ChatRoomViewController *controller = DYNAMIC_CAST(
[[PhoneMainView instance] changeCurrentView:[ChatRoomViewController compositeViewDescription] push:TRUE],
ChatRoomViewController);
if (controller != nil) {
LinphoneChatRoom *room = linphone_core_get_or_create_chat_room([LinphoneManager getLc], lAddress);
[controller setChatRoom:room];
}
ms_free(lAddress);
}
@end

View file

@ -4,18 +4,18 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "HistoryTableViewController.h"
#import "UIHistoryCell.h"
@ -32,94 +32,84 @@
#pragma mark - Lifecycle Functions
- (void)initHistoryTableViewController {
callLogs = [[NSMutableArray alloc] init];
missedFilter = false;
callLogs = [[NSMutableArray alloc] init];
missedFilter = false;
}
- (id)init {
self = [super init];
if (self) {
self = [super init];
if (self) {
[self initHistoryTableViewController];
}
return self;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
self = [super initWithCoder:decoder];
if (self) {
[self initHistoryTableViewController];
}
return self;
}
return self;
}
#pragma mark - ViewController Functions
#pragma mark - ViewController Functions
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(loadData)
name:kLinphoneAddressBookUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(coreUpdateEvent:)
name:kLinphoneCoreUpdate
object:nil];
[self loadData];
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(loadData)
name:kLinphoneAddressBookUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(coreUpdateEvent:)
name:kLinphoneCoreUpdate
object:nil];
[self loadData];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneAddressBookUpdate
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneCoreUpdate
object:nil];
}
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneAddressBookUpdate object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneCoreUpdate object:nil];
}
#pragma mark - Event Functions
- (void)coreUpdateEvent:(NSNotification*)notif {
// Invalid all pointers
[self loadData];
- (void)coreUpdateEvent:(NSNotification *)notif {
// Invalid all pointers
[self loadData];
}
#pragma mark - Property Functions
- (void)setMissedFilter:(BOOL)amissedFilter {
if(missedFilter == amissedFilter) {
return;
}
missedFilter = amissedFilter;
[self loadData];
if (missedFilter == amissedFilter) {
return;
}
missedFilter = amissedFilter;
[self loadData];
}
#pragma mark - UITableViewDataSource Functions
- (void)loadData {
[callLogs removeAllObjects];
const MSList * logs = linphone_core_get_call_logs([LinphoneManager getLc]);
while(logs != NULL) {
LinphoneCallLog* log = (LinphoneCallLog *) logs->data;
if(missedFilter) {
if (linphone_call_log_get_status(log) == LinphoneCallMissed) {
[callLogs addObject:[NSValue valueWithPointer: log]];
}
} else {
[callLogs addObject:[NSValue valueWithPointer: log]];
}
logs = ms_list_next(logs);
}
[[self tableView] reloadData];
[callLogs removeAllObjects];
const MSList *logs = linphone_core_get_call_logs([LinphoneManager getLc]);
while (logs != NULL) {
LinphoneCallLog *log = (LinphoneCallLog *)logs->data;
if (missedFilter) {
if (linphone_call_log_get_status(log) == LinphoneCallMissed) {
[callLogs addObject:[NSValue valueWithPointer:log]];
}
} else {
[callLogs addObject:[NSValue valueWithPointer:log]];
}
logs = ms_list_next(logs);
}
[[self tableView] reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
@ -131,86 +121,90 @@
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *kCellId = @"UIHistoryCell";
UIHistoryCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId];
if (cell == nil) {
cell = [[UIHistoryCell alloc] initWithIdentifier:kCellId];
// Background View
UACellBackgroundView *selectedBackgroundView = [[UACellBackgroundView alloc] initWithFrame:CGRectZero];
cell.selectedBackgroundView = selectedBackgroundView;
[selectedBackgroundView setBackgroundColor:LINPHONE_TABLE_CELL_BACKGROUND_COLOR];
}
LinphoneCallLog *log = [[callLogs objectAtIndex:[indexPath row]] pointerValue];
[cell setCallLog:log];
return cell;
}
static NSString *kCellId = @"UIHistoryCell";
UIHistoryCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId];
if (cell == nil) {
cell = [[UIHistoryCell alloc] initWithIdentifier:kCellId];
// Background View
UACellBackgroundView *selectedBackgroundView = [[UACellBackgroundView alloc] initWithFrame:CGRectZero];
cell.selectedBackgroundView = selectedBackgroundView;
[selectedBackgroundView setBackgroundColor:LINPHONE_TABLE_CELL_BACKGROUND_COLOR];
}
LinphoneCallLog *log = [[callLogs objectAtIndex:[indexPath row]] pointerValue];
[cell setCallLog:log];
return cell;
}
#pragma mark - UITableViewDelegate Functions
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
LinphoneCallLog *callLog = [[callLogs objectAtIndex:[indexPath row]] pointerValue];
LinphoneAddress* addr;
LinphoneCallLog *callLog = [[callLogs objectAtIndex:[indexPath row]] pointerValue];
LinphoneAddress *addr;
if (linphone_call_log_get_dir(callLog) == LinphoneCallIncoming) {
addr = linphone_call_log_get_from(callLog);
} else {
addr = linphone_call_log_get_to(callLog);
}
NSString* displayName = nil;
NSString* address = nil;
if(addr != NULL) {
BOOL useLinphoneAddress = true;
// contact name
char* lAddress = linphone_address_as_string_uri_only(addr);
if(lAddress) {
address = [NSString stringWithUTF8String:lAddress];
NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:address];
ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:normalizedSipAddress];
if(contact) {
displayName = [FastAddressBook getContactDisplayName:contact];
useLinphoneAddress = false;
}
ms_free(lAddress);
}
if(useLinphoneAddress) {
const char* lDisplayName = linphone_address_get_display_name(addr);
if (lDisplayName)
displayName = [NSString stringWithUTF8String:lDisplayName];
}
}
if(address != nil) {
// Go to dialer view
DialerViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]], DialerViewController);
if(controller != nil) {
[controller call:address displayName:displayName];
}
}
NSString *displayName = nil;
NSString *address = nil;
if (addr != NULL) {
BOOL useLinphoneAddress = true;
// contact name
char *lAddress = linphone_address_as_string_uri_only(addr);
if (lAddress) {
address = [NSString stringWithUTF8String:lAddress];
NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:address];
ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:normalizedSipAddress];
if (contact) {
displayName = [FastAddressBook getContactDisplayName:contact];
useLinphoneAddress = false;
}
ms_free(lAddress);
}
if (useLinphoneAddress) {
const char *lDisplayName = linphone_address_get_display_name(addr);
if (lDisplayName)
displayName = [NSString stringWithUTF8String:lDisplayName];
}
}
if (address != nil) {
// Go to dialer view
DialerViewController *controller =
DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]],
DialerViewController);
if (controller != nil) {
[controller call:address displayName:displayName];
}
}
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
// Detemine if it's in editing mode
if (self.editing) {
return UITableViewCellEditingStyleDelete;
}
return UITableViewCellEditingStyleNone;
- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView
editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
// Detemine if it's in editing mode
if (self.editing) {
return UITableViewCellEditingStyleDelete;
}
return UITableViewCellEditingStyleNone;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if(editingStyle == UITableViewCellEditingStyleDelete) {
[tableView beginUpdates];
LinphoneCallLog *callLog = [[callLogs objectAtIndex:[indexPath row]] pointerValue];
linphone_core_remove_call_log([LinphoneManager getLc], callLog);
[callLogs removeObjectAtIndex:[indexPath row]];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[tableView beginUpdates];
LinphoneCallLog *callLog = [[callLogs objectAtIndex:[indexPath row]] pointerValue];
linphone_core_remove_call_log([LinphoneManager getLc], callLog);
[callLogs removeObjectAtIndex:[indexPath row]];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
}
@end

View file

@ -4,18 +4,18 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "HistoryViewController.h"
@ -29,136 +29,126 @@
@synthesize editButton;
@synthesize deleteButton;
typedef enum _HistoryView {
History_All,
History_Missed,
History_MAX
} HistoryView;
typedef enum _HistoryView { History_All, History_Missed, History_MAX } HistoryView;
#pragma mark - Lifecycle Functions
- (id)init {
return [super initWithNibName:@"HistoryViewController" bundle:[NSBundle mainBundle]];
return [super initWithNibName:@"HistoryViewController" bundle:[NSBundle mainBundle]];
}
#pragma mark - UICompositeViewDelegate Functions
static UICompositeViewDescription *compositeDescription = nil;
+ (UICompositeViewDescription *)compositeViewDescription {
if(compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"History"
content:@"HistoryViewController"
stateBar:nil
stateBarEnabled:false
tabBar:@"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
}
return compositeDescription;
if (compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"History"
content:@"HistoryViewController"
stateBar:nil
stateBarEnabled:false
tabBar:@"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
}
return compositeDescription;
}
#pragma mark - ViewController Functions
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[super viewWillAppear:animated];
if([tableController isEditing]) {
[tableController setEditing:FALSE animated:FALSE];
}
[deleteButton setHidden:TRUE];
[editButton setOff];
[self changeView: History_All];
if ([tableController isEditing]) {
[tableController setEditing:FALSE animated:FALSE];
}
[deleteButton setHidden:TRUE];
[editButton setOff];
[self changeView:History_All];
// Reset missed call
linphone_core_reset_missed_calls_count([LinphoneManager getLc]);
// Fake event
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneCallUpdate object:self];
// Reset missed call
linphone_core_reset_missed_calls_count([LinphoneManager getLc]);
// Fake event
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneCallUpdate object:self];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[super viewDidAppear:animated];
editButton.hidden = ([[tableView dataSource] tableView:tableView numberOfRowsInSection:0] == 0);
}
- (void)viewDidLoad {
[super viewDidLoad];
[self changeView: History_All];
// Set selected+over background: IB lack !
[editButton setBackgroundImage:[UIImage imageNamed:@"history_ok_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:editButton];
// Set selected+over background: IB lack !
[allButton setBackgroundImage:[UIImage imageNamed:@"history_all_selected.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStatesForTabs:allButton];
// Set selected+over background: IB lack !
[missedButton setBackgroundImage:[UIImage imageNamed:@"history_missed_selected.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStatesForTabs:missedButton];
[tableController.tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4
[tableController.tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
}
[super viewDidLoad];
[self changeView:History_All];
// Set selected+over background: IB lack !
[editButton setBackgroundImage:[UIImage imageNamed:@"history_ok_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:editButton];
// Set selected+over background: IB lack !
[allButton setBackgroundImage:[UIImage imageNamed:@"history_all_selected.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStatesForTabs:allButton];
// Set selected+over background: IB lack !
[missedButton setBackgroundImage:[UIImage imageNamed:@"history_missed_selected.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStatesForTabs:missedButton];
[tableController.tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4
[tableController.tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
}
#pragma mark -
- (void)changeView: (HistoryView) view {
if(view == History_All) {
allButton.selected = TRUE;
[tableController setMissedFilter:FALSE];
} else {
allButton.selected = FALSE;
}
if(view == History_Missed) {
missedButton.selected = TRUE;
[tableController setMissedFilter:TRUE];
} else {
missedButton.selected = FALSE;
}
- (void)changeView:(HistoryView)view {
if (view == History_All) {
allButton.selected = TRUE;
[tableController setMissedFilter:FALSE];
} else {
allButton.selected = FALSE;
}
if (view == History_Missed) {
missedButton.selected = TRUE;
[tableController setMissedFilter:TRUE];
} else {
missedButton.selected = FALSE;
}
editButton.hidden = ([[tableView dataSource] tableView:tableView numberOfRowsInSection:0] == 0);
}
#pragma mark - Action Functions
- (IBAction)onAllClick:(id) event {
[self changeView: History_All];
- (IBAction)onAllClick:(id)event {
[self changeView:History_All];
}
- (IBAction)onMissedClick:(id) event {
[self changeView: History_Missed];
- (IBAction)onMissedClick:(id)event {
[self changeView:History_Missed];
}
- (IBAction)onEditClick:(id) event {
[tableController setEditing:![tableController isEditing] animated:TRUE];
- (IBAction)onEditClick:(id)event {
[tableController setEditing:![tableController isEditing] animated:TRUE];
[deleteButton setHidden:![tableController isEditing]];
}
- (IBAction)onDeleteClick:(id) event {
- (IBAction)onDeleteClick:(id)event {
linphone_core_clear_call_logs([LinphoneManager getLc]);
[tableController loadData];
editButton.hidden = ([[tableView dataSource] tableView:tableView numberOfRowsInSection:0] == 0);
if([editButton isSelected]) {
[editButton toggle];
[self onEditClick:nil];
}
if ([editButton isSelected]) {
[editButton toggle];
[self onEditClick:nil];
}
}
@end

View file

@ -21,7 +21,6 @@
#import "PhoneMainView.h"
#import "DTActionSheet.h"
@implementation ImagePickerViewController
@synthesize imagePickerDelegate;
@ -30,142 +29,139 @@
@synthesize allowsEditing;
@synthesize popoverController;
#pragma mark - Lifecycle Functions
- (id)init {
self = [super init];
if (self != nil) {
pickerController = [[UIImagePickerController alloc] init];
if([LinphoneManager runningOnIpad]) {
popoverController = [[UIPopoverController alloc] initWithContentViewController:pickerController];
}
}
return self;
self = [super init];
if (self != nil) {
pickerController = [[UIImagePickerController alloc] init];
if ([LinphoneManager runningOnIpad]) {
popoverController = [[UIPopoverController alloc] initWithContentViewController:pickerController];
}
}
return self;
}
#pragma mark - UICompositeViewDelegate Functions
static UICompositeViewDescription *compositeDescription = nil;
+ (UICompositeViewDescription *)compositeViewDescription {
if(compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"ImagePicker"
content:@"ImagePickerViewController"
stateBar:nil
stateBarEnabled:false
tabBar:nil
tabBarEnabled:false
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
if (compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"ImagePicker"
content:@"ImagePickerViewController"
stateBar:nil
stateBarEnabled:false
tabBar:nil
tabBarEnabled:false
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
compositeDescription.darkBackground = false;
}
return compositeDescription;
}
return compositeDescription;
}
#pragma mark - ViewController Functions
- (void)viewDidLoad {
[super viewDidLoad];
[self.view setAutoresizingMask: UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
if(popoverController == nil) {
[pickerController.view setFrame:[self.view bounds]];
[self.view addSubview:[pickerController view]];
} else {
[popoverController setDelegate:self];
}
[pickerController setDelegate:self];
[super viewDidLoad];
[self.view setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
if (popoverController == nil) {
[pickerController.view setFrame:[self.view bounds]];
[self.view addSubview:[pickerController view]];
} else {
[popoverController setDelegate:self];
}
[pickerController setDelegate:self];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if(popoverController != nil) {
[popoverController presentPopoverFromRect:CGRectZero inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:FALSE];
}
[[UIApplication sharedApplication] setStatusBarHidden:NO]; //Fix UIImagePickerController status bar hide
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; //Fix UIImagePickerController status bar style change
[super viewDidAppear:animated];
if (popoverController != nil) {
[popoverController presentPopoverFromRect:CGRectZero
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:FALSE];
}
[[UIApplication sharedApplication] setStatusBarHidden:NO]; // Fix UIImagePickerController status bar hide
[[UIApplication sharedApplication]
setStatusBarStyle:UIStatusBarStyleDefault]; // Fix UIImagePickerController status bar style change
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if(popoverController != nil) {
[popoverController dismissPopoverAnimated: NO];
}
[super viewWillDisappear:animated];
if (popoverController != nil) {
[popoverController dismissPopoverAnimated:NO];
}
}
#pragma mark - Property Functions
- (BOOL)allowsEditing {
return pickerController.allowsEditing;
return pickerController.allowsEditing;
}
- (void)setAllowsEditing:(BOOL)aallowsEditing {
pickerController.allowsEditing = aallowsEditing;
pickerController.allowsEditing = aallowsEditing;
}
- (UIImagePickerControllerSourceType)sourceType {
return pickerController.sourceType;
return pickerController.sourceType;
}
- (void)setSourceType:(UIImagePickerControllerSourceType)asourceType {
pickerController.sourceType = asourceType;
pickerController.sourceType = asourceType;
}
- (NSArray *)mediaTypes {
return pickerController.mediaTypes;
return pickerController.mediaTypes;
}
- (void)setMediaTypes:(NSArray *)amediaTypes {
pickerController.mediaTypes = amediaTypes;
pickerController.mediaTypes = amediaTypes;
}
#pragma mark -
- (void)dismiss {
if([[[PhoneMainView instance] currentView] equal:[ImagePickerViewController compositeViewDescription]]) {
[[PhoneMainView instance] popCurrentView];
}
if ([[[PhoneMainView instance] currentView] equal:[ImagePickerViewController compositeViewDescription]]) {
[[PhoneMainView instance] popCurrentView];
}
}
#pragma mark - UIImagePickerControllerDelegate Functions
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[self dismiss];
UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
if(image == nil) {
image = [info objectForKey:UIImagePickerControllerOriginalImage];
}
if(image != nil && imagePickerDelegate != nil) {
[imagePickerDelegate imagePickerDelegateImage:image info:info];
}
[self dismiss];
UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
if (image == nil) {
image = [info objectForKey:UIImagePickerControllerOriginalImage];
}
if (image != nil && imagePickerDelegate != nil) {
[imagePickerDelegate imagePickerDelegateImage:image info:info];
}
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[self dismiss];
[self dismiss];
}
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)apopoverController {
[self dismiss];
return TRUE;
[self dismiss];
return TRUE;
}
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated {
if ([navigationController isKindOfClass:[UIImagePickerController class]]) {
[[UIApplication sharedApplication] setStatusBarHidden:NO]; //Fix UIImagePickerController status bar hide
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque]; //Fix UIImagePickerController status bar style change
}
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated {
if ([navigationController isKindOfClass:[UIImagePickerController class]]) {
[[UIApplication sharedApplication] setStatusBarHidden:NO]; // Fix UIImagePickerController status bar hide
[[UIApplication sharedApplication]
setStatusBarStyle:UIStatusBarStyleBlackOpaque]; // Fix UIImagePickerController status bar style change
}
}
@end

View file

@ -4,18 +4,18 @@
*
* 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 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* the Free Software Foundation; either version 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "ImageViewController.h"
#import "PhoneMainView.h"
@ -25,90 +25,83 @@
@synthesize image;
@synthesize imageView;
#pragma mark - Lifecycle Functions
- (void)initUIImageScrollView {
imageView = [[UIImageView alloc] init];
self.delegate = self;
[self addSubview:imageView];
imageView = [[UIImageView alloc] init];
self.delegate = self;
[self addSubview:imageView];
}
- (id)init {
self = [super init];
if(self != nil) {
[self initUIImageScrollView];
}
return self;
self = [super init];
if (self != nil) {
[self initUIImageScrollView];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if(self != nil) {
[self initUIImageScrollView];
}
return self;
self = [super initWithCoder:aDecoder];
if (self != nil) {
[self initUIImageScrollView];
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if(self != nil) {
[self initUIImageScrollView];
}
return self;
self = [super initWithFrame:frame];
if (self != nil) {
[self initUIImageScrollView];
}
return self;
}
#pragma mark - ViewController Functions
- (void)layoutSubviews {
[super layoutSubviews];
// center the image as it becomes smaller than the size of the screen
CGSize boundsSize = self.bounds.size;
CGRect frameToCenter = imageView.frame;
// center horizontally
if (frameToCenter.size.width < boundsSize.width)
frameToCenter.origin.x = (boundsSize.width - frameToCenter.size.width) / 2;
else
frameToCenter.origin.x = 0;
// center vertically
if (frameToCenter.size.height < boundsSize.height)
frameToCenter.origin.y = (boundsSize.height - frameToCenter.size.height) / 2;
else
frameToCenter.origin.y = 0;
imageView.frame = frameToCenter;
}
[super layoutSubviews];
// center the image as it becomes smaller than the size of the screen
CGSize boundsSize = self.bounds.size;
CGRect frameToCenter = imageView.frame;
// center horizontally
if (frameToCenter.size.width < boundsSize.width)
frameToCenter.origin.x = (boundsSize.width - frameToCenter.size.width) / 2;
else
frameToCenter.origin.x = 0;
// center vertically
if (frameToCenter.size.height < boundsSize.height)
frameToCenter.origin.y = (boundsSize.height - frameToCenter.size.height) / 2;
else
frameToCenter.origin.y = 0;
imageView.frame = frameToCenter;
}
#pragma mark - Property Functions
- (void)setImage:(UIImage *)aimage {
self.minimumZoomScale = 0;
self.zoomScale = 1;
CGRect rect = CGRectMake(0, 0, aimage.size.width, aimage.size.height);
imageView.image = aimage;
imageView.frame = rect;
self.contentSize = rect.size;
[self zoomToRect:rect animated:FALSE];
self.minimumZoomScale = self.zoomScale;
self.minimumZoomScale = 0;
self.zoomScale = 1;
CGRect rect = CGRectMake(0, 0, aimage.size.width, aimage.size.height);
imageView.image = aimage;
imageView.frame = rect;
self.contentSize = rect.size;
[self zoomToRect:rect animated:FALSE];
self.minimumZoomScale = self.zoomScale;
}
- (UIImage *)image {
return imageView.image;
return imageView.image;
}
#pragma mark - UIScrollViewDelegate Functions
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return imageView;
return imageView;
}
@end
@ -119,52 +112,47 @@
@synthesize backButton;
@synthesize image;
#pragma mark - Lifecycle Functions
- (id)init {
return [super initWithNibName:@"ImageViewController" bundle:[NSBundle mainBundle]];
return [super initWithNibName:@"ImageViewController" bundle:[NSBundle mainBundle]];
}
#pragma mark - UICompositeViewDelegate Functions
static UICompositeViewDescription *compositeDescription = nil;
+ (UICompositeViewDescription *)compositeViewDescription {
if(compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"ImageView"
content:@"ImageViewController"
stateBar:nil
stateBarEnabled:false
tabBar:nil
tabBarEnabled:false
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
}
return compositeDescription;
if (compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"ImageView"
content:@"ImageViewController"
stateBar:nil
stateBarEnabled:false
tabBar:nil
tabBarEnabled:false
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
}
return compositeDescription;
}
#pragma mark - Property Functions
- (void)setImage:(UIImage *)aimage {
scrollView.image = aimage;
scrollView.image = aimage;
}
- (UIImage *)image {
return scrollView.image;
return scrollView.image;
}
#pragma mark - Action Functions
- (IBAction)onBackClick:(id)sender {
if([[[PhoneMainView instance] currentView] equal:[ImageViewController compositeViewDescription]]) {
[[PhoneMainView instance] popCurrentView];
}
if ([[[PhoneMainView instance] currentView] equal:[ImageViewController compositeViewDescription]]) {
[[PhoneMainView instance] popCurrentView];
}
}
@end

View file

@ -30,11 +30,11 @@
#import "PhoneMainView.h"
@interface InAppProductsManager()
@property (strong, nonatomic) NSDate *expirationDate;
@property (strong, nonatomic) NSDictionary *accountCreationData;
@interface InAppProductsManager ()
@property(strong, nonatomic) NSDate *expirationDate;
@property(strong, nonatomic) NSDictionary *accountCreationData;
// needed because request:didFailWithError method is already used by SKProductsRequestDelegate...
@property (nonatomic, strong) InAppProductsXMLRPCDelegate *xmlrpc;
@property(nonatomic, strong) InAppProductsXMLRPCDelegate *xmlrpc;
@end
@implementation InAppProductsManager
@ -44,7 +44,9 @@
- (instancetype)init {
if ((self = [super init]) != nil) {
_enabled = (([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) && ([SKPaymentQueue canMakePayments]) && ([[LinphoneManager instance] lpConfigBoolForKey:@"enabled" forSection:@"in_app_purchase"]));
_enabled =
(([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) && ([SKPaymentQueue canMakePayments]) &&
([[LinphoneManager instance] lpConfigBoolForKey:@"enabled" forSection:@"in_app_purchase"]));
_initialized = false;
_available = false;
_accountActivationInProgress = false;
@ -61,14 +63,15 @@
#pragma mark Public API
- (BOOL)isPurchasedWithID:(NSString *)productID {
if (!_enabled) return FALSE;
if (!_enabled)
return FALSE;
for (NSString *prod in _productsIDPurchased) {
NSDate *now = [[NSDate alloc] init];
// since multiple ID represent the same product, we must not check it
if (/*[prod isEqual: productID] &&*/[self.expirationDate earlierDate:now] == now) {
if (/*[prod isEqual: productID] &&*/ [self.expirationDate earlierDate:now] == now) {
bool isBought = true;
LOGE(@"%@ is %s bought.", prod, isBought?"":"NOT");
LOGE(@"%@ is %s bought.", prod, isBought ? "" : "NOT");
return isBought;
}
}
@ -76,14 +79,17 @@
}
- (BOOL)purchaseWitID:(NSString *)productID {
if (!_enabled||!_initialized||!_available) {
NSDictionary* dict = @{@"product_id":productID, @"error_msg": NSLocalizedString(@"Cannot purchase anything yet, please try again later.", nil)};
if (!_enabled || !_initialized || !_available) {
NSDictionary *dict = @{
@"product_id" : productID,
@"error_msg" : NSLocalizedString(@"Cannot purchase anything yet, please try again later.", nil)
};
[self postNotificationforStatus:kIAPPurchaseFailed withDict:dict];
return FALSE;
}
SKProduct *prod = [self productIDAvailable:productID];
if (prod) {
NSDictionary* dict = @{@"product_id": productID};
NSDictionary *dict = @{ @"product_id" : productID };
[self postNotificationforStatus:kIAPPurchaseTrying withDict:dict];
SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:prod];
_available = false;
@ -91,16 +97,21 @@
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
return TRUE;
} else {
NSDictionary* dict = @{@"product_id": productID, @"error_msg": @"Product not available"};
NSDictionary *dict = @{ @"product_id" : productID, @"error_msg" : @"Product not available" };
[self postNotificationforStatus:kIAPPurchaseFailed withDict:dict];
return FALSE;
}
}
- (BOOL)purchaseAccount:(NSString *)phoneNumber withPassword:(NSString *)password andEmail:(NSString*)email monthly:(BOOL)monthly {
- (BOOL)purchaseAccount:(NSString *)phoneNumber
withPassword:(NSString *)password
andEmail:(NSString *)email
monthly:(BOOL)monthly {
if (phoneNumber) {
NSString* productID = [[LinphoneManager instance] lpConfigStringForKey:(monthly?@"paid_account_id_monthly":@"paid_account_id") forSection:@"in_app_purchase"];
self.accountCreationData = @{ @"phoneNumber":phoneNumber, @"password":password, @"email":email };
NSString *productID =
[[LinphoneManager instance] lpConfigStringForKey:(monthly ? @"paid_account_id_monthly" : @"paid_account_id")
forSection:@"in_app_purchase"];
self.accountCreationData = @{ @"phoneNumber" : phoneNumber, @"password" : password, @"email" : email };
if (![self purchaseWitID:productID]) {
self.accountCreationData = nil;
@ -114,20 +125,17 @@
if (phoneNumber) {
NSString *receiptBase64 = [self getReceipt];
if (receiptBase64) {
NSURL *URL = [NSURL URLWithString:[[LinphoneManager instance] lpConfigStringForKey:@"receipt_validation_url" forSection:@"in_app_purchase"]];
XMLRPCRequest *request = [[XMLRPCRequest alloc] initWithURL: URL];
//buying for the first time: need to create the account
//if ([transaction.transactionIdentifier isEqualToString:transaction.originalTransaction.transactionIdentifier]) {
[request setMethod: @"activate_account" withParameters:[NSArray arrayWithObjects:
@"",
phoneNumber,
receiptBase64,
@"",
@"apple",
nil]];
NSURL *URL = [NSURL URLWithString:[[LinphoneManager instance] lpConfigStringForKey:@"receipt_validation_url"
forSection:@"in_app_purchase"]];
XMLRPCRequest *request = [[XMLRPCRequest alloc] initWithURL:URL];
// buying for the first time: need to create the account
// if ([transaction.transactionIdentifier
// isEqualToString:transaction.originalTransaction.transactionIdentifier]) {
[request setMethod:@"activate_account"
withParameters:[NSArray arrayWithObjects:@"", phoneNumber, receiptBase64, @"", @"apple", nil]];
_accountActivationInProgress = YES;
XMLRPCConnectionManager *manager = [XMLRPCConnectionManager sharedManager];
[manager spawnConnectionWithXMLRPCRequest: request delegate: self.xmlrpc];
[manager spawnConnectionWithXMLRPCRequest:request delegate:self.xmlrpc];
LOGI(@"XMLRPC query %@", [request method]);
return true;
} else {
@ -137,14 +145,14 @@
return false;
}
-(BOOL)restore {
if (!_enabled||!_initialized||!_available) {
NSDictionary* dict = @{@"error_msg": NSLocalizedString(@"In apps not ready yet", nil)};
- (BOOL)restore {
if (!_enabled || !_initialized || !_available) {
NSDictionary *dict = @{ @"error_msg" : NSLocalizedString(@"In apps not ready yet", nil) };
[self postNotificationforStatus:kIAPRestoreFailed withDict:dict];
return FALSE;
}
LOGI(@"Restoring user purchases...");
//force new query of our server
// force new query of our server
latestReceiptMD5 = nil;
_available = false;
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
@ -152,8 +160,8 @@
}
- (BOOL)retrievePurchases {
if (!_enabled|!_initialized|!_available) {
NSDictionary* dict = @{@"error_msg": NSLocalizedString(@"In apps not ready yet", nil)};
if (!_enabled | !_initialized | !_available) {
NSDictionary *dict = @{ @"error_msg" : NSLocalizedString(@"In apps not ready yet", nil) };
[self postNotificationforStatus:kIAPRestoreFailed withDict:dict];
return FALSE;
} else if ([[self getPhoneNumber] length] == 0) {
@ -169,18 +177,20 @@
#pragma mark ProductListLoading
- (void)loadProducts {
NSArray * list = [[[[LinphoneManager instance] lpConfigStringForKey:@"products_list" forSection:@"in_app_purchase"] stringByReplacingOccurrencesOfString:@" " withString:@""] componentsSeparatedByString:@","];
NSArray *list = [[[[LinphoneManager instance] lpConfigStringForKey:@"products_list" forSection:@"in_app_purchase"]
stringByReplacingOccurrencesOfString:@" "
withString:@""] componentsSeparatedByString:@","];
_productsIDPurchased = [[NSMutableArray alloc] initWithCapacity:0];
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithArray:list]];
SKProductsRequest *productsRequest =
[[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithArray:list]];
productsRequest.delegate = self;
[productsRequest start];
}
- (void)productsRequest:(SKProductsRequest *)request
didReceiveResponse:(SKProductsResponse *)response {
_productsAvailable = [NSMutableArray arrayWithArray: response.products];
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
_productsAvailable = [NSMutableArray arrayWithArray:response.products];
LOGI(@"Found %lu products available", (unsigned long)_productsAvailable.count);
_initialized = true;
@ -196,14 +206,15 @@
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
LOGE(@"Impossible to retrieve list of products: %@", [error localizedDescription]);
//well, let's retry...
// well, let's retry...
[self loadProducts];
}
#pragma mark Other
- (SKProduct*) productIDAvailable:(NSString*)productID {
if (!_enabled||!_initialized) return nil;
- (SKProduct *)productIDAvailable:(NSString *)productID {
if (!_enabled || !_initialized)
return nil;
for (SKProduct *product in _productsAvailable) {
if ([product.productIdentifier compare:productID options:NSLiteralSearch] == NSOrderedSame) {
return product;
@ -213,23 +224,24 @@
}
- (void)requestDidFinish:(SKRequest *)request {
if([request isKindOfClass:[SKReceiptRefreshRequest class]]) {
if ([request isKindOfClass:[SKReceiptRefreshRequest class]]) {
NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
if ([[NSFileManager defaultManager] fileExistsAtPath:[receiptUrl path]]) {
LOGI(@"App Receipt exists");
[self validateReceipt:nil];
} else {
// This can happen if the user cancels the login screen for the store.
// If we get here it means there is no receipt and an attempt to get it failed because the user cancelled the login.
// If we get here it means there is no receipt and an attempt to get it failed because the user cancelled
// the login.
LOGF(@"Receipt request done but there is no receipt");
}
}
}
- (NSString*) getReceipt {
- (NSString *)getReceipt {
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
// Test whether the receipt is present at the above URL
if(![[NSFileManager defaultManager] fileExistsAtPath:[receiptURL path]]) {
if (![[NSFileManager defaultManager] fileExistsAtPath:[receiptURL path]]) {
// We are probably in sandbox environment, trying to retrieve it...
return nil;
}
@ -239,42 +251,37 @@
return receiptBase64;
}
- (void)validateReceipt: (SKPaymentTransaction*)transaction {
- (void)validateReceipt:(SKPaymentTransaction *)transaction {
NSString *receiptBase64 = [self getReceipt];
if (receiptBase64 == nil) {
SKRequest* req = [[SKReceiptRefreshRequest alloc] init];
SKRequest *req = [[SKReceiptRefreshRequest alloc] init];
LOGI(@"Receipt not found yet, trying to retrieve it...");
req.delegate = self;
[req start];
return;
}
//only check the receipt if it has changed
// only check the receipt if it has changed
if (latestReceiptMD5 == nil || ![latestReceiptMD5 isEqualToString:[receiptBase64 md5]]) {
// transaction is null when restoring user purchases at application start or if user clicks the "restore" button
// We must validate the receipt on our server
NSURL *URL = [NSURL URLWithString:[[LinphoneManager instance] lpConfigStringForKey:@"receipt_validation_url" forSection:@"in_app_purchase"]];
XMLRPCRequest *request = [[XMLRPCRequest alloc] initWithURL: URL];
//buying for the first time: need to create the account
//if ([transaction.transactionIdentifier isEqualToString:transaction.originalTransaction.transactionIdentifier]) {
NSURL *URL = [NSURL URLWithString:[[LinphoneManager instance] lpConfigStringForKey:@"receipt_validation_url"
forSection:@"in_app_purchase"]];
XMLRPCRequest *request = [[XMLRPCRequest alloc] initWithURL:URL];
// buying for the first time: need to create the account
// if ([transaction.transactionIdentifier
// isEqualToString:transaction.originalTransaction.transactionIdentifier]) {
if (self.accountCreationData.count == 3) {
[request setMethod: @"create_account_from_in_app_purchase" withParameters:[NSArray arrayWithObjects:
@"",
[_accountCreationData objectForKey:@"phoneNumber"],
receiptBase64,
@"",
@"apple",
[_accountCreationData objectForKey:@"email"],
nil]];
[request setMethod:@"create_account_from_in_app_purchase"
withParameters:[NSArray arrayWithObjects:@"", [_accountCreationData objectForKey:@"phoneNumber"],
receiptBase64, @"", @"apple",
[_accountCreationData objectForKey:@"email"], nil]];
self.accountCreationData = nil;
// otherwise simply renewing
} else {
if ([[self getPhoneNumber] length] > 0) {
[request setMethod: @"get_expiration_date" withParameters:[NSArray arrayWithObjects:
[self getPhoneNumber],
receiptBase64,
@"",
@"apple",
nil]];
[request setMethod:@"get_expiration_date"
withParameters:[NSArray
arrayWithObjects:[self getPhoneNumber], receiptBase64, @"", @"apple", nil]];
} else {
LOGW(@"No SIP URI configured, doing nothing");
_available = true;
@ -284,7 +291,7 @@
latestReceiptMD5 = [receiptBase64 md5];
XMLRPCConnectionManager *manager = [XMLRPCConnectionManager sharedManager];
[manager spawnConnectionWithXMLRPCRequest: request delegate: self.xmlrpc];
[manager spawnConnectionWithXMLRPCRequest:request delegate:self.xmlrpc];
LOGI(@"XMLRPC query %@", [request method]);
} else {
LOGW(@"Not checking receipt since it has already been done!");
@ -292,8 +299,8 @@
}
}
- (NSString*)getPhoneNumber {
NSString * phoneNumber = @"";
- (NSString *)getPhoneNumber {
NSString *phoneNumber = @"";
LinphoneProxyConfig *config = linphone_core_get_default_proxy_config([LinphoneManager getLc]);
if (config) {
const char *identity = linphone_proxy_config_get_identity(config);
@ -309,52 +316,53 @@
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for(SKPaymentTransaction * transaction in transactions) {
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchasing:
break;
case SKPaymentTransactionStatePurchased:
case SKPaymentTransactionStateRestored: {
if (!_initialized) {
LOGW(@"Pending transactions before end of initialization, not verifying receipt");
} else {
[self validateReceipt: transaction];
}
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStatePurchasing:
break;
case SKPaymentTransactionStatePurchased:
case SKPaymentTransactionStateRestored: {
if (!_initialized) {
LOGW(@"Pending transactions before end of initialization, not verifying receipt");
} else {
[self validateReceipt:transaction];
}
case SKPaymentTransactionStateDeferred:
LOGI(@"Waiting for parent approval...");
//could do some UI stuff
break;
case SKPaymentTransactionStateFailed: {
_available = true;
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
if (transaction.error.code == SKErrorPaymentCancelled) {
LOGI(@"SKPaymentTransactionStateFailed: cancelled");
NSDictionary* dict = @{@"product_id": transaction.payment.productIdentifier};
[self postNotificationforStatus:kIAPPurchaseCancelled withDict:dict];
} else {
NSString* errlast = [NSString stringWithFormat:@"Purchase failed: %@.",transaction.error.localizedDescription];
LOGE(@"SKPaymentTransactionStateFailed: %@", errlast);
NSDictionary* dict = @{@"product_id": transaction.payment.productIdentifier, @"error_msg": errlast};
[self postNotificationforStatus:kIAPPurchaseFailed withDict:dict];
}
break;
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
}
case SKPaymentTransactionStateDeferred:
LOGI(@"Waiting for parent approval...");
// could do some UI stuff
break;
case SKPaymentTransactionStateFailed: {
_available = true;
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
if (transaction.error.code == SKErrorPaymentCancelled) {
LOGI(@"SKPaymentTransactionStateFailed: cancelled");
NSDictionary *dict = @{ @"product_id" : transaction.payment.productIdentifier };
[self postNotificationforStatus:kIAPPurchaseCancelled withDict:dict];
} else {
NSString *errlast =
[NSString stringWithFormat:@"Purchase failed: %@.", transaction.error.localizedDescription];
LOGE(@"SKPaymentTransactionStateFailed: %@", errlast);
NSDictionary *dict = @{ @"product_id" : transaction.payment.productIdentifier, @"error_msg" : errlast };
[self postNotificationforStatus:kIAPPurchaseFailed withDict:dict];
}
break;
}
}
}
}
- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions {
for(SKPaymentTransaction * transaction in transactions) {
for (SKPaymentTransaction *transaction in transactions) {
LOGD(@"%@ was removed from the payment queue.", transaction.payment.productIdentifier);
}
}
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error {
if (error.code != SKErrorPaymentCancelled) {
NSDictionary* dict = @{@"error_msg": [error localizedDescription]};
NSDictionary *dict = @{ @"error_msg" : [error localizedDescription] };
[self postNotificationforStatus:kIAPRestoreFailed withDict:dict];
}
}
@ -363,14 +371,15 @@
LOGI(@"All restorable transactions have been processed by the payment queue.");
}
-(void)postNotificationforStatus:(IAPPurchaseNotificationStatus)status withDict:(NSDictionary*)dict {
- (void)postNotificationforStatus:(IAPPurchaseNotificationStatus)status withDict:(NSDictionary *)dict {
_status = status;
LOGI(@"Triggering notification for status %@", status);
[[NSNotificationCenter defaultCenter] postNotificationName:status object:self userInfo:dict];
}
- (void)XMLRPCRequest:(XMLRPCRequest *)request didReceiveResponse:(XMLRPCResponse *)response {
if (!_enabled) return;
if (!_enabled)
return;
_available = true;
@ -379,19 +388,20 @@
}
LOGI(@"XMLRPC response %@: %@", [request method], [response body]);
NSString* productID = [[LinphoneManager instance] lpConfigStringForKey:@"paid_account_id" forSection:@"in_app_purchase"];
NSString *productID =
[[LinphoneManager instance] lpConfigStringForKey:@"paid_account_id" forSection:@"in_app_purchase"];
// validation succeeded
if(! [response isFault] && [response object] != nil) {
if(([[request method] isEqualToString:@"get_expiration_date"])
|| ([[request method] isEqualToString:@"create_account_from_in_app_purchase"])) {
if (![response isFault] && [response object] != nil) {
if (([[request method] isEqualToString:@"get_expiration_date"]) ||
([[request method] isEqualToString:@"create_account_from_in_app_purchase"])) {
[_productsIDPurchased removeObject:productID];
// response object can either be expiration date (long long number or an error string)
double timeinterval = [[response object] doubleValue];
if (timeinterval != 0.0f) {
self.expirationDate = [NSDate dateWithTimeIntervalSince1970:timeinterval/1000];
self.expirationDate = [NSDate dateWithTimeIntervalSince1970:timeinterval / 1000];
NSDate *now = [[NSDate alloc] init];
NSDictionary* dict = @{@"product_id": productID, @"expires_date": self.expirationDate};
NSDictionary *dict = @{ @"product_id" : productID, @"expires_date" : self.expirationDate };
if ([self.expirationDate earlierDate:now] == self.expirationDate) {
LOGW(@"Account has expired");
[self postNotificationforStatus:kIAPPurchaseExpired withDict:dict];
@ -406,43 +416,46 @@
LOGE(@"Failed with error %@", error);
NSString *errorMsg;
if ([error isEqualToString:@"ERROR_ACCOUNT_ALREADY_EXISTS"]) {
errorMsg=NSLocalizedString(@"This account is already registered.", nil);
errorMsg = NSLocalizedString(@"This account is already registered.", nil);
} else if ([error isEqualToString:@"ERROR_UID_ALREADY_IN_USE"]) {
errorMsg=NSLocalizedString(@"You already own an account.", nil);
errorMsg = NSLocalizedString(@"You already own an account.", nil);
} else if ([error isEqualToString:@"ERROR_ACCOUNT_DOESNT_EXIST"]) {
errorMsg=NSLocalizedString(@"You have already purchased an account but it does not exist anymore.", nil);
errorMsg =
NSLocalizedString(@"You have already purchased an account but it does not exist anymore.", nil);
} else if ([error isEqualToString:@"ERROR_PURCHASE_CANCELLED"]) {
errorMsg=NSLocalizedString(@"You cancelled your account.", nil);
errorMsg = NSLocalizedString(@"You cancelled your account.", nil);
} else {
errorMsg=[NSString stringWithFormat:NSLocalizedString(@"Unknown error (%@).", nil), error];
errorMsg = [NSString stringWithFormat:NSLocalizedString(@"Unknown error (%@).", nil), error];
}
NSDictionary* dict = @{@"product_id": productID, @"error_msg": errorMsg};
NSDictionary *dict = @{ @"product_id" : productID, @"error_msg" : errorMsg };
[self postNotificationforStatus:kIAPPurchaseFailed withDict:dict];
}
}
} else {
NSString *errorString = NSLocalizedString(@"Unknown error", nil);
if ([response isFault]) {
errorString = [NSString stringWithFormat:NSLocalizedString(@"Communication issue (%@)", nil), [response faultString]];
} else if([response object] == nil) {
errorString =
[NSString stringWithFormat:NSLocalizedString(@"Communication issue (%@)", nil), [response faultString]];
} else if ([response object] == nil) {
errorString = NSLocalizedString(@"Invalid server response", nil);
}
LOGE(@"Communication issue (%@)", [response faultString]);
UIAlertView* errorView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Communication issue",nil)
UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Communication issue", nil)
message:errorString
delegate:nil
cancelButtonTitle:NSLocalizedString(@"Continue",nil)
otherButtonTitles:nil,nil];
cancelButtonTitle:NSLocalizedString(@"Continue", nil)
otherButtonTitles:nil, nil];
[errorView show];
latestReceiptMD5 = nil;
NSDictionary* dict = @{@"error_msg": errorString};
NSDictionary *dict = @{ @"error_msg" : errorString };
[self postNotificationforStatus:kIAPPurchaseFailed withDict:dict];
}
}
- (void)XMLRPCRequest:(XMLRPCRequest *)request didFailWithError:(NSError *)error {
if (!_enabled) return;
if (!_enabled)
return;
_available = true;
@ -451,34 +464,58 @@
}
LOGE(@"Communication issue (%@)", [error localizedDescription]);
NSString *errorString = [NSString stringWithFormat:NSLocalizedString(@"Communication issue (%@)", nil), [error localizedDescription]];
UIAlertView* errorView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Communication issue", nil)
NSString *errorString =
[NSString stringWithFormat:NSLocalizedString(@"Communication issue (%@)", nil), [error localizedDescription]];
UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Communication issue", nil)
message:errorString
delegate:nil
cancelButtonTitle:NSLocalizedString(@"Continue", nil)
otherButtonTitles:nil,nil];
otherButtonTitles:nil, nil];
[errorView show];
latestReceiptMD5 = nil;
NSDictionary* dict = @{@"error_msg": errorString};
NSDictionary *dict = @{ @"error_msg" : errorString };
[self postNotificationforStatus:kIAPReceiptFailed withDict:dict];
}
#else
-(void)postNotificationforStatus:(IAPPurchaseNotificationStatus)status {
- (void)postNotificationforStatus:(IAPPurchaseNotificationStatus)status {
_status = status;
[[NSNotificationCenter defaultCenter] postNotificationName:status object:self userInfo:nil];
LOGE(@"Not supported, triggering %@", status);
}
- (BOOL)purchaseAccount:(NSString *)phoneNumber withPassword:(NSString *)password andEmail:(NSString *)email monthly:(BOOL)monthly { [self postNotificationforStatus:kIAPPurchaseFailed]; return false; }
- (BOOL)restore { [self postNotificationforStatus:kIAPRestoreFailed]; return false; }
- (BOOL)retrievePurchases { [self postNotificationforStatus:kIAPRestoreFailed]; return false; }
- (BOOL)purchaseWitID:(NSString *)productID { [self postNotificationforStatus:kIAPPurchaseFailed]; return FALSE; }
- (BOOL)isPurchasedWithID:(NSString *)productId { return FALSE; }
- (BOOL)purchaseAccount:(NSString *)phoneNumber
withPassword:(NSString *)password
andEmail:(NSString *)email
monthly:(BOOL)monthly {
[self postNotificationforStatus:kIAPPurchaseFailed];
return false;
}
- (BOOL)restore {
[self postNotificationforStatus:kIAPRestoreFailed];
return false;
}
- (BOOL)retrievePurchases {
[self postNotificationforStatus:kIAPRestoreFailed];
return false;
}
- (BOOL)purchaseWitID:(NSString *)productID {
[self postNotificationforStatus:kIAPPurchaseFailed];
return FALSE;
}
- (BOOL)isPurchasedWithID:(NSString *)productId {
return FALSE;
}
- (void)XMLRPCRequest:(XMLRPCRequest *)request didFailWithError:(NSError *)error { }
- (void)XMLRPCRequest:(XMLRPCRequest *)request didReceiveResponse:(XMLRPCResponse *)response { }
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { }
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { }
- (BOOL)activateAccount:(NSString *)phoneNumber { return FALSE; }
- (void)XMLRPCRequest:(XMLRPCRequest *)request didFailWithError:(NSError *)error {
}
- (void)XMLRPCRequest:(XMLRPCRequest *)request didReceiveResponse:(XMLRPCResponse *)response {
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
}
- (BOOL)activateAccount:(NSString *)phoneNumber {
return FALSE;
}
#endif
@end
@ -501,10 +538,8 @@
}
- (void)request:(XMLRPCRequest *)request didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
}
- (void)request:(XMLRPCRequest *)request didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
}
@end

View file

@ -22,306 +22,294 @@
#import "UIConferenceHeader.h"
#import "LinphoneManager.h"
@implementation InCallTableViewController
static NSString *const kLinphoneInCallCellData = @"LinphoneInCallCellData";
enum TableSection {
ConferenceSection = 0,
CallSection = 1
};
enum TableSection { ConferenceSection = 0, CallSection = 1 };
#pragma mark - Lifecycle Functions
- (void)initInCallTableViewController {
minimized = false;
minimized = false;
}
- (id)init{
self = [super init];
if (self) {
- (id)init {
self = [super init];
if (self) {
[self initInCallTableViewController];
}
return self;
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
[self initInCallTableViewController];
}
return self;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
self = [super initWithCoder:decoder];
if (self) {
[self initInCallTableViewController];
}
return self;
return self;
}
#pragma mark - ViewController Functions
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
updateTime = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:@selector(update)
userInfo:nil
repeats:YES];
[super viewWillAppear:animated];
updateTime =
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(update) userInfo:nil repeats:YES];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if (updateTime != nil) {
[updateTime invalidate];
updateTime = nil;
}
[super viewWillDisappear:animated];
if (updateTime != nil) {
[updateTime invalidate];
updateTime = nil;
}
}
#pragma mark - Static Functions
+ (bool)isInConference:(LinphoneCall*) call {
if (!call)
return false;
return linphone_call_is_in_conference(call);
+ (bool)isInConference:(LinphoneCall *)call {
if (!call)
return false;
return linphone_call_is_in_conference(call);
}
+ (int)callCount:(LinphoneCore*) lc {
int count = 0;
const MSList* calls = linphone_core_get_calls(lc);
+ (int)callCount:(LinphoneCore *)lc {
int count = 0;
const MSList *calls = linphone_core_get_calls(lc);
while (calls != 0) {
if (![InCallTableViewController isInConference:((LinphoneCall*)calls->data)]) {
count++;
}
calls = calls->next;
}
return count;
while (calls != 0) {
if (![InCallTableViewController isInConference:((LinphoneCall *)calls->data)]) {
count++;
}
calls = calls->next;
}
return count;
}
+ (LinphoneCall*)retrieveCallAtIndex: (NSInteger) index inConference:(bool) conf{
const MSList* calls = linphone_core_get_calls([LinphoneManager getLc]);
+ (LinphoneCall *)retrieveCallAtIndex:(NSInteger)index inConference:(bool)conf {
const MSList *calls = linphone_core_get_calls([LinphoneManager getLc]);
while (calls != 0) {
if ([InCallTableViewController isInConference:(LinphoneCall*)calls->data] == conf) {
if (index == 0)
break;
index--;
}
calls = calls->next;
}
while (calls != 0) {
if ([InCallTableViewController isInConference:(LinphoneCall *)calls->data] == conf) {
if (index == 0)
break;
index--;
}
calls = calls->next;
}
if (calls == 0) {
LOGE(@"Cannot find call with index %d (in conf: %d)", index, conf);
return nil;
} else {
return (LinphoneCall*)calls->data;
}
if (calls == 0) {
LOGE(@"Cannot find call with index %d (in conf: %d)", index, conf);
return nil;
} else {
return (LinphoneCall *)calls->data;
}
}
#pragma mark -
- (void)removeCallData:(LinphoneCall*) call {
// Remove data associated with the call
if(call != NULL) {
LinphoneCallAppData* appData = (__bridge LinphoneCallAppData*) linphone_call_get_user_pointer(call);
if(appData != NULL) {
[appData->userInfos removeObjectForKey:kLinphoneInCallCellData];
}
}
- (void)removeCallData:(LinphoneCall *)call {
// Remove data associated with the call
if (call != NULL) {
LinphoneCallAppData *appData = (__bridge LinphoneCallAppData *)linphone_call_get_user_pointer(call);
if (appData != NULL) {
[appData->userInfos removeObjectForKey:kLinphoneInCallCellData];
}
}
}
- (UICallCellData*)addCallData:(LinphoneCall*) call {
// Handle data associated with the call
UICallCellData * data = nil;
if(call != NULL) {
LinphoneCallAppData* appData = (__bridge LinphoneCallAppData*) linphone_call_get_user_pointer(call);
if(appData != NULL) {
data = [appData->userInfos objectForKey:kLinphoneInCallCellData];
if(data == nil) {
data = [[UICallCellData alloc] init:call minimized:minimized];
[appData->userInfos setObject:data forKey:kLinphoneInCallCellData];
}
}
}
return data;
- (UICallCellData *)addCallData:(LinphoneCall *)call {
// Handle data associated with the call
UICallCellData *data = nil;
if (call != NULL) {
LinphoneCallAppData *appData = (__bridge LinphoneCallAppData *)linphone_call_get_user_pointer(call);
if (appData != NULL) {
data = [appData->userInfos objectForKey:kLinphoneInCallCellData];
if (data == nil) {
data = [[UICallCellData alloc] init:call minimized:minimized];
[appData->userInfos setObject:data forKey:kLinphoneInCallCellData];
}
}
}
return data;
}
- (UICallCellData*)getCallData:(LinphoneCall*) call {
// Handle data associated with the call
UICallCellData * data = nil;
if(call != NULL) {
LinphoneCallAppData* appData = (__bridge LinphoneCallAppData*) linphone_call_get_user_pointer(call);
if(appData != NULL) {
data = [appData->userInfos objectForKey:kLinphoneInCallCellData];
}
}
return data;
- (UICallCellData *)getCallData:(LinphoneCall *)call {
// Handle data associated with the call
UICallCellData *data = nil;
if (call != NULL) {
LinphoneCallAppData *appData = (__bridge LinphoneCallAppData *)linphone_call_get_user_pointer(call);
if (appData != NULL) {
data = [appData->userInfos objectForKey:kLinphoneInCallCellData];
}
}
return data;
}
- (void)update {
UITableView *tableView = [self tableView];
for (int section = 0; section < [tableView numberOfSections]; section++) {
for (int row = 0; row < [tableView numberOfRowsInSection:section]; row++) {
NSIndexPath* cellPath = [NSIndexPath indexPathForRow:row inSection:section];
UICallCell* cell = (UICallCell*) [tableView cellForRowAtIndexPath:cellPath];
[cell update];
}
}
UITableView *tableView = [self tableView];
for (int section = 0; section < [tableView numberOfSections]; section++) {
for (int row = 0; row < [tableView numberOfRowsInSection:section]; row++) {
NSIndexPath *cellPath = [NSIndexPath indexPathForRow:row inSection:section];
UICallCell *cell = (UICallCell *)[tableView cellForRowAtIndexPath:cellPath];
[cell update];
}
}
}
- (void)minimizeAll {
const MSList *list = linphone_core_get_calls([LinphoneManager getLc]);
minimized = true;
while(list != NULL) {
UICallCellData *data = [self getCallData:(LinphoneCall*)list->data];
if(data) {
data->minimize = true;
} else {
}
list = list->next;
}
[[self tableView] reloadData];
const MSList *list = linphone_core_get_calls([LinphoneManager getLc]);
minimized = true;
while (list != NULL) {
UICallCellData *data = [self getCallData:(LinphoneCall *)list->data];
if (data) {
data->minimize = true;
} else {
}
list = list->next;
}
[[self tableView] reloadData];
}
- (void)maximizeAll {
const MSList *list = linphone_core_get_calls([LinphoneManager getLc]);
minimized = false;
while(list != NULL) {
UICallCellData *data = [self getCallData:(LinphoneCall*)list->data];
if(data) {
data->minimize = false;
}
list = list->next;
}
[[self tableView] reloadData];
const MSList *list = linphone_core_get_calls([LinphoneManager getLc]);
minimized = false;
while (list != NULL) {
UICallCellData *data = [self getCallData:(LinphoneCall *)list->data];
if (data) {
data->minimize = false;
}
list = list->next;
}
[[self tableView] reloadData];
}
#pragma mark - UITableViewDataSource Functions
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *kCellId = @"UICallCell";
UICallCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId];
if (cell == nil) {
cell = [[UICallCell alloc] initWithIdentifier:kCellId];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *kCellId = @"UICallCell";
UICallCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId];
if (cell == nil) {
cell = [[UICallCell alloc] initWithIdentifier:kCellId];
}
bool inConference = indexPath.section == ConferenceSection;
bool inConference = indexPath.section == ConferenceSection;
LinphoneCore* lc = [LinphoneManager getLc];
LinphoneCall* currentCall = linphone_core_get_current_call(lc);
LinphoneCall* call = [InCallTableViewController retrieveCallAtIndex:indexPath.row inConference:inConference];
[cell setData:[self addCallData:call]];
LinphoneCore *lc = [LinphoneManager getLc];
LinphoneCall *currentCall = linphone_core_get_current_call(lc);
LinphoneCall *call = [InCallTableViewController retrieveCallAtIndex:indexPath.row inConference:inConference];
[cell setData:[self addCallData:call]];
// Update cell
if ([indexPath section] == CallSection && [indexPath row] == 0 && linphone_core_get_conference_size(lc) == 0) {
[cell setFirstCell:true];
} else {
[cell setFirstCell:false];
}
[cell setCurrentCall:(currentCall == call)];
[cell setConferenceCell:inConference];
[cell update];
// Update cell
if ([indexPath section] == CallSection && [indexPath row] == 0 && linphone_core_get_conference_size(lc) == 0) {
[cell setFirstCell:true];
} else {
[cell setFirstCell:false];
}
[cell setCurrentCall:(currentCall == call)];
[cell setConferenceCell:inConference];
[cell update];
/*if (linphone_core_get_calls_nb(lc) > 1 || linphone_core_get_conference_size(lc) > 0) {
tableView.scrollEnabled = true;
} else {
tableView.scrollEnabled = false;
}*/
return cell;
/*if (linphone_core_get_calls_nb(lc) > 1 || linphone_core_get_conference_size(lc) > 0) {
tableView.scrollEnabled = true;
} else {
tableView.scrollEnabled = false;
}*/
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
int count = 0;
int count = 0;
LinphoneCore* lc = [LinphoneManager getLc];
LinphoneCore *lc = [LinphoneManager getLc];
if(section == CallSection) {
count = [InCallTableViewController callCount:lc];
} else {
count = linphone_core_get_conference_size(lc);
if(linphone_core_is_in_conference(lc)) {
count--;
}
}
return count;
if (section == CallSection) {
count = [InCallTableViewController callCount:lc];
} else {
count = linphone_core_get_conference_size(lc);
if (linphone_core_is_in_conference(lc)) {
count--;
}
}
return count;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
return 2;
}
- (NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return @"";
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return @"";
}
- (NSString*)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
return @"";
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
return @"";
}
#pragma mark - UITableViewDelegate Functions
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
if(section == CallSection) {
return [[UIView alloc] initWithFrame:CGRectZero];
} else if(section == ConferenceSection) {
LinphoneCore* lc = [LinphoneManager getLc];
if(linphone_core_get_conference_size(lc) > 0){
UIConferenceHeader *headerController = [[UIConferenceHeader alloc] init];
[headerController update];
UIView *headerView = [headerController view];
return headerView;
} else {
return [[UIView alloc] initWithFrame:CGRectZero];
}
}
return [[UIView alloc] initWithFrame:CGRectZero];
if (section == CallSection) {
return [[UIView alloc] initWithFrame:CGRectZero];
} else if (section == ConferenceSection) {
LinphoneCore *lc = [LinphoneManager getLc];
if (linphone_core_get_conference_size(lc) > 0) {
UIConferenceHeader *headerController = [[UIConferenceHeader alloc] init];
[headerController update];
UIView *headerView = [headerController view];
return headerView;
} else {
return [[UIView alloc] initWithFrame:CGRectZero];
}
}
return [[UIView alloc] initWithFrame:CGRectZero];
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
return [[UIView alloc] initWithFrame:CGRectZero];
return [[UIView alloc] initWithFrame:CGRectZero];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
LinphoneCore* lc = [LinphoneManager getLc];
if(section == CallSection) {
return 0.000001f; // Hack UITableView = 0
} else if(section == ConferenceSection) {
if(linphone_core_get_conference_size(lc) > 0) {
return [UIConferenceHeader getHeight];
}
}
return 0.000001f; // Hack UITableView = 0
LinphoneCore *lc = [LinphoneManager getLc];
if (section == CallSection) {
return 0.000001f; // Hack UITableView = 0
} else if (section == ConferenceSection) {
if (linphone_core_get_conference_size(lc) > 0) {
return [UIConferenceHeader getHeight];
}
}
return 0.000001f; // Hack UITableView = 0
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
LinphoneCore* lc = [LinphoneManager getLc];
if(section == CallSection) {
return 0.000001f; // Hack UITableView = 0
} else if(section == ConferenceSection) {
if(linphone_core_get_conference_size(lc) > 0) {
return 20;
}
}
return 0.000001f; // Hack UITableView = 0
LinphoneCore *lc = [LinphoneManager getLc];
if (section == CallSection) {
return 0.000001f; // Hack UITableView = 0
} else if (section == ConferenceSection) {
if (linphone_core_get_conference_size(lc) > 0) {
return 20;
}
}
return 0.000001f; // Hack UITableView = 0
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
bool inConference = indexPath.section == ConferenceSection;
LinphoneCall* call = [InCallTableViewController retrieveCallAtIndex:indexPath.row inConference:inConference];
UICallCellData* data = [self getCallData:call];
if(data != nil &&data->minimize)
return [UICallCell getMinimizedHeight];
return [UICallCell getMaximizedHeight];
bool inConference = indexPath.section == ConferenceSection;
LinphoneCall *call = [InCallTableViewController retrieveCallAtIndex:indexPath.row inConference:inConference];
UICallCellData *data = [self getCallData:call];
if (data != nil && data->minimize)
return [UICallCell getMinimizedHeight];
return [UICallCell getMaximizedHeight];
}
@end

View file

@ -33,11 +33,10 @@
#include "linphone/linphonecore.h"
const NSInteger SECURE_BUTTON_TAG=5;
const NSInteger SECURE_BUTTON_TAG = 5;
@implementation InCallViewController {
BOOL hiddenVolume;
BOOL hiddenVolume;
}
@synthesize callTableController;
@ -52,446 +51,443 @@ const NSInteger SECURE_BUTTON_TAG=5;
@synthesize testVideoView;
#endif
#pragma mark - Lifecycle Functions
- (id)init {
self = [super initWithNibName:@"InCallViewController" bundle:[NSBundle mainBundle]];
if(self != nil) {
self->singleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showControls:)];
self->videoZoomHandler = [[VideoZoomHandler alloc] init];
}
return self;
self = [super initWithNibName:@"InCallViewController" bundle:[NSBundle mainBundle]];
if (self != nil) {
self->singleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showControls:)];
self->videoZoomHandler = [[VideoZoomHandler alloc] init];
}
return self;
}
- (void)dealloc {
[[PhoneMainView instance].view removeGestureRecognizer:singleFingerTap];
// Remove all observer
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[PhoneMainView instance].view removeGestureRecognizer:singleFingerTap];
// Remove all observer
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - UICompositeViewDelegate Functions
static UICompositeViewDescription *compositeDescription = nil;
+ (UICompositeViewDescription *)compositeViewDescription {
if(compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"InCall"
content:@"InCallViewController"
stateBar:@"UIStateBar"
stateBarEnabled:true
tabBar:@"UICallBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:true
portraitMode:true];
compositeDescription.darkBackground = true;
}
return compositeDescription;
if (compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"InCall"
content:@"InCallViewController"
stateBar:@"UIStateBar"
stateBarEnabled:true
tabBar:@"UICallBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:true
portraitMode:true];
compositeDescription.darkBackground = true;
}
return compositeDescription;
}
#pragma mark - ViewController Functions
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[super viewDidAppear:animated];
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
UIDevice *device = [UIDevice currentDevice];
device.proximityMonitoringEnabled = YES;
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
UIDevice *device = [UIDevice currentDevice];
device.proximityMonitoringEnabled = YES;
[[PhoneMainView instance] setVolumeHidden:TRUE];
hiddenVolume = TRUE;
[[PhoneMainView instance] setVolumeHidden:TRUE];
hiddenVolume = TRUE;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if (hideControlsTimer != nil) {
[hideControlsTimer invalidate];
hideControlsTimer = nil;
}
[super viewWillDisappear:animated];
if (hideControlsTimer != nil) {
[hideControlsTimer invalidate];
hideControlsTimer = nil;
}
if( hiddenVolume ) {
[[PhoneMainView instance] setVolumeHidden:FALSE];
hiddenVolume = FALSE;
}
if (hiddenVolume) {
[[PhoneMainView instance] setVolumeHidden:FALSE];
hiddenVolume = FALSE;
}
// Remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneCallUpdate
object:nil];
// Remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneCallUpdate object:nil];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Set observer
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(callUpdateEvent:)
name:kLinphoneCallUpdate
object:nil];
[super viewWillAppear:animated];
// Set observer
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(callUpdateEvent:)
name:kLinphoneCallUpdate
object:nil];
// Update on show
LinphoneCall* call = linphone_core_get_current_call([LinphoneManager getLc]);
LinphoneCallState state = (call != NULL)?linphone_call_get_state(call): 0;
[self callUpdate:call state:state animated:FALSE];
// Update on show
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
LinphoneCallState state = (call != NULL) ? linphone_call_get_state(call) : 0;
[self callUpdate:call state:state animated:FALSE];
// Set windows (warn memory leaks)
linphone_core_set_native_video_window_id([LinphoneManager getLc], (unsigned long)videoView);
linphone_core_set_native_preview_window_id([LinphoneManager getLc], (unsigned long)videoPreview);
// Set windows (warn memory leaks)
linphone_core_set_native_video_window_id([LinphoneManager getLc], (unsigned long)videoView);
linphone_core_set_native_preview_window_id([LinphoneManager getLc], (unsigned long)videoPreview);
// Enable tap
[singleFingerTap setEnabled:TRUE];
// Enable tap
[singleFingerTap setEnabled:TRUE];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[super viewDidDisappear:animated];
[[UIApplication sharedApplication] setIdleTimerDisabled:false];
UIDevice *device = [UIDevice currentDevice];
device.proximityMonitoringEnabled = NO;
device.proximityMonitoringEnabled = NO;
[[PhoneMainView instance] fullScreen:false];
// Disable tap
[singleFingerTap setEnabled:FALSE];
[[PhoneMainView instance] fullScreen:false];
// Disable tap
[singleFingerTap setEnabled:FALSE];
}
- (void)viewDidLoad {
[super viewDidLoad];
[super viewDidLoad];
[singleFingerTap setNumberOfTapsRequired:1];
[singleFingerTap setCancelsTouchesInView: FALSE];
[[PhoneMainView instance].view addGestureRecognizer:singleFingerTap];
[singleFingerTap setNumberOfTapsRequired:1];
[singleFingerTap setCancelsTouchesInView:FALSE];
[[PhoneMainView instance].view addGestureRecognizer:singleFingerTap];
[videoZoomHandler setup:videoGroup];
videoGroup.alpha = 0;
[videoZoomHandler setup:videoGroup];
videoGroup.alpha = 0;
[videoCameraSwitch setPreview:videoPreview];
[videoCameraSwitch setPreview:videoPreview];
[callTableController.tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4
[callTableController.tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
[callTableController.tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4
[callTableController.tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
}
- (void)viewDidUnload {
[super viewDidUnload];
[[PhoneMainView instance].view removeGestureRecognizer:singleFingerTap];
[super viewDidUnload];
[[PhoneMainView instance].view removeGestureRecognizer:singleFingerTap];
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
// in mode display_filter_auto_rotate=0, no need to rotate the preview
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
// in mode display_filter_auto_rotate=0, no need to rotate the preview
}
#pragma mark -
- (void)callUpdate:(LinphoneCall *)call state:(LinphoneCallState)state animated:(BOOL)animated {
LinphoneCore *lc = [LinphoneManager getLc];
if( hiddenVolume ){
[[PhoneMainView instance] setVolumeHidden:FALSE];
hiddenVolume = FALSE;
}
// Update table
[callTableView reloadData];
// Fake call update
if(call == NULL) {
return;
}
switch (state) {
case LinphoneCallIncomingReceived:
case LinphoneCallOutgoingInit:
{
if(linphone_core_get_calls_nb(lc) > 1) {
[callTableController minimizeAll];
}
}
case LinphoneCallConnected:
case LinphoneCallStreamsRunning:
{
//check video
if (linphone_call_params_video_enabled(linphone_call_get_current_params(call))) {
[self displayVideoCall:animated];
} else {
[self displayTableCall:animated];
const LinphoneCallParams* param = linphone_call_get_current_params(call);
const LinphoneCallAppData* callAppData = (__bridge const LinphoneCallAppData *)(linphone_call_get_user_pointer(call));
if(state == LinphoneCallStreamsRunning
&& callAppData->videoRequested
&& linphone_call_params_low_bandwidth_enabled(param)) {
//too bad video was not enabled because low bandwidth
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Low bandwidth", nil)
message:NSLocalizedString(@"Video cannot be activated because of low bandwidth condition, only audio is available", nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(@"Continue", nil)
otherButtonTitles:nil];
[alert show];
callAppData->videoRequested=FALSE; /*reset field*/
}
}
break;
}
case LinphoneCallUpdatedByRemote:
{
const LinphoneCallParams* current = linphone_call_get_current_params(call);
const LinphoneCallParams* remote = linphone_call_get_remote_params(call);
/* remote wants to add video */
if (linphone_core_video_enabled(lc) && !linphone_call_params_video_enabled(current) &&
linphone_call_params_video_enabled(remote) &&
!linphone_core_get_video_policy(lc)->automatically_accept) {
linphone_core_defer_call_update(lc, call);
[self displayAskToEnableVideoCall:call];
} else if (linphone_call_params_video_enabled(current) && !linphone_call_params_video_enabled(remote)) {
[self displayTableCall:animated];
}
break;
}
case LinphoneCallPausing:
case LinphoneCallPaused:
case LinphoneCallPausedByRemote:
{
[self displayTableCall:animated];
break;
}
case LinphoneCallEnd:
case LinphoneCallError:
{
if(linphone_core_get_calls_nb(lc) <= 2 && !videoShown) {
[callTableController maximizeAll];
}
break;
}
default:
break;
if (hiddenVolume) {
[[PhoneMainView instance] setVolumeHidden:FALSE];
hiddenVolume = FALSE;
}
// Update table
[callTableView reloadData];
// Fake call update
if (call == NULL) {
return;
}
switch (state) {
case LinphoneCallIncomingReceived:
case LinphoneCallOutgoingInit: {
if (linphone_core_get_calls_nb(lc) > 1) {
[callTableController minimizeAll];
}
}
case LinphoneCallConnected:
case LinphoneCallStreamsRunning: {
// check video
if (linphone_call_params_video_enabled(linphone_call_get_current_params(call))) {
[self displayVideoCall:animated];
} else {
[self displayTableCall:animated];
const LinphoneCallParams *param = linphone_call_get_current_params(call);
const LinphoneCallAppData *callAppData =
(__bridge const LinphoneCallAppData *)(linphone_call_get_user_pointer(call));
if (state == LinphoneCallStreamsRunning && callAppData->videoRequested &&
linphone_call_params_low_bandwidth_enabled(param)) {
// too bad video was not enabled because low bandwidth
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:NSLocalizedString(@"Low bandwidth", nil)
message:NSLocalizedString(@"Video cannot be activated because of low bandwidth "
@"condition, only audio is available",
nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(@"Continue", nil)
otherButtonTitles:nil];
[alert show];
callAppData->videoRequested = FALSE; /*reset field*/
}
}
break;
}
case LinphoneCallUpdatedByRemote: {
const LinphoneCallParams *current = linphone_call_get_current_params(call);
const LinphoneCallParams *remote = linphone_call_get_remote_params(call);
/* remote wants to add video */
if (linphone_core_video_enabled(lc) && !linphone_call_params_video_enabled(current) &&
linphone_call_params_video_enabled(remote) && !linphone_core_get_video_policy(lc)->automatically_accept) {
linphone_core_defer_call_update(lc, call);
[self displayAskToEnableVideoCall:call];
} else if (linphone_call_params_video_enabled(current) && !linphone_call_params_video_enabled(remote)) {
[self displayTableCall:animated];
}
break;
}
case LinphoneCallPausing:
case LinphoneCallPaused:
case LinphoneCallPausedByRemote: {
[self displayTableCall:animated];
break;
}
case LinphoneCallEnd:
case LinphoneCallError: {
if (linphone_core_get_calls_nb(lc) <= 2 && !videoShown) {
[callTableController maximizeAll];
}
break;
}
default:
break;
}
}
- (void)showControls:(id)sender {
if (hideControlsTimer) {
[hideControlsTimer invalidate];
hideControlsTimer = nil;
}
if (hideControlsTimer) {
[hideControlsTimer invalidate];
hideControlsTimer = nil;
}
if([[[PhoneMainView instance] currentView] equal:[InCallViewController compositeViewDescription]] && videoShown) {
// show controls
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[[PhoneMainView instance] showTabBar: true];
[[PhoneMainView instance] showStateBar: true];
[callTableView setAlpha:1.0];
[videoCameraSwitch setAlpha:1.0];
[UIView commitAnimations];
if ([[[PhoneMainView instance] currentView] equal:[InCallViewController compositeViewDescription]] && videoShown) {
// show controls
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[[PhoneMainView instance] showTabBar:true];
[[PhoneMainView instance] showStateBar:true];
[callTableView setAlpha:1.0];
[videoCameraSwitch setAlpha:1.0];
[UIView commitAnimations];
// hide controls in 5 sec
hideControlsTimer = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:@selector(hideControls:)
userInfo:nil
repeats:NO];
}
// hide controls in 5 sec
hideControlsTimer = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:@selector(hideControls:)
userInfo:nil
repeats:NO];
}
}
- (void)hideControls:(id)sender {
if (hideControlsTimer) {
[hideControlsTimer invalidate];
hideControlsTimer = nil;
}
if (hideControlsTimer) {
[hideControlsTimer invalidate];
hideControlsTimer = nil;
}
if([[[PhoneMainView instance] currentView] equal:[InCallViewController compositeViewDescription]] && videoShown) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[videoCameraSwitch setAlpha:0.0];
[callTableView setAlpha:0.0];
[UIView commitAnimations];
if ([[[PhoneMainView instance] currentView] equal:[InCallViewController compositeViewDescription]] && videoShown) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[videoCameraSwitch setAlpha:0.0];
[callTableView setAlpha:0.0];
[UIView commitAnimations];
[[PhoneMainView instance] showTabBar: false];
[[PhoneMainView instance] showStateBar: false];
}
[[PhoneMainView instance] showTabBar:false];
[[PhoneMainView instance] showStateBar:false];
}
}
#ifdef TEST_VIDEO_VIEW_CHANGE
// Define TEST_VIDEO_VIEW_CHANGE in IncallViewController.h to enable video view switching testing
- (void)_debugChangeVideoView {
static bool normalView = false;
if (normalView) {
linphone_core_set_native_video_window_id([LinphoneManager getLc], (unsigned long)videoView);
} else {
linphone_core_set_native_video_window_id([LinphoneManager getLc], (unsigned long)testVideoView);
}
normalView = !normalView;
static bool normalView = false;
if (normalView) {
linphone_core_set_native_video_window_id([LinphoneManager getLc], (unsigned long)videoView);
} else {
linphone_core_set_native_video_window_id([LinphoneManager getLc], (unsigned long)testVideoView);
}
normalView = !normalView;
}
#endif
- (void)enableVideoDisplay:(BOOL)animation {
if(videoShown && animation)
return;
if (videoShown && animation)
return;
videoShown = true;
videoShown = true;
[videoZoomHandler resetZoom];
[videoZoomHandler resetZoom];
if(animation) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
}
if (animation) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
}
[videoGroup setAlpha:1.0];
[callTableView setAlpha:0.0];
[videoGroup setAlpha:1.0];
[callTableView setAlpha:0.0];
UIEdgeInsets insets = {33, 0, 25, 0};
[callTableView setContentInset:insets];
[callTableView setScrollIndicatorInsets:insets];
[callTableController minimizeAll];
UIEdgeInsets insets = {33, 0, 25, 0};
[callTableView setContentInset:insets];
[callTableView setScrollIndicatorInsets:insets];
[callTableController minimizeAll];
if(animation) {
[UIView commitAnimations];
}
if (animation) {
[UIView commitAnimations];
}
if(linphone_core_self_view_enabled([LinphoneManager getLc])) {
[videoPreview setHidden:FALSE];
} else {
[videoPreview setHidden:TRUE];
}
if (linphone_core_self_view_enabled([LinphoneManager getLc])) {
[videoPreview setHidden:FALSE];
} else {
[videoPreview setHidden:TRUE];
}
if ([LinphoneManager instance].frontCamId != nil) {
// only show camera switch button if we have more than 1 camera
[videoCameraSwitch setHidden:FALSE];
}
[videoCameraSwitch setAlpha:0.0];
if ([LinphoneManager instance].frontCamId != nil) {
// only show camera switch button if we have more than 1 camera
[videoCameraSwitch setHidden:FALSE];
}
[videoCameraSwitch setAlpha:0.0];
[[PhoneMainView instance] fullScreen: true];
[[PhoneMainView instance] showTabBar: false];
[[PhoneMainView instance] showStateBar: false];
[[PhoneMainView instance] fullScreen:true];
[[PhoneMainView instance] showTabBar:false];
[[PhoneMainView instance] showStateBar:false];
#ifdef TEST_VIDEO_VIEW_CHANGE
[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(_debugChangeVideoView) userInfo:nil repeats:YES];
[NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:@selector(_debugChangeVideoView)
userInfo:nil
repeats:YES];
#endif
// [self batteryLevelChanged:nil];
// [self batteryLevelChanged:nil];
[videoWaitingForFirstImage setHidden: NO];
[videoWaitingForFirstImage startAnimating];
[videoWaitingForFirstImage setHidden:NO];
[videoWaitingForFirstImage startAnimating];
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
//linphone_call_params_get_used_video_codec return 0 if no video stream enabled
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
// linphone_call_params_get_used_video_codec return 0 if no video stream enabled
if (call != NULL && linphone_call_params_get_used_video_codec(linphone_call_get_current_params(call))) {
linphone_call_set_next_video_frame_decoded_callback(call, hideSpinner, (__bridge void *)(self));
}
linphone_call_set_next_video_frame_decoded_callback(call, hideSpinner, (__bridge void *)(self));
}
}
- (void)disableVideoDisplay:(BOOL)animation {
if(!videoShown && animation)
return;
if (!videoShown && animation)
return;
videoShown = false;
if(animation) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
}
videoShown = false;
if (animation) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
}
[videoGroup setAlpha:0.0];
[[PhoneMainView instance] showTabBar: true];
[videoGroup setAlpha:0.0];
[[PhoneMainView instance] showTabBar:true];
UIEdgeInsets insets = {10, 0, 25, 0};
[callTableView setContentInset:insets];
[callTableView setScrollIndicatorInsets:insets];
[callTableView setAlpha:1.0];
if(linphone_core_get_calls_nb([LinphoneManager getLc]) <= 2) {
[callTableController maximizeAll];
}
UIEdgeInsets insets = {10, 0, 25, 0};
[callTableView setContentInset:insets];
[callTableView setScrollIndicatorInsets:insets];
[callTableView setAlpha:1.0];
if (linphone_core_get_calls_nb([LinphoneManager getLc]) <= 2) {
[callTableController maximizeAll];
}
[callTableView setAlpha:1.0];
[videoCameraSwitch setHidden:TRUE];
[callTableView setAlpha:1.0];
[videoCameraSwitch setHidden:TRUE];
if(animation) {
[UIView commitAnimations];
}
if (animation) {
[UIView commitAnimations];
}
if (hideControlsTimer != nil) {
[hideControlsTimer invalidate];
hideControlsTimer = nil;
}
if (hideControlsTimer != nil) {
[hideControlsTimer invalidate];
hideControlsTimer = nil;
}
[[PhoneMainView instance] fullScreen:false];
[[PhoneMainView instance] fullScreen:false];
}
- (void)displayVideoCall:(BOOL)animated {
[self enableVideoDisplay:animated];
[self enableVideoDisplay:animated];
}
- (void)displayTableCall:(BOOL)animated {
[self disableVideoDisplay:animated];
[self disableVideoDisplay:animated];
}
#pragma mark - Spinner Functions
- (void)hideSpinnerIndicator: (LinphoneCall*)call {
videoWaitingForFirstImage.hidden = TRUE;
- (void)hideSpinnerIndicator:(LinphoneCall *)call {
videoWaitingForFirstImage.hidden = TRUE;
}
static void hideSpinner(LinphoneCall* call, void* user_data) {
InCallViewController* thiz = (__bridge InCallViewController*) user_data;
[thiz hideSpinnerIndicator:call];
static void hideSpinner(LinphoneCall *call, void *user_data) {
InCallViewController *thiz = (__bridge InCallViewController *)user_data;
[thiz hideSpinnerIndicator:call];
}
#pragma mark - Event Functions
- (void)callUpdateEvent: (NSNotification*) notif {
LinphoneCall *call = [[notif.userInfo objectForKey: @"call"] pointerValue];
LinphoneCallState state = [[notif.userInfo objectForKey: @"state"] intValue];
[self callUpdate:call state:state animated:TRUE];
- (void)callUpdateEvent:(NSNotification *)notif {
LinphoneCall *call = [[notif.userInfo objectForKey:@"call"] pointerValue];
LinphoneCallState state = [[notif.userInfo objectForKey:@"state"] intValue];
[self callUpdate:call state:state animated:TRUE];
}
#pragma mark - ActionSheet Functions
- (void)displayAskToEnableVideoCall:(LinphoneCall*) call {
if (linphone_core_get_video_policy([LinphoneManager getLc])->automatically_accept)
return;
- (void)displayAskToEnableVideoCall:(LinphoneCall *)call {
if (linphone_core_get_video_policy([LinphoneManager getLc])->automatically_accept)
return;
const char* lUserNameChars = linphone_address_get_username(linphone_call_get_remote_address(call));
NSString* lUserName = lUserNameChars?[[NSString alloc] initWithUTF8String:lUserNameChars]:NSLocalizedString(@"Unknown",nil);
const char* lDisplayNameChars = linphone_address_get_display_name(linphone_call_get_remote_address(call));
NSString* lDisplayName = lDisplayNameChars?[[NSString alloc] initWithUTF8String:lDisplayNameChars]:@"";
const char *lUserNameChars = linphone_address_get_username(linphone_call_get_remote_address(call));
NSString *lUserName =
lUserNameChars ? [[NSString alloc] initWithUTF8String:lUserNameChars] : NSLocalizedString(@"Unknown", nil);
const char *lDisplayNameChars = linphone_address_get_display_name(linphone_call_get_remote_address(call));
NSString *lDisplayName = lDisplayNameChars ? [[NSString alloc] initWithUTF8String:lDisplayNameChars] : @"";
NSString* title = [NSString stringWithFormat : NSLocalizedString(@"'%@' would like to enable video",nil), ([lDisplayName length] > 0)?lDisplayName:lUserName];
DTActionSheet *sheet = [[DTActionSheet alloc] initWithTitle:title];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(dismissVideoActionSheet:) userInfo:sheet repeats:NO];
[sheet addButtonWithTitle:NSLocalizedString(@"Accept", nil) block:^() {
LOGI(@"User accept video proposal");
LinphoneCallParams* paramsCopy = linphone_call_params_copy(linphone_call_get_current_params(call));
linphone_call_params_enable_video(paramsCopy, TRUE);
linphone_core_accept_call_update([LinphoneManager getLc], call, paramsCopy);
linphone_call_params_destroy(paramsCopy);
[timer invalidate];
}];
DTActionSheetBlock cancelBlock = ^() {
LOGI(@"User declined video proposal");
LinphoneCallParams* paramsCopy = linphone_call_params_copy(linphone_call_get_current_params(call));
linphone_core_accept_call_update([LinphoneManager getLc], call, paramsCopy);
linphone_call_params_destroy(paramsCopy);
[timer invalidate];
};
[sheet addDestructiveButtonWithTitle:NSLocalizedString(@"Decline", nil) block:cancelBlock];
if([LinphoneManager runningOnIpad]) {
[sheet addCancelButtonWithTitle:NSLocalizedString(@"Decline", nil) block:cancelBlock];
}
[sheet showInView:[PhoneMainView instance].view];
NSString *title = [NSString stringWithFormat:NSLocalizedString(@"'%@' would like to enable video", nil),
([lDisplayName length] > 0) ? lDisplayName : lUserName];
DTActionSheet *sheet = [[DTActionSheet alloc] initWithTitle:title];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:30
target:self
selector:@selector(dismissVideoActionSheet:)
userInfo:sheet
repeats:NO];
[sheet addButtonWithTitle:NSLocalizedString(@"Accept", nil)
block:^() {
LOGI(@"User accept video proposal");
LinphoneCallParams *paramsCopy =
linphone_call_params_copy(linphone_call_get_current_params(call));
linphone_call_params_enable_video(paramsCopy, TRUE);
linphone_core_accept_call_update([LinphoneManager getLc], call, paramsCopy);
linphone_call_params_destroy(paramsCopy);
[timer invalidate];
}];
DTActionSheetBlock cancelBlock = ^() {
LOGI(@"User declined video proposal");
LinphoneCallParams *paramsCopy = linphone_call_params_copy(linphone_call_get_current_params(call));
linphone_core_accept_call_update([LinphoneManager getLc], call, paramsCopy);
linphone_call_params_destroy(paramsCopy);
[timer invalidate];
};
[sheet addDestructiveButtonWithTitle:NSLocalizedString(@"Decline", nil) block:cancelBlock];
if ([LinphoneManager runningOnIpad]) {
[sheet addCancelButtonWithTitle:NSLocalizedString(@"Decline", nil) block:cancelBlock];
}
[sheet showInView:[PhoneMainView instance].view];
}
- (void)dismissVideoActionSheet:(NSTimer*)timer {
DTActionSheet *sheet = (DTActionSheet *)timer.userInfo;
[sheet dismissWithClickedButtonIndex:sheet.destructiveButtonIndex animated:TRUE];
- (void)dismissVideoActionSheet:(NSTimer *)timer {
DTActionSheet *sheet = (DTActionSheet *)timer.userInfo;
[sheet dismissWithClickedButtonIndex:sheet.destructiveButtonIndex animated:TRUE];
}
@end

View file

@ -4,16 +4,16 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
@ -33,175 +33,164 @@
#pragma mark - Lifecycle Functions
- (id)init {
return [super initWithNibName:@"IncomingCallViewController" bundle:[NSBundle mainBundle]];
return [super initWithNibName:@"IncomingCallViewController" bundle:[NSBundle mainBundle]];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - ViewController Functions
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(callUpdateEvent:)
name:kLinphoneCallUpdate
object:nil];
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(callUpdateEvent:)
name:kLinphoneCallUpdate
object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneCallUpdate
object:nil];
}
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneCallUpdate object:nil];
}
#pragma mark - UICompositeViewDelegate Functions
static UICompositeViewDescription *compositeDescription = nil;
+ (UICompositeViewDescription *)compositeViewDescription {
if(compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"IncomingCall"
content:@"IncomingCallViewController"
stateBar:nil
stateBarEnabled:false
tabBar:nil
tabBarEnabled:false
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
compositeDescription.darkBackground = true;
}
return compositeDescription;
if (compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"IncomingCall"
content:@"IncomingCallViewController"
stateBar:nil
stateBarEnabled:false
tabBar:nil
tabBarEnabled:false
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
compositeDescription.darkBackground = true;
}
return compositeDescription;
}
#pragma mark - Event Functions
- (void)callUpdateEvent:(NSNotification*)notif {
LinphoneCall *acall = [[notif.userInfo objectForKey: @"call"] pointerValue];
LinphoneCallState astate = [[notif.userInfo objectForKey: @"state"] intValue];
[self callUpdate:acall state:astate];
- (void)callUpdateEvent:(NSNotification *)notif {
LinphoneCall *acall = [[notif.userInfo objectForKey:@"call"] pointerValue];
LinphoneCallState astate = [[notif.userInfo objectForKey:@"state"] intValue];
[self callUpdate:acall state:astate];
}
#pragma mark -
#pragma mark -
- (void)callUpdate:(LinphoneCall *)acall state:(LinphoneCallState)astate {
if(call == acall && (astate == LinphoneCallEnd || astate == LinphoneCallError)) {
[delegate incomingCallAborted:call];
[self dismiss];
}
- (void)callUpdate:(LinphoneCall *)acall state:(LinphoneCallState)astate {
if (call == acall && (astate == LinphoneCallEnd || astate == LinphoneCallError)) {
[delegate incomingCallAborted:call];
[self dismiss];
}
}
- (void)dismiss {
if([[[PhoneMainView instance] currentView] equal:[IncomingCallViewController compositeViewDescription]]) {
[[PhoneMainView instance] popCurrentView];
}
if ([[[PhoneMainView instance] currentView] equal:[IncomingCallViewController compositeViewDescription]]) {
[[PhoneMainView instance] popCurrentView];
}
}
- (void)update {
[self view]; //Force view load
[avatarImage setImage:[UIImage imageNamed:@"avatar_unknown.png"]];
NSString* address = nil;
const LinphoneAddress* addr = linphone_call_get_remote_address(call);
if (addr != NULL) {
BOOL useLinphoneAddress = true;
// contact name
char* lAddress = linphone_address_as_string_uri_only(addr);
if(lAddress) {
NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:[NSString stringWithUTF8String:lAddress]];
ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:normalizedSipAddress];
if(contact) {
UIImage *tmpImage = [FastAddressBook getContactImage:contact thumbnail:false];
if(tmpImage != nil) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void) {
UIImage *tmpImage2 = [UIImage decodedImageWithImage:tmpImage];
dispatch_async(dispatch_get_main_queue(), ^{
avatarImage.image = tmpImage2;
});
});
}
address = [FastAddressBook getContactDisplayName:contact];
useLinphoneAddress = false;
}
ms_free(lAddress);
}
if(useLinphoneAddress) {
const char* lDisplayName = linphone_address_get_display_name(addr);
const char* lUserName = linphone_address_get_username(addr);
if (lDisplayName)
address = [NSString stringWithUTF8String:lDisplayName];
else if(lUserName)
address = [NSString stringWithUTF8String:lUserName];
}
}
// Set Address
if(address == nil) {
address = @"Unknown";
}
[addressLabel setText:address];
}
[self view]; // Force view load
[avatarImage setImage:[UIImage imageNamed:@"avatar_unknown.png"]];
NSString *address = nil;
const LinphoneAddress *addr = linphone_call_get_remote_address(call);
if (addr != NULL) {
BOOL useLinphoneAddress = true;
// contact name
char *lAddress = linphone_address_as_string_uri_only(addr);
if (lAddress) {
NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:[NSString stringWithUTF8String:lAddress]];
ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:normalizedSipAddress];
if (contact) {
UIImage *tmpImage = [FastAddressBook getContactImage:contact thumbnail:false];
if (tmpImage != nil) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL),
^(void) {
UIImage *tmpImage2 = [UIImage decodedImageWithImage:tmpImage];
dispatch_async(dispatch_get_main_queue(), ^{
avatarImage.image = tmpImage2;
});
});
}
address = [FastAddressBook getContactDisplayName:contact];
useLinphoneAddress = false;
}
ms_free(lAddress);
}
if (useLinphoneAddress) {
const char *lDisplayName = linphone_address_get_display_name(addr);
const char *lUserName = linphone_address_get_username(addr);
if (lDisplayName)
address = [NSString stringWithUTF8String:lDisplayName];
else if (lUserName)
address = [NSString stringWithUTF8String:lUserName];
}
}
// Set Address
if (address == nil) {
address = @"Unknown";
}
[addressLabel setText:address];
}
#pragma mark - Property Functions
- (void)setCall:(LinphoneCall*)acall {
call = acall;
[self update];
[self callUpdate:call state:linphone_call_get_state(call)];
- (void)setCall:(LinphoneCall *)acall {
call = acall;
[self update];
[self callUpdate:call state:linphone_call_get_state(call)];
}
#pragma mark - Action Functions
- (IBAction)onAcceptClick:(id)event {
[self dismiss];
[delegate incomingCallAccepted:call];
[self dismiss];
[delegate incomingCallAccepted:call];
}
- (IBAction)onDeclineClick:(id)event {
[self dismiss];
[delegate incomingCallDeclined:call];
[self dismiss];
[delegate incomingCallDeclined:call];
}
#pragma mark - TPMultiLayoutViewController Functions
- (NSDictionary*)attributesForView:(UIView*)view {
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
[attributes setObject:[NSValue valueWithCGRect:view.frame] forKey:@"frame"];
[attributes setObject:[NSValue valueWithCGRect:view.bounds] forKey:@"bounds"];
if([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)view;
[LinphoneUtils buttonMultiViewAddAttributes:attributes button:button];
}
[attributes setObject:[NSNumber numberWithInteger:view.autoresizingMask] forKey:@"autoresizingMask"];
return attributes;
- (NSDictionary *)attributesForView:(UIView *)view {
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
[attributes setObject:[NSValue valueWithCGRect:view.frame] forKey:@"frame"];
[attributes setObject:[NSValue valueWithCGRect:view.bounds] forKey:@"bounds"];
if ([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)view;
[LinphoneUtils buttonMultiViewAddAttributes:attributes button:button];
}
[attributes setObject:[NSNumber numberWithInteger:view.autoresizingMask] forKey:@"autoresizingMask"];
return attributes;
}
- (void)applyAttributes:(NSDictionary*)attributes toView:(UIView*)view {
view.frame = [[attributes objectForKey:@"frame"] CGRectValue];
view.bounds = [[attributes objectForKey:@"bounds"] CGRectValue];
if([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)view;
[LinphoneUtils buttonMultiViewApplyAttributes:attributes button:button];
}
view.autoresizingMask = [[attributes objectForKey:@"autoresizingMask"] integerValue];
- (void)applyAttributes:(NSDictionary *)attributes toView:(UIView *)view {
view.frame = [[attributes objectForKey:@"frame"] CGRectValue];
view.bounds = [[attributes objectForKey:@"bounds"] CGRectValue];
if ([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)view;
[LinphoneUtils buttonMultiViewApplyAttributes:attributes button:button];
}
view.autoresizingMask = [[attributes objectForKey:@"autoresizingMask"] integerValue];
}
@end

View file

@ -37,142 +37,131 @@
#pragma mark - Lifecycle Functions
- (id)init {
self = [super init];
if(self != nil) {
self->startedInBackground = FALSE;
}
return self;
self = [super init];
if (self != nil) {
self->startedInBackground = FALSE;
}
return self;
}
#pragma mark -
- (void)applicationDidEnterBackground:(UIApplication *)application{
- (void)applicationDidEnterBackground:(UIApplication *)application {
LOGI(@"%@", NSStringFromSelector(_cmd));
[[LinphoneManager instance] enterBackgroundMode];
}
- (void)applicationWillResignActive:(UIApplication *)application {
LOGI(@"%@", NSStringFromSelector(_cmd));
LinphoneCore* lc = [LinphoneManager getLc];
LinphoneCall* call = linphone_core_get_current_call(lc);
LOGI(@"%@", NSStringFromSelector(_cmd));
LinphoneCore *lc = [LinphoneManager getLc];
LinphoneCall *call = linphone_core_get_current_call(lc);
if (call){
if (call) {
/* save call context */
LinphoneManager* instance = [LinphoneManager instance];
LinphoneManager *instance = [LinphoneManager instance];
instance->currentCallContextBeforeGoingBackground.call = call;
instance->currentCallContextBeforeGoingBackground.cameraIsEnabled = linphone_call_camera_enabled(call);
const LinphoneCallParams* params = linphone_call_get_current_params(call);
const LinphoneCallParams *params = linphone_call_get_current_params(call);
if (linphone_call_params_video_enabled(params)) {
linphone_call_enable_camera(call, false);
}
}
if (![[LinphoneManager instance] resignActive]) {
}
if (![[LinphoneManager instance] resignActive]) {
}
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
LOGI(@"%@", NSStringFromSelector(_cmd));
LOGI(@"%@", NSStringFromSelector(_cmd));
if( startedInBackground ){
startedInBackground = FALSE;
[[PhoneMainView instance] startUp];
[[PhoneMainView instance] updateStatusBar:nil];
}
LinphoneManager* instance = [LinphoneManager instance];
if (startedInBackground) {
startedInBackground = FALSE;
[[PhoneMainView instance] startUp];
[[PhoneMainView instance] updateStatusBar:nil];
}
LinphoneManager *instance = [LinphoneManager instance];
[instance becomeActive];
[instance becomeActive];
LinphoneCore* lc = [LinphoneManager getLc];
LinphoneCall* call = linphone_core_get_current_call(lc);
LinphoneCore *lc = [LinphoneManager getLc];
LinphoneCall *call = linphone_core_get_current_call(lc);
if (call){
if (call == instance->currentCallContextBeforeGoingBackground.call) {
const LinphoneCallParams* params = linphone_call_get_current_params(call);
if (linphone_call_params_video_enabled(params)) {
linphone_call_enable_camera(
call,
instance->currentCallContextBeforeGoingBackground.cameraIsEnabled);
}
instance->currentCallContextBeforeGoingBackground.call = 0;
} else if ( linphone_call_get_state(call) == LinphoneCallIncomingReceived ) {
[[PhoneMainView instance ] displayIncomingCall:call];
// in this case, the ringing sound comes from the notification.
// To stop it we have to do the iOS7 ring fix...
[self fixRing];
}
}
if (call) {
if (call == instance->currentCallContextBeforeGoingBackground.call) {
const LinphoneCallParams *params = linphone_call_get_current_params(call);
if (linphone_call_params_video_enabled(params)) {
linphone_call_enable_camera(call, instance->currentCallContextBeforeGoingBackground.cameraIsEnabled);
}
instance->currentCallContextBeforeGoingBackground.call = 0;
} else if (linphone_call_get_state(call) == LinphoneCallIncomingReceived) {
[[PhoneMainView instance] displayIncomingCall:call];
// in this case, the ringing sound comes from the notification.
// To stop it we have to do the iOS7 ring fix...
[self fixRing];
}
}
}
- (UIUserNotificationCategory*)getMessageNotificationCategory {
- (UIUserNotificationCategory *)getMessageNotificationCategory {
UIMutableUserNotificationAction* reply = [[UIMutableUserNotificationAction alloc] init];
reply.identifier = @"reply";
reply.title = NSLocalizedString(@"Reply", nil);
reply.activationMode = UIUserNotificationActivationModeForeground;
reply.destructive = NO;
reply.authenticationRequired = YES;
UIMutableUserNotificationAction *reply = [[UIMutableUserNotificationAction alloc] init];
reply.identifier = @"reply";
reply.title = NSLocalizedString(@"Reply", nil);
reply.activationMode = UIUserNotificationActivationModeForeground;
reply.destructive = NO;
reply.authenticationRequired = YES;
UIMutableUserNotificationAction* mark_read = [[UIMutableUserNotificationAction alloc] init];
mark_read.identifier = @"mark_read";
mark_read.title = NSLocalizedString(@"Mark Read", nil);
mark_read.activationMode = UIUserNotificationActivationModeBackground;
mark_read.destructive = NO;
mark_read.authenticationRequired = NO;
UIMutableUserNotificationAction *mark_read = [[UIMutableUserNotificationAction alloc] init];
mark_read.identifier = @"mark_read";
mark_read.title = NSLocalizedString(@"Mark Read", nil);
mark_read.activationMode = UIUserNotificationActivationModeBackground;
mark_read.destructive = NO;
mark_read.authenticationRequired = NO;
NSArray* localRingActions = @[mark_read, reply];
NSArray *localRingActions = @[ mark_read, reply ];
UIMutableUserNotificationCategory* localRingNotifAction = [[UIMutableUserNotificationCategory alloc] init];
localRingNotifAction.identifier = @"incoming_msg";
[localRingNotifAction setActions:localRingActions forContext:UIUserNotificationActionContextDefault];
[localRingNotifAction setActions:localRingActions forContext:UIUserNotificationActionContextMinimal];
UIMutableUserNotificationCategory *localRingNotifAction = [[UIMutableUserNotificationCategory alloc] init];
localRingNotifAction.identifier = @"incoming_msg";
[localRingNotifAction setActions:localRingActions forContext:UIUserNotificationActionContextDefault];
[localRingNotifAction setActions:localRingActions forContext:UIUserNotificationActionContextMinimal];
return localRingNotifAction;
return localRingNotifAction;
}
- (UIUserNotificationCategory*)getCallNotificationCategory {
UIMutableUserNotificationAction* answer = [[UIMutableUserNotificationAction alloc] init];
answer.identifier = @"answer";
answer.title = NSLocalizedString(@"Answer", nil);
answer.activationMode = UIUserNotificationActivationModeForeground;
answer.destructive = NO;
answer.authenticationRequired = YES;
- (UIUserNotificationCategory *)getCallNotificationCategory {
UIMutableUserNotificationAction *answer = [[UIMutableUserNotificationAction alloc] init];
answer.identifier = @"answer";
answer.title = NSLocalizedString(@"Answer", nil);
answer.activationMode = UIUserNotificationActivationModeForeground;
answer.destructive = NO;
answer.authenticationRequired = YES;
UIMutableUserNotificationAction* decline = [[UIMutableUserNotificationAction alloc] init];
decline.identifier = @"decline";
decline.title = NSLocalizedString(@"Decline", nil);
decline.activationMode = UIUserNotificationActivationModeBackground;
decline.destructive = YES;
decline.authenticationRequired = NO;
UIMutableUserNotificationAction *decline = [[UIMutableUserNotificationAction alloc] init];
decline.identifier = @"decline";
decline.title = NSLocalizedString(@"Decline", nil);
decline.activationMode = UIUserNotificationActivationModeBackground;
decline.destructive = YES;
decline.authenticationRequired = NO;
NSArray *localRingActions = @[ decline, answer ];
NSArray* localRingActions = @[decline, answer];
UIMutableUserNotificationCategory *localRingNotifAction = [[UIMutableUserNotificationCategory alloc] init];
localRingNotifAction.identifier = @"incoming_call";
[localRingNotifAction setActions:localRingActions forContext:UIUserNotificationActionContextDefault];
[localRingNotifAction setActions:localRingActions forContext:UIUserNotificationActionContextMinimal];
UIMutableUserNotificationCategory* localRingNotifAction = [[UIMutableUserNotificationCategory alloc] init];
localRingNotifAction.identifier = @"incoming_call";
[localRingNotifAction setActions:localRingActions forContext:UIUserNotificationActionContextDefault];
[localRingNotifAction setActions:localRingActions forContext:UIUserNotificationActionContextMinimal];
return localRingNotifAction;
return localRingNotifAction;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIApplication* app= [UIApplication sharedApplication];
UIApplicationState state = app.applicationState;
UIApplication *app = [UIApplication sharedApplication];
UIApplicationState state = app.applicationState;
LinphoneManager* instance = [LinphoneManager instance];
BOOL background_mode = [instance lpConfigBoolForKey:@"backgroundmode_preference"];
BOOL start_at_boot = [instance lpConfigBoolForKey:@"start_at_boot_preference"];
LinphoneManager *instance = [LinphoneManager instance];
BOOL background_mode = [instance lpConfigBoolForKey:@"backgroundmode_preference"];
BOOL start_at_boot = [instance lpConfigBoolForKey:@"start_at_boot_preference"];
if ([app respondsToSelector:@selector(registerUserNotificationSettings:)]) {
/* iOS8 notifications can be actioned! Awesome: */
@ -203,316 +192,333 @@
// autoboot disabled or no background, and no push: do nothing and wait for a real launch
/*output a log with NSLog, because the ortp logging system isn't activated yet at this time*/
NSLog(@"Linphone launch doing nothing because start_at_boot or background_mode are not activated.", NULL);
return YES;
}
}
return YES;
}
}
bgStartId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
LOGW(@"Background task for application launching expired.");
[[UIApplication sharedApplication] endBackgroundTask:bgStartId];
LOGW(@"Background task for application launching expired.");
[[UIApplication sharedApplication] endBackgroundTask:bgStartId];
}];
[[LinphoneManager instance] startLinphoneCore];
// initialize UI
[self.window makeKeyAndVisible];
[RootViewManager setupWithPortrait:(PhoneMainView*)self.window.rootViewController];
[[PhoneMainView instance] startUp];
[[PhoneMainView instance] updateStatusBar:nil];
[[LinphoneManager instance] startLinphoneCore];
// initialize UI
[self.window makeKeyAndVisible];
[RootViewManager setupWithPortrait:(PhoneMainView *)self.window.rootViewController];
[[PhoneMainView instance] startUp];
[[PhoneMainView instance] updateStatusBar:nil];
NSDictionary *remoteNotif =[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotif){
NSDictionary *remoteNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotif) {
LOGI(@"PushNotification from launch received.");
[self processRemoteNotification:remoteNotif];
}
if (bgStartId!=UIBackgroundTaskInvalid) [[UIApplication sharedApplication] endBackgroundTask:bgStartId];
if (bgStartId != UIBackgroundTaskInvalid)
[[UIApplication sharedApplication] endBackgroundTask:bgStartId];
return YES;
}
- (void)applicationWillTerminate:(UIApplication *)application {
LOGI(@"%@", NSStringFromSelector(_cmd));
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
NSString *scheme = [[url scheme] lowercaseString];
if ([scheme isEqualToString:@"linphone-config"] || [scheme isEqualToString:@"linphone-config"]) {
NSString* encodedURL = [[url absoluteString] stringByReplacingOccurrencesOfString:@"linphone-config://" withString:@""];
self.configURL = [encodedURL stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
UIAlertView* confirmation = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Remote configuration",nil)
message:NSLocalizedString(@"This operation will load a remote configuration. Continue ?",nil)
delegate:self
cancelButtonTitle:NSLocalizedString(@"No",nil)
otherButtonTitles:NSLocalizedString(@"Yes",nil),nil];
confirmation.tag = 1;
[confirmation show];
} else {
if([[url scheme] isEqualToString:@"sip"]) {
// remove "sip://" from the URI, and do it correctly by taking resourceSpecifier and removing leading and trailing "/"
NSString* sipUri = [[url resourceSpecifier] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"/"]];
DialerViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]], DialerViewController);
if(controller != nil) {
[controller setAddress:sipUri];
}
}
}
return YES;
}
- (void)fixRing{
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
// iOS7 fix for notification sound not stopping.
// see http://stackoverflow.com/questions/19124882/stopping-ios-7-remote-notification-sound
[[UIApplication sharedApplication] setApplicationIconBadgeNumber: 1];
[[UIApplication sharedApplication] setApplicationIconBadgeNumber: 0];
}
- (void)applicationWillTerminate:(UIApplication *)application {
LOGI(@"%@", NSStringFromSelector(_cmd));
}
- (void)processRemoteNotification:(NSDictionary*)userInfo{
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
NSString *scheme = [[url scheme] lowercaseString];
if ([scheme isEqualToString:@"linphone-config"] || [scheme isEqualToString:@"linphone-config"]) {
NSString *encodedURL =
[[url absoluteString] stringByReplacingOccurrencesOfString:@"linphone-config://" withString:@""];
self.configURL = [encodedURL stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
UIAlertView *confirmation = [[UIAlertView alloc]
initWithTitle:NSLocalizedString(@"Remote configuration", nil)
message:NSLocalizedString(@"This operation will load a remote configuration. Continue ?", nil)
delegate:self
cancelButtonTitle:NSLocalizedString(@"No", nil)
otherButtonTitles:NSLocalizedString(@"Yes", nil), nil];
confirmation.tag = 1;
[confirmation show];
} else {
if ([[url scheme] isEqualToString:@"sip"]) {
// remove "sip://" from the URI, and do it correctly by taking resourceSpecifier and removing leading and
// trailing "/"
NSString *sipUri = [[url resourceSpecifier]
stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"/"]];
DialerViewController *controller = DYNAMIC_CAST(
[[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]],
DialerViewController);
if (controller != nil) {
[controller setAddress:sipUri];
}
}
}
return YES;
}
- (void)fixRing {
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
// iOS7 fix for notification sound not stopping.
// see http://stackoverflow.com/questions/19124882/stopping-ios-7-remote-notification-sound
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:1];
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
}
}
- (void)processRemoteNotification:(NSDictionary *)userInfo {
NSDictionary *aps = [userInfo objectForKey:@"aps"];
if(aps != nil) {
NSDictionary *alert = [aps objectForKey:@"alert"];
if(alert != nil) {
NSString *loc_key = [alert objectForKey:@"loc-key"];
if (aps != nil) {
NSDictionary *alert = [aps objectForKey:@"alert"];
if (alert != nil) {
NSString *loc_key = [alert objectForKey:@"loc-key"];
/*if we receive a remote notification, it is probably because our TCP background socket was no more working.
As a result, break it and refresh registers in order to make sure to receive incoming INVITE or MESSAGE*/
LinphoneCore *lc = [LinphoneManager getLc];
if (linphone_core_get_calls(lc)==NULL){ //if there are calls, obviously our TCP socket shall be working
if (linphone_core_get_calls(lc) == NULL) { // if there are calls, obviously our TCP socket shall be working
linphone_core_set_network_reachable(lc, FALSE);
[LinphoneManager instance].connectivity=none; /*force connectivity to be discovered again*/
[[LinphoneManager instance] refreshRegisters];
if(loc_key != nil) {
[LinphoneManager instance].connectivity = none; /*force connectivity to be discovered again*/
[[LinphoneManager instance] refreshRegisters];
if (loc_key != nil) {
NSString* callId = [userInfo objectForKey:@"call-id"];
if( callId != nil ){
NSString *callId = [userInfo objectForKey:@"call-id"];
if (callId != nil) {
[[LinphoneManager instance] addPushCallId:callId];
} else {
LOGE(@"PushNotification: does not have call-id yet, fix it !");
}
if( [loc_key isEqualToString:@"IM_MSG"] ) {
if ([loc_key isEqualToString:@"IM_MSG"]) {
[[PhoneMainView instance] changeCurrentView:[ChatViewController compositeViewDescription]];
} else if( [loc_key isEqualToString:@"IC_MSG"] ) {
} else if ([loc_key isEqualToString:@"IC_MSG"]) {
[self fixRing];
}
}
}
}
}
}
}
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
LOGI(@"%@ : %@", NSStringFromSelector(_cmd), userInfo);
LOGI(@"%@ : %@", NSStringFromSelector(_cmd), userInfo);
[self processRemoteNotification:userInfo];
}
- (LinphoneChatRoom*)findChatRoomForContact:(NSString*)contact {
MSList* rooms = linphone_core_get_chat_rooms([LinphoneManager getLc]);
const char* from = [contact UTF8String];
while (rooms) {
const LinphoneAddress* room_from_address = linphone_chat_room_get_peer_address((LinphoneChatRoom*)rooms->data);
char* room_from = linphone_address_as_string_uri_only(room_from_address);
if( room_from && strcmp(from, room_from)== 0){
return rooms->data;
}
rooms = rooms->next;
}
return NULL;
- (LinphoneChatRoom *)findChatRoomForContact:(NSString *)contact {
MSList *rooms = linphone_core_get_chat_rooms([LinphoneManager getLc]);
const char *from = [contact UTF8String];
while (rooms) {
const LinphoneAddress *room_from_address = linphone_chat_room_get_peer_address((LinphoneChatRoom *)rooms->data);
char *room_from = linphone_address_as_string_uri_only(room_from_address);
if (room_from && strcmp(from, room_from) == 0) {
return rooms->data;
}
rooms = rooms->next;
}
return NULL;
}
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
LOGI(@"%@ - state = %ld", NSStringFromSelector(_cmd), (long)application.applicationState);
LOGI(@"%@ - state = %ld", NSStringFromSelector(_cmd), (long)application.applicationState);
[self fixRing];
[self fixRing];
if([notification.userInfo objectForKey:@"callId"] != nil) {
BOOL auto_answer = TRUE;
if ([notification.userInfo objectForKey:@"callId"] != nil) {
BOOL auto_answer = TRUE;
// some local notifications have an internal timer to relaunch themselves at specified intervals
if( [[notification.userInfo objectForKey:@"timer"] intValue] == 1 ){
[[LinphoneManager instance] cancelLocalNotifTimerForCallId:[notification.userInfo objectForKey:@"callId"]];
auto_answer = [[LinphoneManager instance] lpConfigBoolForKey:@"autoanswer_notif_preference"];
}
if(auto_answer)
{
[[LinphoneManager instance] acceptCallForCallId:[notification.userInfo objectForKey:@"callId"]];
}
} else if([notification.userInfo objectForKey:@"from_addr"] != nil) {
NSString *remoteContact = (NSString*)[notification.userInfo objectForKey:@"from_addr"];
// Go to ChatRoom view
[[PhoneMainView instance] changeCurrentView:[ChatViewController compositeViewDescription]];
LinphoneChatRoom*room = [self findChatRoomForContact:remoteContact];
ChatRoomViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ChatRoomViewController compositeViewDescription] push:TRUE], ChatRoomViewController);
if(controller != nil && room != nil) {
[controller setChatRoom:room];
}
} else if([notification.userInfo objectForKey:@"callLog"] != nil) {
NSString *callLog = (NSString*)[notification.userInfo objectForKey:@"callLog"];
// Go to HistoryDetails view
[[PhoneMainView instance] changeCurrentView:[HistoryViewController compositeViewDescription]];
HistoryDetailsViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[HistoryDetailsViewController compositeViewDescription] push:TRUE], HistoryDetailsViewController);
if(controller != nil) {
[controller setCallLogId:callLog];
}
}
// some local notifications have an internal timer to relaunch themselves at specified intervals
if ([[notification.userInfo objectForKey:@"timer"] intValue] == 1) {
[[LinphoneManager instance] cancelLocalNotifTimerForCallId:[notification.userInfo objectForKey:@"callId"]];
auto_answer = [[LinphoneManager instance] lpConfigBoolForKey:@"autoanswer_notif_preference"];
}
if (auto_answer) {
[[LinphoneManager instance] acceptCallForCallId:[notification.userInfo objectForKey:@"callId"]];
}
} else if ([notification.userInfo objectForKey:@"from_addr"] != nil) {
NSString *remoteContact = (NSString *)[notification.userInfo objectForKey:@"from_addr"];
// Go to ChatRoom view
[[PhoneMainView instance] changeCurrentView:[ChatViewController compositeViewDescription]];
LinphoneChatRoom *room = [self findChatRoomForContact:remoteContact];
ChatRoomViewController *controller = DYNAMIC_CAST(
[[PhoneMainView instance] changeCurrentView:[ChatRoomViewController compositeViewDescription] push:TRUE],
ChatRoomViewController);
if (controller != nil && room != nil) {
[controller setChatRoom:room];
}
} else if ([notification.userInfo objectForKey:@"callLog"] != nil) {
NSString *callLog = (NSString *)[notification.userInfo objectForKey:@"callLog"];
// Go to HistoryDetails view
[[PhoneMainView instance] changeCurrentView:[HistoryViewController compositeViewDescription]];
HistoryDetailsViewController *controller = DYNAMIC_CAST(
[[PhoneMainView instance] changeCurrentView:[HistoryDetailsViewController compositeViewDescription]
push:TRUE],
HistoryDetailsViewController);
if (controller != nil) {
[controller setCallLogId:callLog];
}
}
}
// this method is implemented for iOS7. It is invoked when receiving a push notification for a call and it has "content-available" in the aps section.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
LOGI(@"%@ : %@", NSStringFromSelector(_cmd), userInfo);
LinphoneManager* lm = [LinphoneManager instance];
// this method is implemented for iOS7. It is invoked when receiving a push notification for a call and it has
// "content-available" in the aps section.
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
LOGI(@"%@ : %@", NSStringFromSelector(_cmd), userInfo);
LinphoneManager *lm = [LinphoneManager instance];
// save the completion handler for later execution.
// 2 outcomes:
// - if a new call/message is received, the completion handler will be called with "NEWDATA"
// - if nothing happens for 15 seconds, the completion handler will be called with "NODATA"
lm.silentPushCompletion = completionHandler;
[NSTimer scheduledTimerWithTimeInterval:15.0 target:lm selector:@selector(silentPushFailed:) userInfo:nil repeats:FALSE];
// save the completion handler for later execution.
// 2 outcomes:
// - if a new call/message is received, the completion handler will be called with "NEWDATA"
// - if nothing happens for 15 seconds, the completion handler will be called with "NODATA"
lm.silentPushCompletion = completionHandler;
[NSTimer scheduledTimerWithTimeInterval:15.0
target:lm
selector:@selector(silentPushFailed:)
userInfo:nil
repeats:FALSE];
LinphoneCore *lc=[LinphoneManager getLc];
// If no call is yet received at this time, then force Linphone to drop the current socket and make new one to register, so that we get
LinphoneCore *lc = [LinphoneManager getLc];
// If no call is yet received at this time, then force Linphone to drop the current socket and make new one to
// register, so that we get
// a better chance to receive the INVITE.
if (linphone_core_get_calls(lc)==NULL){
if (linphone_core_get_calls(lc) == NULL) {
linphone_core_set_network_reachable(lc, FALSE);
lm.connectivity=none; /*force connectivity to be discovered again*/
lm.connectivity = none; /*force connectivity to be discovered again*/
[lm refreshRegisters];
}
}
#pragma mark - PushNotification Functions
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
LOGI(@"%@ : %@", NSStringFromSelector(_cmd), deviceToken);
[[LinphoneManager instance] setPushNotificationToken:deviceToken];
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
LOGI(@"%@ : %@", NSStringFromSelector(_cmd), deviceToken);
[[LinphoneManager instance] setPushNotificationToken:deviceToken];
}
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error {
LOGI(@"%@ : %@", NSStringFromSelector(_cmd), [error localizedDescription]);
[[LinphoneManager instance] setPushNotificationToken:nil];
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
LOGI(@"%@ : %@", NSStringFromSelector(_cmd), [error localizedDescription]);
[[LinphoneManager instance] setPushNotificationToken:nil];
}
#pragma mark - User notifications
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
LOGI(@"%@", NSStringFromSelector(_cmd));
- (void)application:(UIApplication *)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
LOGI(@"%@", NSStringFromSelector(_cmd));
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler {
LOGI(@"%@", NSStringFromSelector(_cmd));
if( [[UIDevice currentDevice].systemVersion floatValue] >= 8){
- (void)application:(UIApplication *)application
handleActionWithIdentifier:(NSString *)identifier
forLocalNotification:(UILocalNotification *)notification
completionHandler:(void (^)())completionHandler {
LOGI(@"%@", NSStringFromSelector(_cmd));
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8) {
LinphoneCore* lc = [LinphoneManager getLc];
LOGI(@"%@", NSStringFromSelector(_cmd));
if( [notification.category isEqualToString:@"incoming_call"]) {
if( [identifier isEqualToString:@"answer"] ){
// use the standard handler
[self application:application didReceiveLocalNotification:notification];
} else if( [identifier isEqualToString:@"decline"] ){
LinphoneCall* call = linphone_core_get_current_call(lc);
if( call ) linphone_core_decline_call(lc, call, LinphoneReasonDeclined);
}
} else if( [notification.category isEqualToString:@"incoming_msg"] ){
if( [identifier isEqualToString:@"reply"] ){
// use the standard handler
[self application:application didReceiveLocalNotification:notification];
} else if( [identifier isEqualToString:@"mark_read"] ){
NSString* from = [notification.userInfo objectForKey:@"from_addr"];
LinphoneChatRoom* room = linphone_core_get_or_create_chat_room(lc, [from UTF8String]);
if( room ){
linphone_chat_room_mark_as_read(room);
[[PhoneMainView instance] updateApplicationBadgeNumber];
}
}
}
}
completionHandler();
LinphoneCore *lc = [LinphoneManager getLc];
LOGI(@"%@", NSStringFromSelector(_cmd));
if ([notification.category isEqualToString:@"incoming_call"]) {
if ([identifier isEqualToString:@"answer"]) {
// use the standard handler
[self application:application didReceiveLocalNotification:notification];
} else if ([identifier isEqualToString:@"decline"]) {
LinphoneCall *call = linphone_core_get_current_call(lc);
if (call)
linphone_core_decline_call(lc, call, LinphoneReasonDeclined);
}
} else if ([notification.category isEqualToString:@"incoming_msg"]) {
if ([identifier isEqualToString:@"reply"]) {
// use the standard handler
[self application:application didReceiveLocalNotification:notification];
} else if ([identifier isEqualToString:@"mark_read"]) {
NSString *from = [notification.userInfo objectForKey:@"from_addr"];
LinphoneChatRoom *room = linphone_core_get_or_create_chat_room(lc, [from UTF8String]);
if (room) {
linphone_chat_room_mark_as_read(room);
[[PhoneMainView instance] updateApplicationBadgeNumber];
}
}
}
}
completionHandler();
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler {
LOGI(@"%@", NSStringFromSelector(_cmd));
completionHandler();
- (void)application:(UIApplication *)application
handleActionWithIdentifier:(NSString *)identifier
forRemoteNotification:(NSDictionary *)userInfo
completionHandler:(void (^)())completionHandler {
LOGI(@"%@", NSStringFromSelector(_cmd));
completionHandler();
}
#pragma mark - Remote configuration Functions (URL Handler)
- (void)ConfigurationStateUpdateEvent:(NSNotification *)notif {
LinphoneConfiguringState state = [[notif.userInfo objectForKey:@"state"] intValue];
if (state == LinphoneConfiguringSuccessful) {
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneConfiguringStateUpdate object:nil];
[_waitingIndicator dismissWithClickedButtonIndex:0 animated:true];
- (void)ConfigurationStateUpdateEvent: (NSNotification*) notif {
LinphoneConfiguringState state = [[notif.userInfo objectForKey: @"state"] intValue];
if (state == LinphoneConfiguringSuccessful) {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneConfiguringStateUpdate
object:nil];
[_waitingIndicator dismissWithClickedButtonIndex:0 animated:true];
UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Success",nil)
message:NSLocalizedString(@"Remote configuration successfully fetched and applied.",nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK",nil)
otherButtonTitles:nil];
[error show];
[[PhoneMainView instance] startUp];
}
if (state == LinphoneConfiguringFailed) {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneConfiguringStateUpdate
object:nil];
[_waitingIndicator dismissWithClickedButtonIndex:0 animated:true];
UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Failure",nil)
message:NSLocalizedString(@"Failed configuring from the specified URL." ,nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK",nil)
otherButtonTitles:nil];
[error show];
}
UIAlertView *error = [[UIAlertView alloc]
initWithTitle:NSLocalizedString(@"Success", nil)
message:NSLocalizedString(@"Remote configuration successfully fetched and applied.", nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil];
[error show];
[[PhoneMainView instance] startUp];
}
if (state == LinphoneConfiguringFailed) {
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneConfiguringStateUpdate object:nil];
[_waitingIndicator dismissWithClickedButtonIndex:0 animated:true];
UIAlertView *error =
[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Failure", nil)
message:NSLocalizedString(@"Failed configuring from the specified URL.", nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil];
[error show];
}
}
- (void) showWaitingIndicator {
_waitingIndicator = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Fetching remote configuration...",nil) message:@"" delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
UIActivityIndicatorView *progress= [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(125, 60, 30, 30)];
progress.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0){
[_waitingIndicator setValue:progress forKey:@"accessoryView"];
[progress setColor:[UIColor blackColor]];
} else {
[_waitingIndicator addSubview:progress];
}
[progress startAnimating];
[_waitingIndicator show];
- (void)showWaitingIndicator {
_waitingIndicator = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Fetching remote configuration...", nil)
message:@""
delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil];
UIActivityIndicatorView *progress = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(125, 60, 30, 30)];
progress.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
[_waitingIndicator setValue:progress forKey:@"accessoryView"];
[progress setColor:[UIColor blackColor]];
} else {
[_waitingIndicator addSubview:progress];
}
[progress startAnimating];
[_waitingIndicator show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if ((alertView.tag == 1) && (buttonIndex==1)) {
[self showWaitingIndicator];
[self attemptRemoteConfiguration];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if ((alertView.tag == 1) && (buttonIndex == 1)) {
[self showWaitingIndicator];
[self attemptRemoteConfiguration];
}
}
- (void)attemptRemoteConfiguration {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(ConfigurationStateUpdateEvent:)
name:kLinphoneConfiguringStateUpdate
object:nil];
linphone_core_set_provisioning_uri([LinphoneManager getLc] , [configURL UTF8String]);
[[LinphoneManager instance] destroyLinphoneCore];
[[LinphoneManager instance] startLinphoneCore];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(ConfigurationStateUpdateEvent:)
name:kLinphoneConfiguringStateUpdate
object:nil];
linphone_core_set_provisioning_uri([LinphoneManager getLc], [configURL UTF8String]);
[[LinphoneManager instance] destroyLinphoneCore];
[[LinphoneManager instance] startLinphoneCore];
}
@end

File diff suppressed because it is too large Load diff

View file

@ -4,35 +4,35 @@
*
* 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 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* the Free Software Foundation; either version 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "UIAddressTextField.h"
@implementation UIAddressTextField
- (void)setText:(NSString *)text {
[super setText:text];
[self sendActionsForControlEvents:UIControlEventEditingChanged];
[super setText:text];
[self sendActionsForControlEvents:UIControlEventEditingChanged];
}
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender{
// disable "define" option, since it messes with the keyboard
if ([[NSStringFromSelector(action) lowercaseString] rangeOfString:@"define"].location != NSNotFound) {
return NO;
} else {
return [super canPerformAction:action withSender:sender];
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
// disable "define" option, since it messes with the keyboard
if ([[NSStringFromSelector(action) lowercaseString] rangeOfString:@"define"].location != NSNotFound) {
return NO;
} else {
return [super canPerformAction:action withSender:sender];
}
}
@end

View file

@ -4,18 +4,18 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "UIBluetoothButton.h"
#import <AudioToolbox/AudioToolbox.h>
@ -24,47 +24,38 @@
#include "linphone/linphonecore.h"
@implementation UIBluetoothButton
#define check_auresult(au,method) \
if (au!=0) LOGE(@"UIBluetoothButton error for %s: ret=%ld",method,au)
#define check_auresult(au, method) \
if (au != 0) \
LOGE(@"UIBluetoothButton error for %s: ret=%ld", method, au)
- (void)onOn {
//redirect audio to bluetooth
// redirect audio to bluetooth
UInt32 size = sizeof(CFStringRef);
CFStringRef route=CFSTR("HeadsetBT");
CFStringRef route = CFSTR("HeadsetBT");
OSStatus result = AudioSessionSetProperty(kAudioSessionProperty_AudioRoute, size, &route);
check_auresult(result,"set kAudioSessionProperty_AudioRoute HeadsetBT");
int allowBluetoothInput = 1;
result = AudioSessionSetProperty (
kAudioSessionProperty_OverrideCategoryEnableBluetoothInput,
sizeof (allowBluetoothInput),
&allowBluetoothInput
);
check_auresult(result,"set kAudioSessionProperty_OverrideCategoryEnableBluetoothInput 1");
check_auresult(result, "set kAudioSessionProperty_AudioRoute HeadsetBT");
int allowBluetoothInput = 1;
result = AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryEnableBluetoothInput,
sizeof(allowBluetoothInput), &allowBluetoothInput);
check_auresult(result, "set kAudioSessionProperty_OverrideCategoryEnableBluetoothInput 1");
}
- (void)onOff {
//redirect audio to bluetooth
// redirect audio to bluetooth
int allowBluetoothInput = 0;
OSStatus result = AudioSessionSetProperty (
kAudioSessionProperty_OverrideCategoryEnableBluetoothInput,
sizeof (allowBluetoothInput),
&allowBluetoothInput
);
check_auresult(result,"set kAudioSessionProperty_OverrideCategoryEnableBluetoothInput 0");
OSStatus result = AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryEnableBluetoothInput,
sizeof(allowBluetoothInput), &allowBluetoothInput);
check_auresult(result, "set kAudioSessionProperty_OverrideCategoryEnableBluetoothInput 0");
UInt32 size = sizeof(CFStringRef);
CFStringRef route=CFSTR("ReceiverAndMicrophone");
CFStringRef route = CFSTR("ReceiverAndMicrophone");
result = AudioSessionSetProperty(kAudioSessionProperty_AudioRoute, size, &route);
check_auresult(result,"set kAudioSessionProperty_AudioRoute ReceiverAndMicrophone");
check_auresult(result, "set kAudioSessionProperty_AudioRoute ReceiverAndMicrophone");
}
- (bool)onUpdate {
return false;
}
@end

View file

@ -30,5 +30,4 @@
return self;
}
@end

View file

@ -4,18 +4,18 @@
*
* 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 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* the Free Software Foundation; either version 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "UICallBar.h"
#import "LinphoneManager.h"
@ -59,514 +59,522 @@
@synthesize zeroButton;
@synthesize sharpButton;
#pragma mark - Lifecycle Functions
- (id)init {
return [super initWithNibName:@"UICallBar" bundle:[NSBundle mainBundle]];
return [super initWithNibName:@"UICallBar" bundle:[NSBundle mainBundle]];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - ViewController Functions
- (void)viewDidLoad {
[pauseButton setType:UIPauseButtonType_CurrentCall call:nil];
[zeroButton setDigit:'0'];
[zeroButton setDtmf:true];
[oneButton setDigit:'1'];
[oneButton setDtmf:true];
[twoButton setDigit:'2'];
[twoButton setDtmf:true];
[threeButton setDigit:'3'];
[threeButton setDtmf:true];
[fourButton setDigit:'4'];
[fourButton setDtmf:true];
[fiveButton setDigit:'5'];
[fiveButton setDtmf:true];
[sixButton setDigit:'6'];
[sixButton setDtmf:true];
[sevenButton setDigit:'7'];
[sevenButton setDtmf:true];
[eightButton setDigit:'8'];
[eightButton setDtmf:true];
[nineButton setDigit:'9'];
[nineButton setDtmf:true];
[starButton setDigit:'*'];
[starButton setDtmf:true];
[sharpButton setDigit:'#'];
[sharpButton setDtmf:true];
[pauseButton setType:UIPauseButtonType_CurrentCall call:nil];
{
UIButton *videoButtonLandscape = (UIButton*)[landscapeView viewWithTag:[videoButton tag]];
// Set selected+disabled background: IB lack !
[videoButton setBackgroundImage:[UIImage imageNamed:@"video_on_disabled.png"]
forState:(UIControlStateDisabled | UIControlStateSelected)];
[videoButtonLandscape setBackgroundImage:[UIImage imageNamed:@"video_on_disabled_landscape.png"]
forState:(UIControlStateDisabled | UIControlStateSelected)];
// Set selected+over background: IB lack !
[videoButton setBackgroundImage:[UIImage imageNamed:@"video_on_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[videoButtonLandscape setBackgroundImage:[UIImage imageNamed:@"video_on_over_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:videoButton];
[LinphoneUtils buttonFixStates:videoButtonLandscape];
}
[zeroButton setDigit:'0'];
[zeroButton setDtmf:true];
[oneButton setDigit:'1'];
[oneButton setDtmf:true];
[twoButton setDigit:'2'];
[twoButton setDtmf:true];
[threeButton setDigit:'3'];
[threeButton setDtmf:true];
[fourButton setDigit:'4'];
[fourButton setDtmf:true];
[fiveButton setDigit:'5'];
[fiveButton setDtmf:true];
[sixButton setDigit:'6'];
[sixButton setDtmf:true];
[sevenButton setDigit:'7'];
[sevenButton setDtmf:true];
[eightButton setDigit:'8'];
[eightButton setDtmf:true];
[nineButton setDigit:'9'];
[nineButton setDtmf:true];
[starButton setDigit:'*'];
[starButton setDtmf:true];
[sharpButton setDigit:'#'];
[sharpButton setDtmf:true];
{
UIImageView* leftPaddingLandscape = (UIImageView*)[landscapeView viewWithTag:self.leftPadding.tag];
leftPaddingLandscape.image =[UIImage imageNamed:@"incall_padding_left_landscape.png"];
}
{
UIImageView* rightPaddingLandscape = (UIImageView*)[landscapeView viewWithTag:self.rightPadding.tag];
rightPaddingLandscape.image = [UIImage imageNamed:@"incall_padding_right_landscape.png"];
}
{
UIButton *videoButtonLandscape = (UIButton *)[landscapeView viewWithTag:[videoButton tag]];
// Set selected+disabled background: IB lack !
[videoButton setBackgroundImage:[UIImage imageNamed:@"video_on_disabled.png"]
forState:(UIControlStateDisabled | UIControlStateSelected)];
[videoButtonLandscape setBackgroundImage:[UIImage imageNamed:@"video_on_disabled_landscape.png"]
forState:(UIControlStateDisabled | UIControlStateSelected)];
{
UIButton *speakerButtonLandscape = (UIButton*) [landscapeView viewWithTag:[speakerButton tag]];
// Set selected+disabled background: IB lack !
[speakerButton setBackgroundImage:[UIImage imageNamed:@"speaker_on_disabled.png"]
forState:(UIControlStateDisabled | UIControlStateSelected)];
[speakerButtonLandscape setBackgroundImage:[UIImage imageNamed:@"speaker_on_disabled_landscape.png"]
forState:(UIControlStateDisabled | UIControlStateSelected)];
// Set selected+over background: IB lack !
[speakerButton setBackgroundImage:[UIImage imageNamed:@"speaker_on_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[speakerButtonLandscape setBackgroundImage:[UIImage imageNamed:@"speaker_on_over_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:speakerButton];
[LinphoneUtils buttonFixStates:speakerButtonLandscape];
}
if (![LinphoneManager runningOnIpad]) {
UIButton *routesButtonLandscape = (UIButton*) [landscapeView viewWithTag:[routesButton tag]];
// Set selected+over background: IB lack !
[routesButton setBackgroundImage:[UIImage imageNamed:@"routes_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[routesButtonLandscape setBackgroundImage:[UIImage imageNamed:@"routes_over_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:routesButton];
[LinphoneUtils buttonFixStates:routesButtonLandscape];
}
{
UIButton *microButtonLandscape = (UIButton*) [landscapeView viewWithTag:[microButton tag]];
// Set selected+disabled background: IB lack !
[microButton setBackgroundImage:[UIImage imageNamed:@"micro_on_disabled.png"]
forState:(UIControlStateDisabled | UIControlStateSelected)];
[microButtonLandscape setBackgroundImage:[UIImage imageNamed:@"micro_on_disabled_landscape.png"]
forState:(UIControlStateDisabled | UIControlStateSelected)];
// Set selected+over background: IB lack !
[microButton setBackgroundImage:[UIImage imageNamed:@"micro_on_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[microButtonLandscape setBackgroundImage:[UIImage imageNamed:@"micro_on_over_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:microButton];
[LinphoneUtils buttonFixStates:microButtonLandscape];
}
{
UIButton *optionsButtonLandscape = (UIButton*) [landscapeView viewWithTag:[optionsButton tag]];
// Set selected+over background: IB lack !
[optionsButton setBackgroundImage:[UIImage imageNamed:@"options_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[optionsButtonLandscape setBackgroundImage:[UIImage imageNamed:@"options_over_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:optionsButton];
[LinphoneUtils buttonFixStates:optionsButtonLandscape];
}
{
UIButton *pauseButtonLandscape = (UIButton*) [landscapeView viewWithTag:[pauseButton tag]];
// Set selected+over background: IB lack !
[pauseButton setBackgroundImage:[UIImage imageNamed:@"pause_on_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[pauseButtonLandscape setBackgroundImage:[UIImage imageNamed:@"pause_on_over_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:pauseButton];
[LinphoneUtils buttonFixStates:pauseButtonLandscape];
}
{
UIButton *dialerButtonLandscape = (UIButton*) [landscapeView viewWithTag:[dialerButton tag]] ;
// Set selected+over background: IB lack !
[dialerButton setBackgroundImage:[UIImage imageNamed:@"dialer_alt_back_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[dialerButtonLandscape setBackgroundImage:[UIImage imageNamed:@"dialer_alt_back_over_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:dialerButton];
[LinphoneUtils buttonFixStates:dialerButtonLandscape];
}
[super viewDidLoad];
// Set selected+over background: IB lack !
[videoButton setBackgroundImage:[UIImage imageNamed:@"video_on_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[videoButtonLandscape setBackgroundImage:[UIImage imageNamed:@"video_on_over_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:videoButton];
[LinphoneUtils buttonFixStates:videoButtonLandscape];
}
{
UIImageView *leftPaddingLandscape = (UIImageView *)[landscapeView viewWithTag:self.leftPadding.tag];
leftPaddingLandscape.image = [UIImage imageNamed:@"incall_padding_left_landscape.png"];
}
{
UIImageView *rightPaddingLandscape = (UIImageView *)[landscapeView viewWithTag:self.rightPadding.tag];
rightPaddingLandscape.image = [UIImage imageNamed:@"incall_padding_right_landscape.png"];
}
{
UIButton *speakerButtonLandscape = (UIButton *)[landscapeView viewWithTag:[speakerButton tag]];
// Set selected+disabled background: IB lack !
[speakerButton setBackgroundImage:[UIImage imageNamed:@"speaker_on_disabled.png"]
forState:(UIControlStateDisabled | UIControlStateSelected)];
[speakerButtonLandscape setBackgroundImage:[UIImage imageNamed:@"speaker_on_disabled_landscape.png"]
forState:(UIControlStateDisabled | UIControlStateSelected)];
// Set selected+over background: IB lack !
[speakerButton setBackgroundImage:[UIImage imageNamed:@"speaker_on_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[speakerButtonLandscape setBackgroundImage:[UIImage imageNamed:@"speaker_on_over_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:speakerButton];
[LinphoneUtils buttonFixStates:speakerButtonLandscape];
}
if (![LinphoneManager runningOnIpad]) {
UIButton *routesButtonLandscape = (UIButton *)[landscapeView viewWithTag:[routesButton tag]];
// Set selected+over background: IB lack !
[routesButton setBackgroundImage:[UIImage imageNamed:@"routes_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[routesButtonLandscape setBackgroundImage:[UIImage imageNamed:@"routes_over_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:routesButton];
[LinphoneUtils buttonFixStates:routesButtonLandscape];
}
{
UIButton *microButtonLandscape = (UIButton *)[landscapeView viewWithTag:[microButton tag]];
// Set selected+disabled background: IB lack !
[microButton setBackgroundImage:[UIImage imageNamed:@"micro_on_disabled.png"]
forState:(UIControlStateDisabled | UIControlStateSelected)];
[microButtonLandscape setBackgroundImage:[UIImage imageNamed:@"micro_on_disabled_landscape.png"]
forState:(UIControlStateDisabled | UIControlStateSelected)];
// Set selected+over background: IB lack !
[microButton setBackgroundImage:[UIImage imageNamed:@"micro_on_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[microButtonLandscape setBackgroundImage:[UIImage imageNamed:@"micro_on_over_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:microButton];
[LinphoneUtils buttonFixStates:microButtonLandscape];
}
{
UIButton *optionsButtonLandscape = (UIButton *)[landscapeView viewWithTag:[optionsButton tag]];
// Set selected+over background: IB lack !
[optionsButton setBackgroundImage:[UIImage imageNamed:@"options_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[optionsButtonLandscape setBackgroundImage:[UIImage imageNamed:@"options_over_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:optionsButton];
[LinphoneUtils buttonFixStates:optionsButtonLandscape];
}
{
UIButton *pauseButtonLandscape = (UIButton *)[landscapeView viewWithTag:[pauseButton tag]];
// Set selected+over background: IB lack !
[pauseButton setBackgroundImage:[UIImage imageNamed:@"pause_on_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[pauseButtonLandscape setBackgroundImage:[UIImage imageNamed:@"pause_on_over_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:pauseButton];
[LinphoneUtils buttonFixStates:pauseButtonLandscape];
}
{
UIButton *dialerButtonLandscape = (UIButton *)[landscapeView viewWithTag:[dialerButton tag]];
// Set selected+over background: IB lack !
[dialerButton setBackgroundImage:[UIImage imageNamed:@"dialer_alt_back_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[dialerButtonLandscape setBackgroundImage:[UIImage imageNamed:@"dialer_alt_back_over_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:dialerButton];
[LinphoneUtils buttonFixStates:dialerButtonLandscape];
}
[super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(callUpdateEvent:)
name:kLinphoneCallUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(bluetoothAvailabilityUpdateEvent:)
name:kLinphoneBluetoothAvailabilityUpdate
object:nil];
// Update on show
LinphoneCall* call = linphone_core_get_current_call([LinphoneManager getLc]);
LinphoneCallState state = (call != NULL)?linphone_call_get_state(call): 0;
[self callUpdate:call state:state];
[self hideRoutes:FALSE];
[self hideOptions:FALSE];
[self hidePad:FALSE];
[self showSpeaker];
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(callUpdateEvent:)
name:kLinphoneCallUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(bluetoothAvailabilityUpdateEvent:)
name:kLinphoneBluetoothAvailabilityUpdate
object:nil];
// Update on show
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
LinphoneCallState state = (call != NULL) ? linphone_call_get_state(call) : 0;
[self callUpdate:call state:state];
[self hideRoutes:FALSE];
[self hideOptions:FALSE];
[self hidePad:FALSE];
[self showSpeaker];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneCallUpdate
object:nil];
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneCallUpdate object:nil];
if (linphone_core_get_calls_nb([LinphoneManager getLc]) == 0) {
//reseting speaker button because no more call
speakerButton.selected=FALSE;
// reseting speaker button because no more call
speakerButton.selected = FALSE;
}
}
#pragma mark - Event Functions
- (void)callUpdateEvent:(NSNotification*)notif {
LinphoneCall *call = [[notif.userInfo objectForKey: @"call"] pointerValue];
LinphoneCallState state = [[notif.userInfo objectForKey: @"state"] intValue];
[self callUpdate:call state:state];
- (void)callUpdateEvent:(NSNotification *)notif {
LinphoneCall *call = [[notif.userInfo objectForKey:@"call"] pointerValue];
LinphoneCallState state = [[notif.userInfo objectForKey:@"state"] intValue];
[self callUpdate:call state:state];
}
- (void)bluetoothAvailabilityUpdateEvent:(NSNotification*)notif {
bool available = [[notif.userInfo objectForKey:@"available"] intValue];
[self bluetoothAvailabilityUpdate:available];
- (void)bluetoothAvailabilityUpdateEvent:(NSNotification *)notif {
bool available = [[notif.userInfo objectForKey:@"available"] intValue];
[self bluetoothAvailabilityUpdate:available];
}
#pragma mark -
- (void)callUpdate:(LinphoneCall*)call state:(LinphoneCallState)state {
LinphoneCore* lc = [LinphoneManager getLc];
[speakerButton update];
[microButton update];
[pauseButton update];
[videoButton update];
[hangupButton update];
// Show Pause/Conference button following call count
if(linphone_core_get_calls_nb(lc) > 1) {
if(![pauseButton isHidden]) {
[pauseButton setHidden:true];
[conferenceButton setHidden:false];
}
bool enabled = true;
const MSList *list = linphone_core_get_calls(lc);
while(list != NULL) {
LinphoneCall *call = (LinphoneCall*) list->data;
LinphoneCallState state = linphone_call_get_state(call);
if(state == LinphoneCallIncomingReceived ||
state == LinphoneCallOutgoingInit ||
state == LinphoneCallOutgoingProgress ||
state == LinphoneCallOutgoingRinging ||
state == LinphoneCallOutgoingEarlyMedia ||
state == LinphoneCallConnected) {
enabled = false;
}
list = list->next;
}
[conferenceButton setEnabled:enabled];
} else {
if([pauseButton isHidden]) {
[pauseButton setHidden:false];
[conferenceButton setHidden:true];
}
}
// Disable transfert in conference
if(linphone_core_get_current_call(lc) == NULL) {
[optionsTransferButton setEnabled:FALSE];
} else {
[optionsTransferButton setEnabled:TRUE];
}
switch(state) {
case LinphoneCallEnd:
case LinphoneCallError:
case LinphoneCallIncoming:
case LinphoneCallOutgoing:
[self hidePad:TRUE];
[self hideOptions:TRUE];
[self hideRoutes:TRUE];
default:
break;
}
}
- (void)bluetoothAvailabilityUpdate:(bool)available {
if (available) {
[self hideSpeaker];
} else {
[self showSpeaker];
}
}
#pragma mark -
- (void)showAnimation:(NSString*)animationID target:(UIView*)target completion:(void (^)(BOOL finished))completion {
CGRect frame = [target frame];
int original_y = frame.origin.y;
frame.origin.y = [[self view] frame].size.height;
[target setFrame:frame];
[target setHidden:FALSE];
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
CGRect frame = [target frame];
frame.origin.y = original_y;
[target setFrame:frame];
}
completion:^(BOOL finished){
CGRect frame = [target frame];
frame.origin.y = original_y;
[target setFrame:frame];
completion(finished);
}];
- (void)callUpdate:(LinphoneCall *)call state:(LinphoneCallState)state {
LinphoneCore *lc = [LinphoneManager getLc];
[speakerButton update];
[microButton update];
[pauseButton update];
[videoButton update];
[hangupButton update];
// Show Pause/Conference button following call count
if (linphone_core_get_calls_nb(lc) > 1) {
if (![pauseButton isHidden]) {
[pauseButton setHidden:true];
[conferenceButton setHidden:false];
}
bool enabled = true;
const MSList *list = linphone_core_get_calls(lc);
while (list != NULL) {
LinphoneCall *call = (LinphoneCall *)list->data;
LinphoneCallState state = linphone_call_get_state(call);
if (state == LinphoneCallIncomingReceived || state == LinphoneCallOutgoingInit ||
state == LinphoneCallOutgoingProgress || state == LinphoneCallOutgoingRinging ||
state == LinphoneCallOutgoingEarlyMedia || state == LinphoneCallConnected) {
enabled = false;
}
list = list->next;
}
[conferenceButton setEnabled:enabled];
} else {
if ([pauseButton isHidden]) {
[pauseButton setHidden:false];
[conferenceButton setHidden:true];
}
}
// Disable transfert in conference
if (linphone_core_get_current_call(lc) == NULL) {
[optionsTransferButton setEnabled:FALSE];
} else {
[optionsTransferButton setEnabled:TRUE];
}
switch (state) {
case LinphoneCallEnd:
case LinphoneCallError:
case LinphoneCallIncoming:
case LinphoneCallOutgoing:
[self hidePad:TRUE];
[self hideOptions:TRUE];
[self hideRoutes:TRUE];
default:
break;
}
}
- (void)hideAnimation:(NSString*)animationID target:(UIView*)target completion:(void (^)(BOOL finished))completion {
CGRect frame = [target frame];
int original_y = frame.origin.y;
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
CGRect frame = [target frame];
frame.origin.y = [[self view] frame].size.height;
[target setFrame:frame];
}
completion:^(BOOL finished){
CGRect frame = [target frame];
frame.origin.y = original_y;
[target setHidden:TRUE];
[target setFrame:frame];
completion(finished);
}];
- (void)bluetoothAvailabilityUpdate:(bool)available {
if (available) {
[self hideSpeaker];
} else {
[self showSpeaker];
}
}
#pragma mark -
- (void)showAnimation:(NSString *)animationID target:(UIView *)target completion:(void (^)(BOOL finished))completion {
CGRect frame = [target frame];
int original_y = frame.origin.y;
frame.origin.y = [[self view] frame].size.height;
[target setFrame:frame];
[target setHidden:FALSE];
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
CGRect frame = [target frame];
frame.origin.y = original_y;
[target setFrame:frame];
}
completion:^(BOOL finished) {
CGRect frame = [target frame];
frame.origin.y = original_y;
[target setFrame:frame];
completion(finished);
}];
}
- (void)hideAnimation:(NSString *)animationID target:(UIView *)target completion:(void (^)(BOOL finished))completion {
CGRect frame = [target frame];
int original_y = frame.origin.y;
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
CGRect frame = [target frame];
frame.origin.y = [[self view] frame].size.height;
[target setFrame:frame];
}
completion:^(BOOL finished) {
CGRect frame = [target frame];
frame.origin.y = original_y;
[target setHidden:TRUE];
[target setFrame:frame];
completion(finished);
}];
}
- (void)showPad:(BOOL)animated {
[dialerButton setOn];
if([padView isHidden]) {
if(animated) {
[self showAnimation:@"show" target:padView completion:^(BOOL finished){}];
} else {
[padView setHidden:FALSE];
}
}
[dialerButton setOn];
if ([padView isHidden]) {
if (animated) {
[self showAnimation:@"show"
target:padView
completion:^(BOOL finished){
}];
} else {
[padView setHidden:FALSE];
}
}
}
- (void)hidePad:(BOOL)animated {
[dialerButton setOff];
if(![padView isHidden]) {
if(animated) {
[self hideAnimation:@"hide" target:padView completion:^(BOOL finished){}];
} else {
[padView setHidden:TRUE];
}
}
[dialerButton setOff];
if (![padView isHidden]) {
if (animated) {
[self hideAnimation:@"hide"
target:padView
completion:^(BOOL finished){
}];
} else {
[padView setHidden:TRUE];
}
}
}
- (void)showRoutes:(BOOL)animated {
if (![LinphoneManager runningOnIpad]) {
[routesButton setOn];
[routesBluetoothButton setSelected:[[LinphoneManager instance] bluetoothEnabled]];
[routesSpeakerButton setSelected:[[LinphoneManager instance] speakerEnabled]];
[routesReceiverButton setSelected:!([[LinphoneManager instance] bluetoothEnabled] || [[LinphoneManager instance] speakerEnabled])];
if([routesView isHidden]) {
if(animated) {
[self showAnimation:@"show" target:routesView completion:^(BOOL finished){}];
} else {
[routesView setHidden:FALSE];
}
}
}
if (![LinphoneManager runningOnIpad]) {
[routesButton setOn];
[routesBluetoothButton setSelected:[[LinphoneManager instance] bluetoothEnabled]];
[routesSpeakerButton setSelected:[[LinphoneManager instance] speakerEnabled]];
[routesReceiverButton setSelected:!([[LinphoneManager instance] bluetoothEnabled] ||
[[LinphoneManager instance] speakerEnabled])];
if ([routesView isHidden]) {
if (animated) {
[self showAnimation:@"show"
target:routesView
completion:^(BOOL finished){
}];
} else {
[routesView setHidden:FALSE];
}
}
}
}
- (void)hideRoutes:(BOOL)animated {
if (![LinphoneManager runningOnIpad]) {
[routesButton setOff];
if(![routesView isHidden]) {
if(animated) {
[self hideAnimation:@"hide" target:routesView completion:^(BOOL finished){}];
} else {
[routesView setHidden:TRUE];
}
}
}
if (![LinphoneManager runningOnIpad]) {
[routesButton setOff];
if (![routesView isHidden]) {
if (animated) {
[self hideAnimation:@"hide"
target:routesView
completion:^(BOOL finished){
}];
} else {
[routesView setHidden:TRUE];
}
}
}
}
- (void)showOptions:(BOOL)animated {
[optionsButton setOn];
if([optionsView isHidden]) {
if(animated) {
[self showAnimation:@"show" target:optionsView completion:^(BOOL finished){}];
} else {
[optionsView setHidden:FALSE];
}
}
[optionsButton setOn];
if ([optionsView isHidden]) {
if (animated) {
[self showAnimation:@"show"
target:optionsView
completion:^(BOOL finished){
}];
} else {
[optionsView setHidden:FALSE];
}
}
}
- (void)hideOptions:(BOOL)animated {
[optionsButton setOff];
if(![optionsView isHidden]) {
if(animated) {
[self hideAnimation:@"hide" target:optionsView completion:^(BOOL finished){}];
} else {
[optionsView setHidden:TRUE];
}
}
[optionsButton setOff];
if (![optionsView isHidden]) {
if (animated) {
[self hideAnimation:@"hide"
target:optionsView
completion:^(BOOL finished){
}];
} else {
[optionsView setHidden:TRUE];
}
}
}
- (void)showSpeaker {
if (![LinphoneManager runningOnIpad]) {
[speakerButton setHidden:FALSE];
[routesButton setHidden:TRUE];
}
if (![LinphoneManager runningOnIpad]) {
[speakerButton setHidden:FALSE];
[routesButton setHidden:TRUE];
}
}
- (void)hideSpeaker {
if (![LinphoneManager runningOnIpad]) {
[speakerButton setHidden:TRUE];
[routesButton setHidden:FALSE];
}
if (![LinphoneManager runningOnIpad]) {
[speakerButton setHidden:TRUE];
[routesButton setHidden:FALSE];
}
}
#pragma mark - Action Functions
- (IBAction)onPadClick:(id)sender {
if([padView isHidden]) {
[self showPad:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
} else {
[self hidePad:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
}
if ([padView isHidden]) {
[self showPad:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
} else {
[self hidePad:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
}
}
- (IBAction)onRoutesBluetoothClick:(id)sender {
[self hideRoutes:TRUE];
[[LinphoneManager instance] setBluetoothEnabled:TRUE];
[self hideRoutes:TRUE];
[[LinphoneManager instance] setBluetoothEnabled:TRUE];
}
- (IBAction)onRoutesReceiverClick:(id)sender {
[self hideRoutes:TRUE];
[[LinphoneManager instance] setSpeakerEnabled:FALSE];
[[LinphoneManager instance] setBluetoothEnabled:FALSE];
[self hideRoutes:TRUE];
[[LinphoneManager instance] setSpeakerEnabled:FALSE];
[[LinphoneManager instance] setBluetoothEnabled:FALSE];
}
- (IBAction)onRoutesSpeakerClick:(id)sender {
[self hideRoutes:TRUE];
[[LinphoneManager instance] setSpeakerEnabled:TRUE];
[self hideRoutes:TRUE];
[[LinphoneManager instance] setSpeakerEnabled:TRUE];
}
- (IBAction)onRoutesClick:(id)sender {
if([routesView isHidden]) {
[self showRoutes:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
} else {
[self hideRoutes:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
}
if ([routesView isHidden]) {
[self showRoutes:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
} else {
[self hideRoutes:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
}
}
- (IBAction)onOptionsTransferClick:(id)sender {
[self hideOptions:TRUE];
// Go to dialer view
DialerViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]], DialerViewController);
if(controller != nil) {
[controller setAddress:@""];
[controller setTransferMode:TRUE];
}
[self hideOptions:TRUE];
// Go to dialer view
DialerViewController *controller =
DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]],
DialerViewController);
if (controller != nil) {
[controller setAddress:@""];
[controller setTransferMode:TRUE];
}
}
- (IBAction)onOptionsAddClick:(id)sender {
[self hideOptions:TRUE];
// Go to dialer view
DialerViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]], DialerViewController);
if(controller != nil) {
[controller setAddress:@""];
[controller setTransferMode:FALSE];
}
[self hideOptions:TRUE];
// Go to dialer view
DialerViewController *controller =
DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]],
DialerViewController);
if (controller != nil) {
[controller setAddress:@""];
[controller setTransferMode:FALSE];
}
}
- (IBAction)onOptionsClick:(id)sender {
if([optionsView isHidden]) {
[self showOptions:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
} else {
[self hideOptions:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
}
if ([optionsView isHidden]) {
[self showOptions:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
} else {
[self hideOptions:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
}
}
- (IBAction)onConferenceClick:(id)sender {
linphone_core_add_all_to_conference([LinphoneManager getLc]);
linphone_core_add_all_to_conference([LinphoneManager getLc]);
}
#pragma mark - TPMultiLayoutViewController Functions
- (NSDictionary*)attributesForView:(UIView*)view {
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
- (NSDictionary *)attributesForView:(UIView *)view {
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
[attributes setObject:[NSValue valueWithCGRect:view.frame] forKey:@"frame"];
[attributes setObject:[NSValue valueWithCGRect:view.bounds] forKey:@"bounds"];
if([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)view;
[attributes setObject:[NSValue valueWithCGRect:view.frame] forKey:@"frame"];
[attributes setObject:[NSValue valueWithCGRect:view.bounds] forKey:@"bounds"];
if ([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)view;
[LinphoneUtils buttonMultiViewAddAttributes:attributes button:button];
} else if (view.tag ==self.leftPadding.tag || view.tag == self.rightPadding.tag){
UIImage* image = [(UIImageView*)view image];
if( image ){
} else if (view.tag == self.leftPadding.tag || view.tag == self.rightPadding.tag) {
UIImage *image = [(UIImageView *)view image];
if (image) {
[attributes setObject:image forKey:@"image"];
}
}
[attributes setObject:[NSNumber numberWithInteger:view.autoresizingMask] forKey:@"autoresizingMask"];
}
[attributes setObject:[NSNumber numberWithInteger:view.autoresizingMask] forKey:@"autoresizingMask"];
return attributes;
return attributes;
}
- (void)applyAttributes:(NSDictionary*)attributes toView:(UIView*)view {
view.frame = [[attributes objectForKey:@"frame"] CGRectValue];
view.bounds = [[attributes objectForKey:@"bounds"] CGRectValue];
if([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)view;
[LinphoneUtils buttonMultiViewApplyAttributes:attributes button:button];
} else if (view.tag ==self.leftPadding.tag || view.tag == self.rightPadding.tag){
- (void)applyAttributes:(NSDictionary *)attributes toView:(UIView *)view {
view.frame = [[attributes objectForKey:@"frame"] CGRectValue];
view.bounds = [[attributes objectForKey:@"bounds"] CGRectValue];
if ([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)view;
[LinphoneUtils buttonMultiViewApplyAttributes:attributes button:button];
} else if (view.tag == self.leftPadding.tag || view.tag == self.rightPadding.tag) {
[(UIImageView*)view setImage:[attributes objectForKey:@"image"]];
}
view.autoresizingMask = [[attributes objectForKey:@"autoresizingMask"] integerValue];
[(UIImageView *)view setImage:[attributes objectForKey:@"image"]];
}
view.autoresizingMask = [[attributes objectForKey:@"autoresizingMask"] integerValue];
}
@end

View file

@ -4,18 +4,18 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "UICallButton.h"
#import "LinphoneManager.h"
@ -26,85 +26,82 @@
@synthesize addressField;
#pragma mark - Lifecycle Functions
- (void)initUICallButton {
[self addTarget:self action:@selector(touchUp:) forControlEvents:UIControlEventTouchUpInside];
[self addTarget:self action:@selector(touchUp:) forControlEvents:UIControlEventTouchUpInside];
}
- (id)init {
self = [super init];
if (self) {
self = [super init];
if (self) {
[self initUICallButton];
}
return self;
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self = [super initWithFrame:frame];
if (self) {
[self initUICallButton];
}
return self;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
self = [super initWithCoder:decoder];
if (self) {
[self initUICallButton];
}
return self;
}
return self;
}
#pragma mark -
- (void)touchUp:(id) sender {
NSString *address = [addressField text];
NSString *displayName = nil;
- (void)touchUp:(id)sender {
NSString *address = [addressField text];
NSString *displayName = nil;
if( [address length] == 0){
const MSList* logs = linphone_core_get_call_logs([LinphoneManager getLc]);
while( logs ){
LinphoneCallLog* log = logs->data;
if( linphone_call_log_get_dir(log) == LinphoneCallOutgoing ){
LinphoneProxyConfig* def_proxy = NULL;
LinphoneAddress* to = linphone_call_log_get_to(log);
const char* domain = linphone_address_get_domain(to);
char* bis_address = NULL;
if ([address length] == 0) {
const MSList *logs = linphone_core_get_call_logs([LinphoneManager getLc]);
while (logs) {
LinphoneCallLog *log = logs->data;
if (linphone_call_log_get_dir(log) == LinphoneCallOutgoing) {
LinphoneProxyConfig *def_proxy = NULL;
LinphoneAddress *to = linphone_call_log_get_to(log);
const char *domain = linphone_address_get_domain(to);
char *bis_address = NULL;
linphone_core_get_default_proxy([LinphoneManager getLc], &def_proxy);
linphone_core_get_default_proxy([LinphoneManager getLc], &def_proxy);
// if the 'to' address is on the default proxy, only present the username
if( def_proxy ){
const char* def_domain = linphone_proxy_config_get_domain(def_proxy);
if( def_domain && domain && !strcmp(domain, def_domain) ){
bis_address = ms_strdup(linphone_address_get_username(to));
}
}
// if the 'to' address is on the default proxy, only present the username
if (def_proxy) {
const char *def_domain = linphone_proxy_config_get_domain(def_proxy);
if (def_domain && domain && !strcmp(domain, def_domain)) {
bis_address = ms_strdup(linphone_address_get_username(to));
}
}
if( bis_address == NULL ) {
bis_address = linphone_address_as_string_uri_only(to);
}
if (bis_address == NULL) {
bis_address = linphone_address_as_string_uri_only(to);
}
[addressField setText:[NSString stringWithUTF8String:bis_address]];
ms_free(bis_address);
// return after filling the address, let the user confirm the call by pressing again
return;
}
logs = ms_list_next(logs);
}
}
[addressField setText:[NSString stringWithUTF8String:bis_address]];
ms_free(bis_address);
// return after filling the address, let the user confirm the call by pressing again
return;
}
logs = ms_list_next(logs);
}
}
if( [address length] > 0){
ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:address];
if(contact) {
displayName = [FastAddressBook getContactDisplayName:contact];
}
[[LinphoneManager instance] call:address displayName:displayName transfer:FALSE];
}
if ([address length] > 0) {
ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:address];
if (contact) {
displayName = [FastAddressBook getContactDisplayName:contact];
}
[[LinphoneManager instance] call:address displayName:displayName transfer:FALSE];
}
}
@end

View file

@ -29,60 +29,60 @@
@synthesize address;
@synthesize image;
- (id)init:(LinphoneCall*)acall minimized:(BOOL)minimized{
self = [super init];
if(self != nil) {
self->minimize = minimized;
self->view = UICallCellOtherView_Avatar;
self->call = acall;
image = [UIImage imageNamed:@"avatar_unknown.png"];
address = NSLocalizedString(@"Unknown",nil);
[self update];
}
return self;
- (id)init:(LinphoneCall *)acall minimized:(BOOL)minimized {
self = [super init];
if (self != nil) {
self->minimize = minimized;
self->view = UICallCellOtherView_Avatar;
self->call = acall;
image = [UIImage imageNamed:@"avatar_unknown.png"];
address = NSLocalizedString(@"Unknown", nil);
[self update];
}
return self;
}
- (void)update {
if(call == NULL) {
LOGW(@"Cannot update call cell: null call or data");
return;
}
const LinphoneAddress* addr = linphone_call_get_remote_address(call);
if (call == NULL) {
LOGW(@"Cannot update call cell: null call or data");
return;
}
const LinphoneAddress *addr = linphone_call_get_remote_address(call);
if(addr != NULL) {
BOOL useLinphoneAddress = true;
// contact name
char* lAddress = linphone_address_as_string_uri_only(addr);
if(lAddress) {
NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:[NSString stringWithUTF8String:lAddress]];
ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:normalizedSipAddress];
if(contact) {
useLinphoneAddress = false;
self.address = [FastAddressBook getContactDisplayName:contact];
UIImage *tmpImage = [FastAddressBook getContactImage:contact thumbnail:false];
if(tmpImage != nil) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void) {
UIImage *tmpImage2 = [UIImage decodedImageWithImage:tmpImage];
dispatch_async(dispatch_get_main_queue(), ^{
[self setImage: tmpImage2];
});
});
}
}
ms_free(lAddress);
}
if(useLinphoneAddress) {
const char* lDisplayName = linphone_address_get_display_name(addr);
const char* lUserName = linphone_address_get_username(addr);
if (lDisplayName)
self.address = [NSString stringWithUTF8String:lDisplayName];
else if(lUserName)
self.address = [NSString stringWithUTF8String:lUserName];
}
}
if (addr != NULL) {
BOOL useLinphoneAddress = true;
// contact name
char *lAddress = linphone_address_as_string_uri_only(addr);
if (lAddress) {
NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:[NSString stringWithUTF8String:lAddress]];
ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:normalizedSipAddress];
if (contact) {
useLinphoneAddress = false;
self.address = [FastAddressBook getContactDisplayName:contact];
UIImage *tmpImage = [FastAddressBook getContactImage:contact thumbnail:false];
if (tmpImage != nil) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL),
^(void) {
UIImage *tmpImage2 = [UIImage decodedImageWithImage:tmpImage];
dispatch_async(dispatch_get_main_queue(), ^{
[self setImage:tmpImage2];
});
});
}
}
ms_free(lAddress);
}
if (useLinphoneAddress) {
const char *lDisplayName = linphone_address_get_display_name(addr);
const char *lUserName = linphone_address_get_username(addr);
if (lDisplayName)
self.address = [NSString stringWithUTF8String:lDisplayName];
else if (lUserName)
self.address = [NSString stringWithUTF8String:lUserName];
}
}
}
@end
@implementation UICallCell
@ -131,107 +131,92 @@
@synthesize detailsLeftSwipeGestureRecognizer;
@synthesize detailsRightSwipeGestureRecognizer;
#pragma mark - Lifecycle Functions
- (id)initWithIdentifier:(NSString*)identifier {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"UICallCell"
owner:self
options:nil];
- (id)initWithIdentifier:(NSString *)identifier {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"UICallCell" owner:self options:nil];
if ([arrayOfViews count] >= 1) {
//resize cell to match .nib size. It is needed when resized the cell to
//correctly adapt its height too
UIView *sub = ((UIView*)[arrayOfViews objectAtIndex:0]);
if ([arrayOfViews count] >= 1) {
// resize cell to match .nib size. It is needed when resized the cell to
// correctly adapt its height too
UIView *sub = ((UIView *)[arrayOfViews objectAtIndex:0]);
[self setFrame:CGRectMake(0, 0, sub.frame.size.width, sub.frame.size.height)];
[self addSubview:sub];
}
// Set selected+over background: IB lack !
[pauseButton setImage:[UIImage imageNamed:@"call_state_pause_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[self addSubview:sub];
}
// Set selected+over background: IB lack !
[pauseButton setImage:[UIImage imageNamed:@"call_state_pause_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
self->currentCall = FALSE;
self->currentCall = FALSE;
self->detailsRightSwipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(doDetailsSwipe:)];
[detailsRightSwipeGestureRecognizer setDirection:UISwipeGestureRecognizerDirectionLeft];
[otherView addGestureRecognizer:detailsRightSwipeGestureRecognizer];
self->detailsRightSwipeGestureRecognizer =
[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(doDetailsSwipe:)];
[detailsRightSwipeGestureRecognizer setDirection:UISwipeGestureRecognizerDirectionLeft];
[otherView addGestureRecognizer:detailsRightSwipeGestureRecognizer];
self->detailsRightSwipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(doDetailsSwipe:)];
[detailsRightSwipeGestureRecognizer setDirection:UISwipeGestureRecognizerDirectionRight];
[otherView addGestureRecognizer:detailsRightSwipeGestureRecognizer];
self->detailsRightSwipeGestureRecognizer =
[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(doDetailsSwipe:)];
[detailsRightSwipeGestureRecognizer setDirection:UISwipeGestureRecognizerDirectionRight];
[otherView addGestureRecognizer:detailsRightSwipeGestureRecognizer];
[self->avatarView setHidden:TRUE];
[self->audioStatsView setHidden:TRUE];
[self->videoStatsView setHidden:TRUE];
[self->avatarView setHidden:TRUE];
[self->audioStatsView setHidden:TRUE];
[self->videoStatsView setHidden:TRUE];
[UICallCell adaptSize:audioCodecHeaderLabel field:audioCodecLabel];
[UICallCell adaptSize:audioDownloadBandwidthHeaderLabel field:audioDownloadBandwidthLabel];
[UICallCell adaptSize:audioUploadBandwidthHeaderLabel field:audioUploadBandwidthLabel];
[UICallCell adaptSize:audioIceConnectivityHeaderLabel field:audioIceConnectivityLabel];
[UICallCell adaptSize:audioCodecHeaderLabel field:audioCodecLabel];
[UICallCell adaptSize:audioDownloadBandwidthHeaderLabel field:audioDownloadBandwidthLabel];
[UICallCell adaptSize:audioUploadBandwidthHeaderLabel field:audioUploadBandwidthLabel];
[UICallCell adaptSize:audioIceConnectivityHeaderLabel field:audioIceConnectivityLabel];
[UICallCell adaptSize:videoCodecHeaderLabel field:videoCodecLabel];
[UICallCell adaptSize:videoDownloadBandwidthHeaderLabel field:videoDownloadBandwidthLabel];
[UICallCell adaptSize:videoUploadBandwidthHeaderLabel field:videoUploadBandwidthLabel];
[UICallCell adaptSize:videoIceConnectivityHeaderLabel field:videoIceConnectivityLabel];
[UICallCell adaptSize:videoCodecHeaderLabel field:videoCodecLabel];
[UICallCell adaptSize:videoDownloadBandwidthHeaderLabel field:videoDownloadBandwidthLabel];
[UICallCell adaptSize:videoUploadBandwidthHeaderLabel field:videoUploadBandwidthLabel];
[UICallCell adaptSize:videoIceConnectivityHeaderLabel field:videoIceConnectivityLabel];
if ([LinphoneManager runningOnIpad]) {
[LinphoneUtils adjustFontSize:self.audioStatsView mult:2.22];
[LinphoneUtils adjustFontSize:self.videoStatsView mult:2.22];
}
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillEnterForeground:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
}
return self;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillEnterForeground:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationWillEnterForegroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationWillEnterForegroundNotification
object:nil];
}
#pragma mark - Properties Functions
- (void)setData:(UICallCellData *)adata {
if(adata == data) {
return;
}
if(data != nil) {
data = nil;
}
if(adata != nil) {
data = adata;
}
if (adata == data) {
return;
}
if (data != nil) {
data = nil;
}
if (adata != nil) {
data = adata;
}
}
- (void)setCurrentCall:(BOOL) val {
currentCall = val;
if (currentCall && ![self isBlinkAnimationRunning:@"blink" target:headerBackgroundHighlightImage]) {
[self startBlinkAnimation:@"blink" target:headerBackgroundHighlightImage];
}
if (!currentCall) {
[self stopBlinkAnimation:@"blink" target:headerBackgroundHighlightImage];
}
- (void)setCurrentCall:(BOOL)val {
currentCall = val;
if (currentCall && ![self isBlinkAnimationRunning:@"blink" target:headerBackgroundHighlightImage]) {
[self startBlinkAnimation:@"blink" target:headerBackgroundHighlightImage];
}
if (!currentCall) {
[self stopBlinkAnimation:@"blink" target:headerBackgroundHighlightImage];
}
}
#pragma mark - Static Functions
+ (int)getMaximizedHeight {
@ -242,196 +227,195 @@
return [LinphoneManager runningOnIpad] ? 126 : 63;
}
+ (void)adaptSize:(UILabel*)label field:(UIView*)field {
//
// Adapt size
//
CGRect labelFrame = [label frame];
CGRect fieldFrame = [field frame];
+ (void)adaptSize:(UILabel *)label field:(UIView *)field {
//
// Adapt size
//
CGRect labelFrame = [label frame];
CGRect fieldFrame = [field frame];
fieldFrame.origin.x -= labelFrame.size.width;
fieldFrame.origin.x -= labelFrame.size.width;
// Compute firstName size
CGSize contraints;
contraints.height = [label frame].size.height;
contraints.width = ([field frame].size.width + [field frame].origin.x) - [label frame].origin.x;
CGSize firstNameSize = [[label text] sizeWithFont:[label font] constrainedToSize: contraints];
labelFrame.size.width = firstNameSize.width;
// Compute firstName size
CGSize contraints;
contraints.height = [label frame].size.height;
contraints.width = ([field frame].size.width + [field frame].origin.x) - [label frame].origin.x;
CGSize firstNameSize = [[label text] sizeWithFont:[label font] constrainedToSize:contraints];
labelFrame.size.width = firstNameSize.width;
// Compute lastName size & position
fieldFrame.origin.x += labelFrame.size.width;
fieldFrame.size.width = (contraints.width + [label frame].origin.x) - fieldFrame.origin.x;
// Compute lastName size & position
fieldFrame.origin.x += labelFrame.size.width;
fieldFrame.size.width = (contraints.width + [label frame].origin.x) - fieldFrame.origin.x;
[label setFrame: labelFrame];
[field setFrame: fieldFrame];
[label setFrame:labelFrame];
[field setFrame:fieldFrame];
}
+ (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 *)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;
}
}
#pragma mark - Event Functions
- (void)applicationWillEnterForeground:(NSNotification*)notif {
if (currentCall) {
[self startBlinkAnimation:@"blink" target:headerBackgroundHighlightImage];
}
- (void)applicationWillEnterForeground:(NSNotification *)notif {
if (currentCall) {
[self startBlinkAnimation:@"blink" target:headerBackgroundHighlightImage];
}
}
#pragma mark - Animation Functions
- (void)startBlinkAnimation:(NSString *)animationID target:(UIView *)target {
if( [[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]){
CABasicAnimation *blink = [CABasicAnimation animationWithKeyPath:@"opacity"];
blink.duration = 1.0;
blink.fromValue = [NSNumber numberWithDouble:0.0f];
blink.toValue = [NSNumber numberWithDouble:1.0f];
blink.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
blink.autoreverses = TRUE;
blink.repeatCount = HUGE_VALF;
[target.layer addAnimation:blink forKey:animationID];
} else {
[target setAlpha:1.0f];
}
- (void)startBlinkAnimation:(NSString *)animationID target:(UIView *)target {
if ([[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]) {
CABasicAnimation *blink = [CABasicAnimation animationWithKeyPath:@"opacity"];
blink.duration = 1.0;
blink.fromValue = [NSNumber numberWithDouble:0.0f];
blink.toValue = [NSNumber numberWithDouble:1.0f];
blink.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
blink.autoreverses = TRUE;
blink.repeatCount = HUGE_VALF;
[target.layer addAnimation:blink forKey:animationID];
} else {
[target setAlpha:1.0f];
}
}
- (BOOL)isBlinkAnimationRunning:(NSString *)animationID target:(UIView *)target {
return [target.layer animationForKey:animationID] != nil;
return [target.layer animationForKey:animationID] != nil;
}
- (void)stopBlinkAnimation:(NSString *)animationID target:(UIView *)target {
if( [self isBlinkAnimationRunning:animationID target:target] ){
[target.layer removeAnimationForKey:animationID];
}
[target setAlpha:0.0f];
if ([self isBlinkAnimationRunning:animationID target:target]) {
[target.layer removeAnimationForKey:animationID];
}
[target setAlpha:0.0f];
}
#pragma mark -
- (void)update {
if(data == nil || data->call == NULL) {
LOGW(@"Cannot update call cell: null call or data");
return;
}
LinphoneCall *call = data->call;
if (data == nil || data->call == NULL) {
LOGW(@"Cannot update call cell: null call or data");
return;
}
LinphoneCall *call = data->call;
[pauseButton setType:UIPauseButtonType_Call call:call];
[pauseButton setType:UIPauseButtonType_Call call:call];
[addressLabel setText:data.address];
[avatarImage setImage:data.image];
[addressLabel setText:data.address];
[avatarImage setImage:data.image];
LinphoneCallState state = linphone_call_get_state(call);
if(!conferenceCell) {
if(state == LinphoneCallOutgoingRinging) {
[stateImage setImage:[UIImage imageNamed:@"call_state_ringing_default.png"]];
[stateImage setHidden:false];
[pauseButton setHidden:true];
} else if(state == LinphoneCallOutgoingInit || state == LinphoneCallOutgoingProgress){
[stateImage setImage:[UIImage imageNamed:@"call_state_outgoing_default.png"]];
[stateImage setHidden:false];
[pauseButton setHidden:true];
} else {
[stateImage setHidden:true];
[pauseButton setHidden:false];
[pauseButton update];
}
[removeButton setHidden:true];
if(firstCell) {
[headerBackgroundImage setImage:[UIImage imageNamed:@"cell_call_first.png"]];
[headerBackgroundHighlightImage setImage:[UIImage imageNamed:@"cell_call_first_highlight.png"]];
} else {
[headerBackgroundImage setImage:[UIImage imageNamed:@"cell_call.png"]];
[headerBackgroundHighlightImage setImage:[UIImage imageNamed:@"cell_call_highlight.png"]];
}
} else {
[stateImage setHidden:true];
[pauseButton setHidden:true];
[removeButton setHidden:false];
[headerBackgroundImage setImage:[UIImage imageNamed:@"cell_conference.png"]];
}
LinphoneCallState state = linphone_call_get_state(call);
if (!conferenceCell) {
if (state == LinphoneCallOutgoingRinging) {
[stateImage setImage:[UIImage imageNamed:@"call_state_ringing_default.png"]];
[stateImage setHidden:false];
[pauseButton setHidden:true];
} else if (state == LinphoneCallOutgoingInit || state == LinphoneCallOutgoingProgress) {
[stateImage setImage:[UIImage imageNamed:@"call_state_outgoing_default.png"]];
[stateImage setHidden:false];
[pauseButton setHidden:true];
} else {
[stateImage setHidden:true];
[pauseButton setHidden:false];
[pauseButton update];
}
[removeButton setHidden:true];
if (firstCell) {
[headerBackgroundImage setImage:[UIImage imageNamed:@"cell_call_first.png"]];
[headerBackgroundHighlightImage setImage:[UIImage imageNamed:@"cell_call_first_highlight.png"]];
} else {
[headerBackgroundImage setImage:[UIImage imageNamed:@"cell_call.png"]];
[headerBackgroundHighlightImage setImage:[UIImage imageNamed:@"cell_call_highlight.png"]];
}
} else {
[stateImage setHidden:true];
[pauseButton setHidden:true];
[removeButton setHidden:false];
[headerBackgroundImage setImage:[UIImage imageNamed:@"cell_conference.png"]];
}
int duration = linphone_call_get_duration(call);
[stateLabel setText:[NSString stringWithFormat:@"%02i:%02i", (duration/60), (duration%60), nil]];
int duration = linphone_call_get_duration(call);
[stateLabel setText:[NSString stringWithFormat:@"%02i:%02i", (duration / 60), (duration % 60), nil]];
if(!data->minimize) {
CGRect frame = [self frame];
frame.size.height = [UICallCell getMaximizedHeight];
[self setFrame:frame];
if (!data->minimize) {
CGRect frame = [self frame];
frame.size.height = [UICallCell getMaximizedHeight];
[self setFrame:frame];
frame = otherView.frame;
frame.size.height = [UICallCell getMaximizedHeight];
[otherView setHidden:false];
[otherView setHidden:false];
otherView.frame = frame;
} else {
CGRect frame = [self frame];
frame.size.height = [headerView frame].size.height;
[self setFrame:frame];
[otherView setHidden:true];
}
} else {
CGRect frame = [self frame];
frame.size.height = [headerView frame].size.height;
[self setFrame:frame];
[otherView setHidden:true];
}
[self updateStats];
[self updateStats];
[self updateDetailsView];
[self updateDetailsView];
}
- (void)updateStats {
if(data == nil || data->call == NULL) {
LOGW(@"Cannot update call cell: null call or data");
return;
}
LinphoneCall *call = data->call;
if (data == nil || data->call == NULL) {
LOGW(@"Cannot update call cell: null call or data");
return;
}
LinphoneCall *call = data->call;
const LinphoneCallParams *params = linphone_call_get_current_params(call);
{
const PayloadType* payload = linphone_call_params_get_used_audio_codec(params);
if(payload != NULL) {
[audioCodecLabel setText:[NSString stringWithFormat:@"%s/%i/%i", payload->mime_type, payload->clock_rate, payload->channels]];
} else {
[audioCodecLabel setText:NSLocalizedString(@"No codec", nil)];
}
const LinphoneCallStats *stats = linphone_call_get_audio_stats(call);
if(stats != NULL) {
[audioUploadBandwidthLabel setText:[NSString stringWithFormat:@"%1.1f kbits/s", stats->upload_bandwidth]];
[audioDownloadBandwidthLabel setText:[NSString stringWithFormat:@"%1.1f kbits/s", stats->download_bandwidth]];
[audioIceConnectivityLabel setText:[UICallCell iceToString:stats->ice_state]];
} else {
[audioUploadBandwidthLabel setText:@""];
[audioDownloadBandwidthLabel setText:@""];
[audioIceConnectivityLabel setText:@""];
}
}
const LinphoneCallParams *params = linphone_call_get_current_params(call);
{
const PayloadType *payload = linphone_call_params_get_used_audio_codec(params);
if (payload != NULL) {
[audioCodecLabel setText:[NSString stringWithFormat:@"%s/%i/%i", payload->mime_type, payload->clock_rate,
payload->channels]];
} else {
[audioCodecLabel setText:NSLocalizedString(@"No codec", nil)];
}
const LinphoneCallStats *stats = linphone_call_get_audio_stats(call);
if (stats != NULL) {
[audioUploadBandwidthLabel setText:[NSString stringWithFormat:@"%1.1f kbits/s", stats->upload_bandwidth]];
[audioDownloadBandwidthLabel
setText:[NSString stringWithFormat:@"%1.1f kbits/s", stats->download_bandwidth]];
[audioIceConnectivityLabel setText:[UICallCell iceToString:stats->ice_state]];
} else {
[audioUploadBandwidthLabel setText:@""];
[audioDownloadBandwidthLabel setText:@""];
[audioIceConnectivityLabel setText:@""];
}
}
{
const PayloadType* payload = linphone_call_params_get_used_video_codec(params);
if(payload != NULL) {
[videoCodecLabel setText:[NSString stringWithFormat:@"%s/%i", payload->mime_type, payload->clock_rate]];
} else {
[videoCodecLabel setText:NSLocalizedString(@"No codec", nil)];
}
{
const PayloadType *payload = linphone_call_params_get_used_video_codec(params);
if (payload != NULL) {
[videoCodecLabel setText:[NSString stringWithFormat:@"%s/%i", payload->mime_type, payload->clock_rate]];
} else {
[videoCodecLabel setText:NSLocalizedString(@"No codec", nil)];
}
const LinphoneCallStats *stats = linphone_call_get_video_stats(call);
const LinphoneCallStats *stats = linphone_call_get_video_stats(call);
if (stats != NULL && linphone_call_params_video_enabled(params)) {
MSVideoSize sentSize = linphone_call_params_get_sent_video_size(params);
@ -457,88 +441,87 @@
}
}
- (void)updateDetailsView {
if(data == nil || data->call == NULL) {
LOGW(@"Cannot update call cell: null call or data");
return;
}
if(data->view == UICallCellOtherView_Avatar && avatarView.isHidden) {
[self->avatarView setHidden:FALSE];
[self->audioStatsView setHidden:TRUE];
[self->videoStatsView setHidden:TRUE];
} else if(data->view == UICallCellOtherView_AudioStats && audioStatsView.isHidden) {
[self->avatarView setHidden:TRUE];
[self->audioStatsView setHidden:FALSE];
[self->videoStatsView setHidden:TRUE];
} else if(data->view == UICallCellOtherView_VideoStats && videoStatsView.isHidden) {
[self->avatarView setHidden:TRUE];
[self->audioStatsView setHidden:TRUE];
[self->videoStatsView setHidden:FALSE];
}
if (data == nil || data->call == NULL) {
LOGW(@"Cannot update call cell: null call or data");
return;
}
if (data->view == UICallCellOtherView_Avatar && avatarView.isHidden) {
[self->avatarView setHidden:FALSE];
[self->audioStatsView setHidden:TRUE];
[self->videoStatsView setHidden:TRUE];
} else if (data->view == UICallCellOtherView_AudioStats && audioStatsView.isHidden) {
[self->avatarView setHidden:TRUE];
[self->audioStatsView setHidden:FALSE];
[self->videoStatsView setHidden:TRUE];
} else if (data->view == UICallCellOtherView_VideoStats && videoStatsView.isHidden) {
[self->avatarView setHidden:TRUE];
[self->audioStatsView setHidden:TRUE];
[self->videoStatsView setHidden:FALSE];
}
}
- (void)selfUpdate {
UITableView *parentTable = (UITableView *)self.superview;
UITableView *parentTable = (UITableView *)self.superview;
while( parentTable != nil && ![parentTable isKindOfClass:[UITableView class]] ) parentTable = (UITableView *)[parentTable superview];
while (parentTable != nil && ![parentTable isKindOfClass:[UITableView class]])
parentTable = (UITableView *)[parentTable superview];
if(parentTable != nil) {
NSIndexPath *index= [parentTable indexPathForCell:self];
if(index != nil) {
[parentTable reloadRowsAtIndexPaths:@[index] withRowAnimation:false];
}
}
if (parentTable != nil) {
NSIndexPath *index = [parentTable indexPathForCell:self];
if (index != nil) {
[parentTable reloadRowsAtIndexPaths:@[ index ] withRowAnimation:false];
}
}
}
#pragma mark - Action Functions
- (IBAction)doHeaderClick:(id)sender {
if(data) {
data->minimize = !data->minimize;
[self selfUpdate];
}
if (data) {
data->minimize = !data->minimize;
[self selfUpdate];
}
}
- (IBAction)doRemoveClick:(id)sender {
if(data != nil && data->call != NULL) {
linphone_core_remove_from_conference([LinphoneManager getLc], data->call);
}
if (data != nil && data->call != NULL) {
linphone_core_remove_from_conference([LinphoneManager getLc], data->call);
}
}
- (IBAction)doDetailsSwipe:(UISwipeGestureRecognizer *)sender {
CATransition* trans = nil;
if(data != nil) {
if (sender.direction == UISwipeGestureRecognizerDirectionLeft) {
if(data->view == UICallCellOtherView_MAX - 1) {
data->view = 0;
} else {
++data->view;
}
trans = [CATransition animation];
[trans setType:kCATransitionPush];
[trans setDuration:0.35];
[trans setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[trans setSubtype:kCATransitionFromRight];
} else if (sender.direction == UISwipeGestureRecognizerDirectionRight) {
if(data->view == 0) {
data->view = UICallCellOtherView_MAX - 1;
} else {
--data->view;
}
trans = [CATransition animation];
[trans setType:kCATransitionPush];
[trans setDuration:0.35];
[trans setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[trans setSubtype:kCATransitionFromLeft];
}
if(trans) {
[otherView.layer removeAnimationForKey:@"transition"];
[otherView.layer addAnimation:trans forKey:@"transition"];
[self updateDetailsView];
}
}
CATransition *trans = nil;
if (data != nil) {
if (sender.direction == UISwipeGestureRecognizerDirectionLeft) {
if (data->view == UICallCellOtherView_MAX - 1) {
data->view = 0;
} else {
++data->view;
}
trans = [CATransition animation];
[trans setType:kCATransitionPush];
[trans setDuration:0.35];
[trans setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[trans setSubtype:kCATransitionFromRight];
} else if (sender.direction == UISwipeGestureRecognizerDirectionRight) {
if (data->view == 0) {
data->view = UICallCellOtherView_MAX - 1;
} else {
--data->view;
}
trans = [CATransition animation];
[trans setType:kCATransitionPush];
[trans setDuration:0.35];
[trans setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[trans setSubtype:kCATransitionFromLeft];
}
if (trans) {
[otherView.layer removeAnimationForKey:@"transition"];
[otherView.layer addAnimation:trans forKey:@"transition"];
[self updateDetailsView];
}
}
}
@end

View file

@ -4,18 +4,18 @@
*
* 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 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* the Free Software Foundation; either version 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "UICamSwitch.h"
#include "LinphoneManager.h"
@ -23,7 +23,6 @@
@implementation UICamSwitch
@synthesize preview;
#pragma mark - Lifecycle Functions
- (id)initUICamSwitch {
@ -32,53 +31,56 @@
}
- (id)init {
self = [super init];
if (self) {
if (!(self = [self initUICamSwitch])) return nil;
}
return self;
self = [super init];
if (self) {
if (!(self = [self initUICamSwitch]))
return nil;
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
if (!(self = [self initUICamSwitch])) return nil;
}
return self;
self = [super initWithFrame:frame];
if (self) {
if (!(self = [self initUICamSwitch]))
return nil;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
if (!(self = [self initUICamSwitch])) return nil;
self = [super initWithCoder:decoder];
if (self) {
if (!(self = [self initUICamSwitch]))
return nil;
}
return self;
return self;
}
#pragma mark -
#pragma mark -
-(void) touchUp:(id) sender {
const char *currentCamId = (char*)linphone_core_get_video_device([LinphoneManager getLc]);
const char **cameras=linphone_core_get_video_devices([LinphoneManager getLc]);
const char *newCamId=NULL;
- (void)touchUp:(id)sender {
const char *currentCamId = (char *)linphone_core_get_video_device([LinphoneManager getLc]);
const char **cameras = linphone_core_get_video_devices([LinphoneManager getLc]);
const char *newCamId = NULL;
int i;
for (i=0;cameras[i]!=NULL;++i){
if (strcmp(cameras[i],"StaticImage: Static picture")==0) continue;
if (strcmp(cameras[i],currentCamId)!=0){
newCamId=cameras[i];
for (i = 0; cameras[i] != NULL; ++i) {
if (strcmp(cameras[i], "StaticImage: Static picture") == 0)
continue;
if (strcmp(cameras[i], currentCamId) != 0) {
newCamId = cameras[i];
break;
}
}
if (newCamId){
if (newCamId) {
LOGI(@"Switching from [%s] to [%s]", currentCamId, newCamId);
linphone_core_set_video_device([LinphoneManager getLc], newCamId);
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
if(call != NULL) {
linphone_core_update_call([LinphoneManager getLc], call, NULL);
}
if (call != NULL) {
linphone_core_update_call([LinphoneManager getLc], call, NULL);
}
}
}

View file

@ -31,34 +31,28 @@
@synthesize unreadMessageLabel;
@synthesize unreadMessageView;
#pragma mark - Lifecycle Functions
- (id)initWithIdentifier:(NSString*)identifier {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"UIChatCell"
owner:self
options:nil];
- (id)initWithIdentifier:(NSString *)identifier {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"UIChatCell" owner:self options:nil];
if ([arrayOfViews count] >= 1) {
if ([arrayOfViews count] >= 1) {
[self.contentView addSubview:[arrayOfViews objectAtIndex:0]];
}
[chatContentLabel setAdjustsFontSizeToFitWidth:TRUE]; // Auto shrink: IB lack!
}
return self;
[self.contentView addSubview:[arrayOfViews objectAtIndex:0]];
}
[chatContentLabel setAdjustsFontSizeToFitWidth:TRUE]; // Auto shrink: IB lack!
}
return self;
}
#pragma mark - Property Funcitons
- (void)setChatRoom:(LinphoneChatRoom *)achat {
self->chatRoom = achat;
[self update];
self->chatRoom = achat;
[self update];
}
#pragma mark -
- (NSString *)accessibilityValue {
@ -70,15 +64,14 @@
}
}
- (void)update {
NSString *displayName = nil;
UIImage *image = nil;
if(chatRoom == nil) {
LOGW(@"Cannot update chat cell: null chat");
return;
}
const LinphoneAddress* linphoneAddress = linphone_chat_room_get_peer_address(chatRoom);
UIImage *image = nil;
if (chatRoom == nil) {
LOGW(@"Cannot update chat cell: null chat");
return;
}
const LinphoneAddress *linphoneAddress = linphone_chat_room_get_peer_address(chatRoom);
if (linphoneAddress == NULL)
return;
@ -86,38 +79,38 @@
NSString *normalizedSipAddress = [NSString stringWithUTF8String:tmp];
ms_free(tmp);
ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:normalizedSipAddress];
if(contact != nil) {
displayName = [FastAddressBook getContactDisplayName:contact];
image = [FastAddressBook getContactImage:contact thumbnail:true];
}
ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:normalizedSipAddress];
if (contact != nil) {
displayName = [FastAddressBook getContactDisplayName:contact];
image = [FastAddressBook getContactImage:contact thumbnail:true];
}
// Display name
if(displayName == nil) {
const char* username = linphone_address_get_username(linphoneAddress);
char* address = linphone_address_as_string(linphoneAddress);
displayName = [NSString stringWithUTF8String:username?:address];
// Display name
if (displayName == nil) {
const char *username = linphone_address_get_username(linphoneAddress);
char *address = linphone_address_as_string(linphoneAddress);
displayName = [NSString stringWithUTF8String:username ?: address];
ms_free(address);
}
[addressLabel setText:displayName];
}
[addressLabel setText:displayName];
// Avatar
if(image == nil) {
image = [UIImage imageNamed:@"avatar_unknown_small.png"];
}
[avatarImage setImage:image];
// Avatar
if (image == nil) {
image = [UIImage imageNamed:@"avatar_unknown_small.png"];
}
[avatarImage setImage:image];
LinphoneChatMessage* last_message = linphone_chat_room_get_user_data(chatRoom);
LinphoneChatMessage *last_message = linphone_chat_room_get_user_data(chatRoom);
if( last_message ){
if (last_message) {
const char* text = linphone_chat_message_get_text(last_message);
const char* url = linphone_chat_message_get_external_body_url(last_message);
const LinphoneContent *last_content = linphone_chat_message_get_file_transfer_information(last_message);
const char *text = linphone_chat_message_get_text(last_message);
const char *url = linphone_chat_message_get_external_body_url(last_message);
const LinphoneContent *last_content = linphone_chat_message_get_file_transfer_information(last_message);
// Message
if(url||last_content) {
[chatContentLabel setText:@"🗻"];
} else if (text) {
if (url || last_content) {
[chatContentLabel setText:@"🗻"];
} else if (text) {
NSString *message = [NSString stringWithUTF8String:text];
// shorten long messages
if ([message length] > 50)
@ -137,38 +130,40 @@
}
- (void)setEditing:(BOOL)editing {
[self setEditing:editing animated:FALSE];
[self setEditing:editing animated:FALSE];
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
if(animated) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
}
if(editing) {
[deleteButton setAlpha:1.0f];
} else {
[deleteButton setAlpha:0.0f];
}
if(animated) {
[UIView commitAnimations];
}
if (animated) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
}
if (editing) {
[deleteButton setAlpha:1.0f];
} else {
[deleteButton setAlpha:0.0f];
}
if (animated) {
[UIView commitAnimations];
}
}
#pragma mark - Action Functions
- (IBAction)onDeleteClick: (id) event {
if(chatRoom != NULL) {
UIView *view = [self superview];
// Find TableViewCell
while( view != nil && ![view isKindOfClass:[UITableView class]]) view = [view superview];
if(view != nil) {
UITableView *tableView = (UITableView*) view;
NSIndexPath *indexPath = [tableView indexPathForCell:self];
[[tableView dataSource] tableView:tableView commitEditingStyle:UITableViewCellEditingStyleDelete forRowAtIndexPath:indexPath];
}
}
- (IBAction)onDeleteClick:(id)event {
if (chatRoom != NULL) {
UIView *view = [self superview];
// Find TableViewCell
while (view != nil && ![view isKindOfClass:[UITableView class]])
view = [view superview];
if (view != nil) {
UITableView *tableView = (UITableView *)view;
NSIndexPath *indexPath = [tableView indexPathForCell:self];
[[tableView dataSource] tableView:tableView
commitEditingStyle:UITableViewCellEditingStyleDelete
forRowAtIndexPath:indexPath];
}
}
}
@end

View file

@ -29,7 +29,7 @@
#include "linphone/linphonecore.h"
@implementation UIChatRoomCell {
FileTransferDelegate* ftd;
FileTransferDelegate *ftd;
}
@synthesize innerView;
@ -47,7 +47,7 @@
static const CGFloat CELL_MIN_HEIGHT = 50.0f;
static const CGFloat CELL_MIN_WIDTH = 150.0f;
//static const CGFloat CELL_MAX_WIDTH = 320.0f;
// static const CGFloat CELL_MAX_WIDTH = 320.0f;
static const CGFloat CELL_MESSAGE_X_MARGIN = 26.0f + 10.0f;
static const CGFloat CELL_MESSAGE_Y_MARGIN = 36.0f;
static const CGFloat CELL_FONT_SIZE = 17.0f;
@ -57,15 +57,15 @@ static UIFont *CELL_FONT = nil;
#pragma mark - Lifecycle Functions
- (id)initWithIdentifier:(NSString*)identifier {
- (id)initWithIdentifier:(NSString *)identifier {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
[[NSBundle mainBundle] loadNibNamed:@"UIChatRoomCell"
owner:self
options:nil];
imageTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onImageClick:)];
[[NSBundle mainBundle] loadNibNamed:@"UIChatRoomCell" owner:self options:nil];
imageTapGestureRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onImageClick:)];
[messageImageView addGestureRecognizer:imageTapGestureRecognizer];
resendTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onResendClick:)];
resendTapGestureRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onResendClick:)];
[dateLabel addGestureRecognizer:resendTapGestureRecognizer];
[statusImage addGestureRecognizer:resendTapGestureRecognizer];
@ -74,8 +74,8 @@ static UIFont *CELL_FONT = nil;
// shift message box, otherwise it will collide with the bubble
CGRect messageCoords = [messageText frame];
messageCoords.origin.x += 2;
messageCoords.origin.y += 2;
messageCoords.origin.x += 2;
messageCoords.origin.y += 2;
messageCoords.size.width -= 5;
[messageText setFrame:messageCoords];
messageText.allowSelectAll = TRUE;
@ -128,15 +128,14 @@ static UIFont *CELL_FONT = nil;
}
[self update];
}
}
+ (NSString*)decodeTextMessage:(const char*)text {
NSString* decoded = [NSString stringWithUTF8String:text];
if( decoded == nil ){
+ (NSString *)decodeTextMessage:(const char *)text {
NSString *decoded = [NSString stringWithUTF8String:text];
if (decoded == nil) {
// couldn't decode the string as UTF8, do a lossy conversion
decoded = [NSString stringWithCString:text encoding:NSASCIIStringEncoding];
if( decoded == nil ){
if (decoded == nil) {
decoded = @"(invalid string)";
}
}
@ -144,19 +143,19 @@ static UIFont *CELL_FONT = nil;
}
- (void)update {
if(chat == nil) {
if (chat == nil) {
LOGW(@"Cannot update chat room cell: null chat");
return;
}
const char* url = linphone_chat_message_get_external_body_url(chat);
const char* text = linphone_chat_message_get_text(chat);
const char *url = linphone_chat_message_get_external_body_url(chat);
const char *text = linphone_chat_message_get_text(chat);
BOOL is_external =
(url && (strstr(url, "http") == url)) || linphone_chat_message_get_file_transfer_information(chat);
NSString* localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:chat];
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:chat];
// this is an image (either to download or already downloaded)
if (is_external || localImage) {
if(localImage) {
if (localImage) {
if (messageImageView.image == nil) {
NSURL *imageUrl = [NSURL URLWithString:localImage];
messageText.hidden = YES;
@ -197,16 +196,18 @@ static UIFont *CELL_FONT = nil;
// simple text message
} else {
[messageText setHidden:FALSE];
if ( text ){
NSString* nstext = [UIChatRoomCell decodeTextMessage:text];
if (text) {
NSString *nstext = [UIChatRoomCell decodeTextMessage:text];
/* We need to use an attributed string here so that data detector don't mess
* with the text style. See http://stackoverflow.com/a/20669356 */
NSAttributedString* attr_text = [[NSAttributedString alloc]
initWithString:nstext
attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:17.0],
NSForegroundColorAttributeName:[UIColor darkGrayColor]}];
NSAttributedString *attr_text =
[[NSAttributedString alloc] initWithString:nstext
attributes:@{
NSFontAttributeName : [UIFont systemFontOfSize:17.0],
NSForegroundColorAttributeName : [UIColor darkGrayColor]
}];
messageText.attributedText = attr_text;
} else {
@ -229,10 +230,10 @@ static UIFont *CELL_FONT = nil;
LinphoneChatMessageState state = linphone_chat_message_get_state(chat);
BOOL outgoing = linphone_chat_message_is_outgoing(chat);
if( !outgoing ){
if (!outgoing) {
[statusImage setAccessibilityValue:@"incoming"];
statusImage.hidden = TRUE; // not useful for incoming chats..
} else if (state== LinphoneChatMessageStateInProgress) {
} else if (state == LinphoneChatMessageStateInProgress) {
[statusImage setImage:[UIImage imageNamed:@"chat_message_inprogress.png"]];
[statusImage setAccessibilityValue:@"in progress"];
statusImage.hidden = FALSE;
@ -245,13 +246,13 @@ static UIFont *CELL_FONT = nil;
[statusImage setAccessibilityValue:@"not delivered"];
statusImage.hidden = FALSE;
NSAttributedString* resend_text = [[NSAttributedString alloc]
initWithString:NSLocalizedString(@"Resend", @"Resend")
attributes:@{NSForegroundColorAttributeName: [UIColor redColor]}];
NSAttributedString *resend_text =
[[NSAttributedString alloc] initWithString:NSLocalizedString(@"Resend", @"Resend")
attributes:@{NSForegroundColorAttributeName : [UIColor redColor]}];
[dateLabel setAttributedText:resend_text];
}
if( outgoing){
if (outgoing) {
[messageText setAccessibilityLabel:@"Outgoing message"];
} else {
[messageText setAccessibilityLabel:@"Incoming message"];
@ -263,72 +264,74 @@ static UIFont *CELL_FONT = nil;
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
if(animated) {
if (animated) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
}
if(editing) {
if (editing) {
[deleteButton setAlpha:1.0f];
} else {
[deleteButton setAlpha:0.0f];
}
if(animated) {
if (animated) {
[UIView commitAnimations];
}
}
+ (CGSize)viewSize:(LinphoneChatMessage*)chat width:(int)width {
+ (CGSize)viewSize:(LinphoneChatMessage *)chat width:(int)width {
CGSize messageSize;
const char* url = linphone_chat_message_get_external_body_url(chat);
const char* text = linphone_chat_message_get_text(chat);
NSString* messageText = text ? [UIChatRoomCell decodeTextMessage:text] : @"";
const char *url = linphone_chat_message_get_external_body_url(chat);
const char *text = linphone_chat_message_get_text(chat);
NSString *messageText = text ? [UIChatRoomCell decodeTextMessage:text] : @"";
if (url == nil && linphone_chat_message_get_file_transfer_information(chat) == NULL) {
if(CELL_FONT == nil) {
if (CELL_FONT == nil) {
CELL_FONT = [UIFont systemFontOfSize:CELL_FONT_SIZE];
}
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
if( [[[UIDevice currentDevice] systemVersion] doubleValue] >= 7){
messageSize = [messageText
boundingRectWithSize:CGSizeMake(width - CELL_MESSAGE_X_MARGIN, CGFLOAT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesFontLeading)
attributes:@{NSFontAttributeName: CELL_FONT}
context:nil].size;
if ([[[UIDevice currentDevice] systemVersion] doubleValue] >= 7) {
messageSize = [messageText boundingRectWithSize:CGSizeMake(width - CELL_MESSAGE_X_MARGIN, CGFLOAT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin |
NSStringDrawingTruncatesLastVisibleLine |
NSStringDrawingUsesFontLeading)
attributes:@{
NSFontAttributeName : CELL_FONT
} context:nil]
.size;
} else
#endif
{
messageSize = [messageText sizeWithFont: CELL_FONT
constrainedToSize: CGSizeMake(width - CELL_MESSAGE_X_MARGIN, 10000.0f)
lineBreakMode: NSLineBreakByTruncatingTail];
messageSize = [messageText sizeWithFont:CELL_FONT
constrainedToSize:CGSizeMake(width - CELL_MESSAGE_X_MARGIN, 10000.0f)
lineBreakMode:NSLineBreakByTruncatingTail];
}
} else {
messageSize = CGSizeMake(CELL_IMAGE_WIDTH, CELL_IMAGE_HEIGHT);
}
messageSize.height += CELL_MESSAGE_Y_MARGIN;
if(messageSize.height < CELL_MIN_HEIGHT)
if (messageSize.height < CELL_MIN_HEIGHT)
messageSize.height = CELL_MIN_HEIGHT;
messageSize.width += CELL_MESSAGE_X_MARGIN;
if(messageSize.width < CELL_MIN_WIDTH)
if (messageSize.width < CELL_MIN_WIDTH)
messageSize.width = CELL_MIN_WIDTH;
return messageSize;
}
+ (CGFloat)height:(LinphoneChatMessage*)chatMessage width:(int)width {
+ (CGFloat)height:(LinphoneChatMessage *)chatMessage width:(int)width {
return [UIChatRoomCell viewSize:chatMessage width:width].height;
}
#pragma mark - View Functions
- (void)layoutSubviews {
[super layoutSubviews];
if(chat != nil) {
if (chat != nil) {
// Resize inner
CGRect innerFrame;
BOOL is_outgoing = linphone_chat_message_is_outgoing(chat);
innerFrame.size = [UIChatRoomCell viewSize:chat width:[self frame].size.width];
if(!is_outgoing) { // Inverted
if (!is_outgoing) { // Inverted
innerFrame.origin.x = 0.0f;
innerFrame.origin.y = 0.0f;
} else {
@ -338,14 +341,14 @@ static UIFont *CELL_FONT = nil;
[innerView setFrame:innerFrame];
CGRect messageFrame = [bubbleView frame];
messageFrame.origin.y = ([innerView frame].size.height - messageFrame.size.height)/2;
if(!is_outgoing) { // Inverted
UIImage* image = [UIImage imageNamed:@"chat_bubble_incoming"];
messageFrame.origin.y = ([innerView frame].size.height - messageFrame.size.height) / 2;
if (!is_outgoing) { // Inverted
UIImage *image = [UIImage imageNamed:@"chat_bubble_incoming"];
image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(26, 32, 34, 56)];
[backgroundImage setImage:image];
messageFrame.origin.y += 5;
} else {
UIImage* image = [UIImage imageNamed:@"chat_bubble_outgoing"];
UIImage *image = [UIImage imageNamed:@"chat_bubble_outgoing"];
image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(14, 15, 25, 40)];
[backgroundImage setImage:image];
messageFrame.origin.y -= 5;
@ -354,21 +357,23 @@ static UIFont *CELL_FONT = nil;
}
}
#pragma mark - Action Functions
- (IBAction)onDeleteClick:(id)event {
if(chat != NULL) {
if (chat != NULL) {
if (ftd.message != nil) {
[ftd cancel];
}
UIView *view = [self superview];
// Find TableViewCell
while(view != nil && ![view isKindOfClass:[UITableView class]]) view = [view superview];
if(view != nil) {
UITableView *tableView = (UITableView*) view;
while (view != nil && ![view isKindOfClass:[UITableView class]])
view = [view superview];
if (view != nil) {
UITableView *tableView = (UITableView *)view;
NSIndexPath *indexPath = [tableView indexPathForCell:self];
[[tableView dataSource] tableView:tableView commitEditingStyle:UITableViewCellEditingStyleDelete forRowAtIndexPath:indexPath];
[[tableView dataSource] tableView:tableView
commitEditingStyle:UITableViewCellEditingStyleDelete
forRowAtIndexPath:indexPath];
}
}
}
@ -389,7 +394,6 @@ static UIFont *CELL_FONT = nil;
[self update];
}
- (IBAction)onImageClick:(id)event {
LinphoneChatMessageState state = linphone_chat_message_get_state(self->chat);
if (state == LinphoneChatMessageStateNotDelivered) {
@ -409,7 +413,8 @@ static UIFont *CELL_FONT = nil;
}
- (IBAction)onResendClick:(id)event {
if( chat == nil ) return;
if (chat == nil)
return;
LinphoneChatMessageState state = linphone_chat_message_get_state(self->chat);
if (state == LinphoneChatMessageStateNotDelivered) {
@ -469,7 +474,7 @@ static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState st
#pragma mark - LinphoneFileTransfer Notifications Handling
- (void)connectToFileDelegate:(FileTransferDelegate*)aftd {
- (void)connectToFileDelegate:(FileTransferDelegate *)aftd {
ftd = aftd;
_fileTransferProgress.progress = 0;
[[NSNotificationCenter defaultCenter] removeObserver:self];
@ -488,7 +493,7 @@ static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState st
ftd = nil;
}
- (void)onFileTransferSendUpdate:(NSNotification*)notif {
- (void)onFileTransferSendUpdate:(NSNotification *)notif {
LinphoneChatMessageState state = [[[notif userInfo] objectForKey:@"state"] intValue];
if (state == LinphoneChatMessageStateInProgress) {
@ -504,7 +509,7 @@ static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState st
[self update];
}
}
- (void)onFileTransferRecvUpdate:(NSNotification*)notif {
- (void)onFileTransferRecvUpdate:(NSNotification *)notif {
LinphoneChatMessageState state = [[[notif userInfo] objectForKey:@"state"] intValue];
if (state == LinphoneChatMessageStateInProgress) {
float progress = [[[notif userInfo] objectForKey:@"progress"] floatValue];

View file

@ -33,53 +33,53 @@
@synthesize landscapeMode;
@synthesize portraitMode;
- (id)copy {
UICompositeViewDescription *copy = [UICompositeViewDescription alloc];
copy.content = self.content;
copy.stateBar = self.stateBar;
copy.stateBarEnabled = self.stateBarEnabled;
copy.tabBar = self.tabBar;
copy.tabBarEnabled = self.tabBarEnabled;
copy.fullscreen = self.fullscreen;
copy.landscapeMode = self.landscapeMode;
copy.portraitMode = self.portraitMode;
copy.darkBackground = self.darkBackground;
return copy;
UICompositeViewDescription *copy = [UICompositeViewDescription alloc];
copy.content = self.content;
copy.stateBar = self.stateBar;
copy.stateBarEnabled = self.stateBarEnabled;
copy.tabBar = self.tabBar;
copy.tabBarEnabled = self.tabBarEnabled;
copy.fullscreen = self.fullscreen;
copy.landscapeMode = self.landscapeMode;
copy.portraitMode = self.portraitMode;
copy.darkBackground = self.darkBackground;
return copy;
}
- (BOOL)equal:(UICompositeViewDescription*) description {
return [self.name compare:description.name] == NSOrderedSame;
- (BOOL)equal:(UICompositeViewDescription *)description {
return [self.name compare:description.name] == NSOrderedSame;
}
- (id)init:(NSString *)aname content:(NSString *)acontent stateBar:(NSString*)astateBar
stateBarEnabled:(BOOL) astateBarEnabled
tabBar:(NSString*)atabBar
tabBarEnabled:(BOOL) atabBarEnabled
fullscreen:(BOOL) afullscreen
landscapeMode:(BOOL) alandscapeMode
portraitMode:(BOOL) aportraitMode{
self.name = aname;
self.content = acontent;
self.stateBar = astateBar;
self.stateBarEnabled = astateBarEnabled;
self.tabBar = atabBar;
self.tabBarEnabled = atabBarEnabled;
self.fullscreen = afullscreen;
self.landscapeMode = alandscapeMode;
self.portraitMode = aportraitMode;
self.darkBackground = false;
- (id)init:(NSString *)aname
content:(NSString *)acontent
stateBar:(NSString *)astateBar
stateBarEnabled:(BOOL)astateBarEnabled
tabBar:(NSString *)atabBar
tabBarEnabled:(BOOL)atabBarEnabled
fullscreen:(BOOL)afullscreen
landscapeMode:(BOOL)alandscapeMode
portraitMode:(BOOL)aportraitMode {
self.name = aname;
self.content = acontent;
self.stateBar = astateBar;
self.stateBarEnabled = astateBarEnabled;
self.tabBar = atabBar;
self.tabBarEnabled = atabBarEnabled;
self.fullscreen = afullscreen;
self.landscapeMode = alandscapeMode;
self.portraitMode = aportraitMode;
self.darkBackground = false;
return self;
return self;
}
@end
@interface UICompositeViewController ()
@property (nonatomic, strong) UIViewController *stateBarViewController;
@property (nonatomic, strong) UIViewController *tabBarViewController;
@property (nonatomic, strong) UIViewController *contentViewController;
@property(nonatomic, strong) UIViewController *stateBarViewController;
@property(nonatomic, strong) UIViewController *tabBarViewController;
@property(nonatomic, strong) UIViewController *contentViewController;
@end
@ -94,277 +94,276 @@
@synthesize viewTransition;
#pragma mark - Lifecycle Functions
- (void)initUICompositeViewController {
viewControllerCache = [[NSMutableDictionary alloc] init];
currentOrientation = (UIInterfaceOrientation)UIDeviceOrientationUnknown;
viewControllerCache = [[NSMutableDictionary alloc] init];
currentOrientation = (UIInterfaceOrientation)UIDeviceOrientationUnknown;
}
- (id)init{
self = [super init];
if (self) {
- (id)init {
self = [super init];
if (self) {
[self initUICompositeViewController];
}
return self;
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
[self initUICompositeViewController];
}
return self;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
self = [super initWithCoder:decoder];
if (self) {
[self initUICompositeViewController];
}
return self;
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - Property Functions
- (UIViewController*)stateBarViewController {
return _stateBarViewController;
- (UIViewController *)stateBarViewController {
return _stateBarViewController;
}
- (UIViewController*)contentViewController {
return _contentViewController;
- (UIViewController *)contentViewController {
return _contentViewController;
}
- (UIViewController*)tabBarViewController {
return _tabBarViewController;
- (UIViewController *)tabBarViewController {
return _tabBarViewController;
}
#pragma mark - ViewController Functions
- (void)updateViewsFramesAccordingToLaunchOrientation {
CGRect frame = [self.view frame]; // this view has the correct size at launch (1024/768 for iPad, 320*{568,480} for iPhone)
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
BOOL portrait = UIInterfaceOrientationIsPortrait(orientation);
CGRect oppositeFrame = frame;
oppositeFrame.size.height = frame.size.width;
oppositeFrame.size.width = frame.size.height;
CGRect frame =
[self.view frame]; // this view has the correct size at launch (1024/768 for iPad, 320*{568,480} for iPhone)
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
BOOL portrait = UIInterfaceOrientationIsPortrait(orientation);
CGRect oppositeFrame = frame;
oppositeFrame.size.height = frame.size.width;
oppositeFrame.size.width = frame.size.height;
// if we start in portrait, the landscape view must get the opposite height and width
if( portrait || [[UIDevice currentDevice].systemVersion floatValue] < 8 ){
LOGI(@"landscape get opposite: %@", NSStringFromCGSize(oppositeFrame.size));
[landscapeView setFrame:oppositeFrame];
} else {
// if we start in landscape, the landscape view has to get the current size,
// whereas the portrait has to get the opposite
LOGI(@"landscape get frame: %@ and portrait gets opposite: %@", NSStringFromCGSize(frame.size), NSStringFromCGSize(oppositeFrame.size));
[landscapeView setFrame:frame];
[portraitView setFrame:oppositeFrame];
}
// if we start in portrait, the landscape view must get the opposite height and width
if (portrait || [[UIDevice currentDevice].systemVersion floatValue] < 8) {
LOGI(@"landscape get opposite: %@", NSStringFromCGSize(oppositeFrame.size));
[landscapeView setFrame:oppositeFrame];
} else {
// if we start in landscape, the landscape view has to get the current size,
// whereas the portrait has to get the opposite
LOGI(@"landscape get frame: %@ and portrait gets opposite: %@", NSStringFromCGSize(frame.size),
NSStringFromCGSize(oppositeFrame.size));
[landscapeView setFrame:frame];
[portraitView setFrame:oppositeFrame];
}
}
- (void)viewDidLoad {
/* Force landscape view to match portrait view, because portrait view inherits
the device screen size at load */
[self updateViewsFramesAccordingToLaunchOrientation];
[super viewDidLoad];
/* Force landscape view to match portrait view, because portrait view inherits
the device screen size at load */
[self updateViewsFramesAccordingToLaunchOrientation];
[super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.contentViewController viewWillAppear:animated];
[self.tabBarViewController viewWillAppear:animated];
[self.stateBarViewController viewWillAppear:animated];
[super viewWillAppear:animated];
[self.contentViewController viewWillAppear:animated];
[self.tabBarViewController viewWillAppear:animated];
[self.stateBarViewController viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(orientationDidChange:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(orientationDidChange:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.contentViewController viewDidAppear:animated];
[self.tabBarViewController viewDidAppear:animated];
[self.stateBarViewController viewDidAppear:animated];
[super viewDidAppear:animated];
[self.contentViewController viewDidAppear:animated];
[self.tabBarViewController viewDidAppear:animated];
[self.stateBarViewController viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.contentViewController viewWillDisappear:animated];
[self.tabBarViewController viewWillDisappear:animated];
[self.stateBarViewController viewWillDisappear:animated];
[super viewWillDisappear:animated];
[self.contentViewController viewWillDisappear:animated];
[self.tabBarViewController viewWillDisappear:animated];
[self.stateBarViewController viewWillDisappear:animated];
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIDeviceOrientationDidChangeNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self.contentViewController viewDidDisappear:animated];
[self.tabBarViewController viewDidDisappear:animated];
[self.stateBarViewController viewDidDisappear:animated];
[super viewDidDisappear:animated];
[self.contentViewController viewDidDisappear:animated];
[self.tabBarViewController viewDidDisappear:animated];
[self.stateBarViewController viewDidDisappear:animated];
}
#pragma mark - Rotation messages
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
currentOrientation = toInterfaceOrientation;
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self.contentViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self.tabBarViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self.stateBarViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {
currentOrientation = toInterfaceOrientation;
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self.contentViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self.tabBarViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self.stateBarViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; // Will invoke TPMultiLayout
[self.contentViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self.tabBarViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self.stateBarViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self update:nil tabBar:nil stateBar:nil fullscreen:nil];
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation
duration:duration]; // Will invoke TPMultiLayout
[self.contentViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self.tabBarViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self.stateBarViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self update:nil tabBar:nil stateBar:nil fullscreen:nil];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
[self.contentViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
[self.tabBarViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
[self.stateBarViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
[self.contentViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
[self.tabBarViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
[self.stateBarViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if(interfaceOrientation == currentOrientation)
return YES;
return NO;
if (interfaceOrientation == currentOrientation)
return YES;
return NO;
}
#pragma mark - Event Functions
- (void)orientationDidChange:(NSNotification*)notif {
// Update rotation
UIInterfaceOrientation correctOrientation = [self getCorrectInterfaceOrientation:[[UIDevice currentDevice] orientation]];
if(currentOrientation != correctOrientation) {
[UICompositeViewController setOrientation:correctOrientation animated:currentOrientation != UIDeviceOrientationUnknown];
}
- (void)orientationDidChange:(NSNotification *)notif {
// Update rotation
UIInterfaceOrientation correctOrientation =
[self getCorrectInterfaceOrientation:[[UIDevice currentDevice] orientation]];
if (currentOrientation != correctOrientation) {
[UICompositeViewController setOrientation:correctOrientation
animated:currentOrientation != UIDeviceOrientationUnknown];
}
}
#pragma mark -
/*
Will simulate a device rotation
*/
+ (void)setOrientation:(UIInterfaceOrientation)orientation animated:(BOOL)animated {
UIView *firstResponder = nil;
UIView *firstResponder = nil;
UIViewController *controller = nil;
UIViewController *controller = nil;
controller = [[UIApplication sharedApplication] keyWindow].rootViewController;
CGRect frame = [[UIScreen mainScreen] bounds];
UIInterfaceOrientation oldOrientation = controller.interfaceOrientation;
controller = [[UIApplication sharedApplication] keyWindow].rootViewController;
CGRect frame = [[UIScreen mainScreen] bounds];
UIInterfaceOrientation oldOrientation = controller.interfaceOrientation;
NSTimeInterval animationDuration = animated? 0.3f : 0.0;
NSTimeInterval animationDuration = animated ? 0.3f : 0.0;
[controller willRotateToInterfaceOrientation:orientation duration:animationDuration];
[controller willAnimateRotationToInterfaceOrientation:orientation duration:animationDuration];
[controller didRotateFromInterfaceOrientation:oldOrientation];
[UIView animateWithDuration:animationDuration animations:^{
[controller.view setFrame:frame];
}];
[controller willRotateToInterfaceOrientation:orientation duration:animationDuration];
[controller willAnimateRotationToInterfaceOrientation:orientation duration:animationDuration];
[controller didRotateFromInterfaceOrientation:oldOrientation];
[UIView animateWithDuration:animationDuration
animations:^{
[controller.view setFrame:frame];
}];
if(firstResponder == nil) {
firstResponder = [UICompositeViewController findFirstResponder:controller.view];
}
if (firstResponder == nil) {
firstResponder = [UICompositeViewController findFirstResponder:controller.view];
}
[[UIApplication sharedApplication] setStatusBarOrientation:orientation animated:animated];
if(firstResponder) {
[firstResponder resignFirstResponder];
[firstResponder becomeFirstResponder];
}
[[UIApplication sharedApplication] setStatusBarOrientation:orientation animated:animated];
if (firstResponder) {
[firstResponder resignFirstResponder];
[firstResponder becomeFirstResponder];
}
}
+ (UIView*)findFirstResponder:(UIView*)view {
if (view.isFirstResponder) {
return view;
}
for (UIView *subView in view.subviews) {
UIView *ret = [UICompositeViewController findFirstResponder:subView];
if (ret != nil)
return ret;
}
return nil;
+ (UIView *)findFirstResponder:(UIView *)view {
if (view.isFirstResponder) {
return view;
}
for (UIView *subView in view.subviews) {
UIView *ret = [UICompositeViewController findFirstResponder:subView];
if (ret != nil)
return ret;
}
return nil;
}
- (void)clearCache:(NSArray *)exclude {
for(NSString *key in [viewControllerCache allKeys]) {
bool remove = true;
if(exclude != nil) {
for (UICompositeViewDescription *description in exclude) {
if([key isEqualToString:description.content] ||
[key isEqualToString:description.stateBar] ||
[key isEqualToString:description.tabBar]
) {
remove = false;
break;
}
}
}
if(remove) {
LOGI(@"Free cached view: %@", key);
[viewControllerCache removeObjectForKey:key];
}
}
for (NSString *key in [viewControllerCache allKeys]) {
bool remove = true;
if (exclude != nil) {
for (UICompositeViewDescription *description in exclude) {
if ([key isEqualToString:description.content] || [key isEqualToString:description.stateBar] ||
[key isEqualToString:description.tabBar]) {
remove = false;
break;
}
}
}
if (remove) {
LOGI(@"Free cached view: %@", key);
[viewControllerCache removeObjectForKey:key];
}
}
}
- (UIInterfaceOrientation)currentOrientation {
return currentOrientation;
return currentOrientation;
}
+ (void)addSubView:(UIViewController*)controller view:(UIView*)view {
if(controller != nil) {
[view addSubview: controller.view];
}
+ (void)addSubView:(UIViewController *)controller view:(UIView *)view {
if (controller != nil) {
[view addSubview:controller.view];
}
}
+ (void)removeSubView:(UIViewController*)controller {
if(controller != nil) {
[controller.view removeFromSuperview];
}
+ (void)removeSubView:(UIViewController *)controller {
if (controller != nil) {
[controller.view removeFromSuperview];
}
}
- (UIViewController*)getCachedController:(NSString*)name {
UIViewController *controller = nil;
if(name != nil) {
controller = [viewControllerCache objectForKey:name];
if(controller == nil) {
controller = [[NSClassFromString(name) alloc] init];
[viewControllerCache setValue:controller forKey:name];
[controller view]; // Load the view
}
}
- (UIViewController *)getCachedController:(NSString *)name {
UIViewController *controller = nil;
if (name != nil) {
controller = [viewControllerCache objectForKey:name];
if (controller == nil) {
controller = [[NSClassFromString(name) alloc] init];
[viewControllerCache setValue:controller forKey:name];
[controller view]; // Load the view
}
}
return controller;
}
- (UIInterfaceOrientation)getCorrectInterfaceOrientation:(UIDeviceOrientation)deviceOrientation {
if(currentViewDescription != nil) {
if (currentViewDescription != nil) {
// If unknown return status bar orientation
if(deviceOrientation == UIDeviceOrientationUnknown && currentOrientation == UIDeviceOrientationUnknown) {
if (deviceOrientation == UIDeviceOrientationUnknown && currentOrientation == UIDeviceOrientationUnknown) {
return [UIApplication sharedApplication].statusBarOrientation;
}
// Don't rotate in UIDeviceOrientationFaceUp UIDeviceOrientationFaceDown
if(!UIDeviceOrientationIsPortrait(deviceOrientation) && !UIDeviceOrientationIsLandscape(deviceOrientation)) {
if(currentOrientation == UIDeviceOrientationUnknown) {
if (!UIDeviceOrientationIsPortrait(deviceOrientation) && !UIDeviceOrientationIsLandscape(deviceOrientation)) {
if (currentOrientation == UIDeviceOrientationUnknown) {
return [UIApplication sharedApplication].statusBarOrientation;
}
deviceOrientation = (UIDeviceOrientation)currentOrientation;
@ -384,229 +383,236 @@
}
}
}
return UIInterfaceOrientationPortrait;
return UIInterfaceOrientationPortrait;
}
#define IPHONE_STATUSBAR_HEIGHT 20
- (void)update: (UICompositeViewDescription*) description tabBar:(NSNumber*)tabBar stateBar:(NSNumber*)stateBar fullscreen:(NSNumber*)fullscreen {
- (void)update:(UICompositeViewDescription *)description
tabBar:(NSNumber *)tabBar
stateBar:(NSNumber *)stateBar
fullscreen:(NSNumber *)fullscreen {
UIViewController *oldContentViewController = self.contentViewController;
UIViewController *oldStateBarViewController = self.stateBarViewController;
UIViewController *oldTabBarViewController = self.tabBarViewController;
// Copy view description
UICompositeViewDescription *oldViewDescription = nil;
UIViewController *oldContentViewController = self.contentViewController;
UIViewController *oldStateBarViewController = self.stateBarViewController;
UIViewController *oldTabBarViewController = self.tabBarViewController;
// Copy view description
UICompositeViewDescription *oldViewDescription = nil;
if(description != nil) {
oldViewDescription = currentViewDescription;
currentViewDescription = [description copy];
if (description != nil) {
oldViewDescription = currentViewDescription;
currentViewDescription = [description copy];
// Animate only with a previous screen
if(oldViewDescription != nil && viewTransition != nil) {
[contentView.layer removeAnimationForKey:@"transition"];
[contentView.layer addAnimation:viewTransition forKey:@"transition"];
if(oldViewDescription.stateBar != currentViewDescription.stateBar ||
oldViewDescription.stateBarEnabled != currentViewDescription.stateBarEnabled ||
[stateBarView.layer animationForKey:@"transition"] != nil) {
[stateBarView.layer removeAnimationForKey:@"transition"];
[stateBarView.layer addAnimation:viewTransition forKey:@"transition"];
}
if(oldViewDescription.tabBar != currentViewDescription.tabBar ||
oldViewDescription.tabBarEnabled != currentViewDescription.tabBarEnabled ||
[tabBarView.layer animationForKey:@"transition"] != nil) {
[tabBarView.layer removeAnimationForKey:@"transition"];
[tabBarView.layer addAnimation:viewTransition forKey:@"transition"];
}
}
// Animate only with a previous screen
if (oldViewDescription != nil && viewTransition != nil) {
[contentView.layer removeAnimationForKey:@"transition"];
[contentView.layer addAnimation:viewTransition forKey:@"transition"];
if (oldViewDescription.stateBar != currentViewDescription.stateBar ||
oldViewDescription.stateBarEnabled != currentViewDescription.stateBarEnabled ||
[stateBarView.layer animationForKey:@"transition"] != nil) {
[stateBarView.layer removeAnimationForKey:@"transition"];
[stateBarView.layer addAnimation:viewTransition forKey:@"transition"];
}
if (oldViewDescription.tabBar != currentViewDescription.tabBar ||
oldViewDescription.tabBarEnabled != currentViewDescription.tabBarEnabled ||
[tabBarView.layer animationForKey:@"transition"] != nil) {
[tabBarView.layer removeAnimationForKey:@"transition"];
[tabBarView.layer addAnimation:viewTransition forKey:@"transition"];
}
}
UIViewController *newContentViewController = [self getCachedController:description.content];
UIViewController *newStateBarViewController = [self getCachedController:description.stateBar];
UIViewController *newTabBarViewController = [self getCachedController:description.tabBar];
UIViewController *newContentViewController = [self getCachedController:description.content];
UIViewController *newStateBarViewController = [self getCachedController:description.stateBar];
UIViewController *newTabBarViewController = [self getCachedController:description.tabBar];
[UICompositeViewController removeSubView: oldContentViewController];
if(oldTabBarViewController != nil && oldTabBarViewController != newTabBarViewController) {
[UICompositeViewController removeSubView:oldTabBarViewController];
}
if(oldStateBarViewController != nil && oldStateBarViewController != newStateBarViewController) {
[UICompositeViewController removeSubView:oldStateBarViewController];
}
[UICompositeViewController removeSubView:oldContentViewController];
if (oldTabBarViewController != nil && oldTabBarViewController != newTabBarViewController) {
[UICompositeViewController removeSubView:oldTabBarViewController];
}
if (oldStateBarViewController != nil && oldStateBarViewController != newStateBarViewController) {
[UICompositeViewController removeSubView:oldStateBarViewController];
}
self.stateBarViewController = newStateBarViewController;
self.contentViewController = newContentViewController;
self.tabBarViewController = newTabBarViewController;
self.stateBarViewController = newStateBarViewController;
self.contentViewController = newContentViewController;
self.tabBarViewController = newTabBarViewController;
// Update rotation
UIInterfaceOrientation correctOrientation = [self getCorrectInterfaceOrientation:(UIDeviceOrientation)[UIApplication sharedApplication].statusBarOrientation];
if(currentOrientation != correctOrientation) {
[UICompositeViewController setOrientation:correctOrientation animated:currentOrientation!=UIDeviceOrientationUnknown];
if( UIInterfaceOrientationIsLandscape(correctOrientation) ){
[self.contentViewController willAnimateRotationToInterfaceOrientation:correctOrientation duration:0];
[self.tabBarViewController willAnimateRotationToInterfaceOrientation:correctOrientation duration:0];
[self.stateBarViewController willAnimateRotationToInterfaceOrientation:correctOrientation duration:0];
}
} else {
if(oldContentViewController != newContentViewController) {
UIInterfaceOrientation oldOrientation = self.contentViewController.interfaceOrientation;
[self.contentViewController willRotateToInterfaceOrientation:correctOrientation duration:0];
[self.contentViewController willAnimateRotationToInterfaceOrientation:correctOrientation duration:0];
[self.contentViewController didRotateFromInterfaceOrientation:oldOrientation];
}
if(oldTabBarViewController != newTabBarViewController) {
UIInterfaceOrientation oldOrientation = self.tabBarViewController.interfaceOrientation;
[self.tabBarViewController willRotateToInterfaceOrientation:correctOrientation duration:0];
[self.tabBarViewController willAnimateRotationToInterfaceOrientation:correctOrientation duration:0];
[self.tabBarViewController didRotateFromInterfaceOrientation:oldOrientation];
}
if(oldStateBarViewController != newStateBarViewController) {
UIInterfaceOrientation oldOrientation = self.stateBarViewController.interfaceOrientation;
[self.stateBarViewController willRotateToInterfaceOrientation:correctOrientation duration:0];
[self.stateBarViewController willAnimateRotationToInterfaceOrientation:correctOrientation duration:0];
[self.stateBarViewController didRotateFromInterfaceOrientation:oldOrientation];
}
}
} else {
oldViewDescription = (currentViewDescription != nil)? [currentViewDescription copy]: nil;
}
// Update rotation
UIInterfaceOrientation correctOrientation = [self
getCorrectInterfaceOrientation:(UIDeviceOrientation)[UIApplication sharedApplication].statusBarOrientation];
if (currentOrientation != correctOrientation) {
[UICompositeViewController setOrientation:correctOrientation
animated:currentOrientation != UIDeviceOrientationUnknown];
if (UIInterfaceOrientationIsLandscape(correctOrientation)) {
[self.contentViewController willAnimateRotationToInterfaceOrientation:correctOrientation duration:0];
[self.tabBarViewController willAnimateRotationToInterfaceOrientation:correctOrientation duration:0];
[self.stateBarViewController willAnimateRotationToInterfaceOrientation:correctOrientation duration:0];
}
} else {
if (oldContentViewController != newContentViewController) {
UIInterfaceOrientation oldOrientation = self.contentViewController.interfaceOrientation;
[self.contentViewController willRotateToInterfaceOrientation:correctOrientation duration:0];
[self.contentViewController willAnimateRotationToInterfaceOrientation:correctOrientation duration:0];
[self.contentViewController didRotateFromInterfaceOrientation:oldOrientation];
}
if (oldTabBarViewController != newTabBarViewController) {
UIInterfaceOrientation oldOrientation = self.tabBarViewController.interfaceOrientation;
[self.tabBarViewController willRotateToInterfaceOrientation:correctOrientation duration:0];
[self.tabBarViewController willAnimateRotationToInterfaceOrientation:correctOrientation duration:0];
[self.tabBarViewController didRotateFromInterfaceOrientation:oldOrientation];
}
if (oldStateBarViewController != newStateBarViewController) {
UIInterfaceOrientation oldOrientation = self.stateBarViewController.interfaceOrientation;
[self.stateBarViewController willRotateToInterfaceOrientation:correctOrientation duration:0];
[self.stateBarViewController willAnimateRotationToInterfaceOrientation:correctOrientation duration:0];
[self.stateBarViewController didRotateFromInterfaceOrientation:oldOrientation];
}
}
} else {
oldViewDescription = (currentViewDescription != nil) ? [currentViewDescription copy] : nil;
}
if(currentViewDescription == nil) {
return;
}
if (currentViewDescription == nil) {
return;
}
if(tabBar != nil) {
if(currentViewDescription.tabBarEnabled != [tabBar boolValue]) {
currentViewDescription.tabBarEnabled = [tabBar boolValue];
} else {
tabBar = nil; // No change = No Update
}
}
if (tabBar != nil) {
if (currentViewDescription.tabBarEnabled != [tabBar boolValue]) {
currentViewDescription.tabBarEnabled = [tabBar boolValue];
} else {
tabBar = nil; // No change = No Update
}
}
if(stateBar != nil) {
if(currentViewDescription.stateBarEnabled != [stateBar boolValue]) {
currentViewDescription.stateBarEnabled = [stateBar boolValue];
} else {
stateBar = nil; // No change = No Update
}
}
if (stateBar != nil) {
if (currentViewDescription.stateBarEnabled != [stateBar boolValue]) {
currentViewDescription.stateBarEnabled = [stateBar boolValue];
} else {
stateBar = nil; // No change = No Update
}
}
if(fullscreen != nil) {
if(currentViewDescription.fullscreen != [fullscreen boolValue]) {
currentViewDescription.fullscreen = [fullscreen boolValue];
[[UIApplication sharedApplication] setStatusBarHidden:currentViewDescription.fullscreen withAnimation:UIStatusBarAnimationSlide];
} else {
fullscreen = nil; // No change = No Update
}
} else {
[[UIApplication sharedApplication] setStatusBarHidden:currentViewDescription.fullscreen withAnimation:UIStatusBarAnimationNone];
}
if (fullscreen != nil) {
if (currentViewDescription.fullscreen != [fullscreen boolValue]) {
currentViewDescription.fullscreen = [fullscreen boolValue];
[[UIApplication sharedApplication] setStatusBarHidden:currentViewDescription.fullscreen
withAnimation:UIStatusBarAnimationSlide];
} else {
fullscreen = nil; // No change = No Update
}
} else {
[[UIApplication sharedApplication] setStatusBarHidden:currentViewDescription.fullscreen
withAnimation:UIStatusBarAnimationNone];
}
// Start animation
if(tabBar != nil || stateBar != nil || fullscreen != nil) {
[UIView beginAnimations:@"resize" context:nil];
[UIView setAnimationDuration:0.35];
[UIView setAnimationBeginsFromCurrentState:TRUE];
}
// Start animation
if (tabBar != nil || stateBar != nil || fullscreen != nil) {
[UIView beginAnimations:@"resize" context:nil];
[UIView setAnimationDuration:0.35];
[UIView setAnimationBeginsFromCurrentState:TRUE];
}
CGRect contentFrame = contentView.frame;
CGRect viewFrame = [self.view frame];
CGRect contentFrame = contentView.frame;
CGRect viewFrame = [self.view frame];
// Resize StateBar
CGRect stateBarFrame = stateBarView.frame;
int origin = IPHONE_STATUSBAR_HEIGHT;
if(currentViewDescription.fullscreen)
origin = 0;
// Resize StateBar
CGRect stateBarFrame = stateBarView.frame;
int origin = IPHONE_STATUSBAR_HEIGHT;
if (currentViewDescription.fullscreen)
origin = 0;
if(self.stateBarViewController != nil && currentViewDescription.stateBarEnabled) {
contentFrame.origin.y = origin + stateBarFrame.size.height;
stateBarFrame.origin.y = origin;
} else {
contentFrame.origin.y = origin;
stateBarFrame.origin.y = origin - stateBarFrame.size.height;
}
if (self.stateBarViewController != nil && currentViewDescription.stateBarEnabled) {
contentFrame.origin.y = origin + stateBarFrame.size.height;
stateBarFrame.origin.y = origin;
} else {
contentFrame.origin.y = origin;
stateBarFrame.origin.y = origin - stateBarFrame.size.height;
}
// Resize TabBar
CGRect tabFrame = tabBarView.frame;
if(self.tabBarViewController != nil && currentViewDescription.tabBarEnabled) {
tabFrame.origin.y = viewFrame.size.height;
tabFrame.origin.x = viewFrame.size.width;
tabFrame.size.height = self.tabBarViewController.view.frame.size.height;
//tabFrame.size.width = self.tabBarViewController.view.frame.size.width;
tabFrame.origin.y -= tabFrame.size.height;
tabFrame.origin.x -= tabFrame.size.width;
contentFrame.size.height = tabFrame.origin.y - contentFrame.origin.y;
// Resize TabBar
CGRect tabFrame = tabBarView.frame;
if (self.tabBarViewController != nil && currentViewDescription.tabBarEnabled) {
tabFrame.origin.y = viewFrame.size.height;
tabFrame.origin.x = viewFrame.size.width;
tabFrame.size.height = self.tabBarViewController.view.frame.size.height;
// tabFrame.size.width = self.tabBarViewController.view.frame.size.width;
tabFrame.origin.y -= tabFrame.size.height;
tabFrame.origin.x -= tabFrame.size.width;
contentFrame.size.height = tabFrame.origin.y - contentFrame.origin.y;
// for some views, we need the content to overlap, in which case
// we insert in the tab XIB a mask with tag -1 and with y = the amount of
// points that the content should overlap.
for (UIView *view in self.tabBarViewController.view.subviews) {
if(view.tag == -1) {
contentFrame.size.height += view.frame.origin.y;
break;
}
}
} else {
contentFrame.size.height = viewFrame.size.height - contentFrame.origin.y;
tabFrame.origin.y = viewFrame.size.height;
}
// for some views, we need the content to overlap, in which case
// we insert in the tab XIB a mask with tag -1 and with y = the amount of
// points that the content should overlap.
for (UIView *view in self.tabBarViewController.view.subviews) {
if (view.tag == -1) {
contentFrame.size.height += view.frame.origin.y;
break;
}
}
} else {
contentFrame.size.height = viewFrame.size.height - contentFrame.origin.y;
tabFrame.origin.y = viewFrame.size.height;
}
if(currentViewDescription.fullscreen) {
contentFrame.origin.y = origin;
contentFrame.size.height = viewFrame.size.height - contentFrame.origin.y;
}
if (currentViewDescription.fullscreen) {
contentFrame.origin.y = origin;
contentFrame.size.height = viewFrame.size.height - contentFrame.origin.y;
}
// Set frames
[contentView setFrame: contentFrame];
[self.contentViewController.view setFrame: [contentView bounds]];
[tabBarView setFrame: tabFrame];
CGRect frame = [self.tabBarViewController.view frame];
frame.size.width = [tabBarView bounds].size.width;
[self.tabBarViewController.view setFrame:frame];
[stateBarView setFrame: stateBarFrame];
frame = [self.stateBarViewController.view frame];
frame.size.width = [stateBarView bounds].size.width;
[self.stateBarViewController.view setFrame:frame];
// Set frames
[contentView setFrame:contentFrame];
[self.contentViewController.view setFrame:[contentView bounds]];
[tabBarView setFrame:tabFrame];
CGRect frame = [self.tabBarViewController.view frame];
frame.size.width = [tabBarView bounds].size.width;
[self.tabBarViewController.view setFrame:frame];
[stateBarView setFrame:stateBarFrame];
frame = [self.stateBarViewController.view frame];
frame.size.width = [stateBarView bounds].size.width;
[self.stateBarViewController.view setFrame:frame];
// Commit animation
if(tabBar != nil || stateBar != nil || fullscreen != nil) {
[UIView commitAnimations];
}
// Commit animation
if (tabBar != nil || stateBar != nil || fullscreen != nil) {
[UIView commitAnimations];
}
// Change view
if(description != nil) {
[UICompositeViewController addSubView: self.contentViewController view:contentView];
if(oldTabBarViewController == nil || oldTabBarViewController != self.tabBarViewController) {
[UICompositeViewController addSubView: self.tabBarViewController view:tabBarView];
}
if(oldStateBarViewController == nil || oldStateBarViewController != self.stateBarViewController) {
[UICompositeViewController addSubView: self.stateBarViewController view:stateBarView];
}
}
// Change view
if (description != nil) {
[UICompositeViewController addSubView:self.contentViewController view:contentView];
if (oldTabBarViewController == nil || oldTabBarViewController != self.tabBarViewController) {
[UICompositeViewController addSubView:self.tabBarViewController view:tabBarView];
}
if (oldStateBarViewController == nil || oldStateBarViewController != self.stateBarViewController) {
[UICompositeViewController addSubView:self.stateBarViewController view:stateBarView];
}
}
// Dealloc old view description
// Dealloc old view description
}
- (void) changeView:(UICompositeViewDescription *)description {
[self view]; // Force view load
[self update:description tabBar:nil stateBar:nil fullscreen:nil];
- (void)changeView:(UICompositeViewDescription *)description {
[self view]; // Force view load
[self update:description tabBar:nil stateBar:nil fullscreen:nil];
}
- (void) setFullScreen:(BOOL) enabled {
[self update:nil tabBar:nil stateBar:nil fullscreen:[NSNumber numberWithBool:enabled]];
- (void)setFullScreen:(BOOL)enabled {
[self update:nil tabBar:nil stateBar:nil fullscreen:[NSNumber numberWithBool:enabled]];
}
- (void) setToolBarHidden:(BOOL) hidden {
[self update:nil tabBar:[NSNumber numberWithBool:!hidden] stateBar:nil fullscreen:nil];
- (void)setToolBarHidden:(BOOL)hidden {
[self update:nil tabBar:[NSNumber numberWithBool:!hidden] stateBar:nil fullscreen:nil];
}
- (void) setStateBarHidden:(BOOL) hidden {
[self update:nil tabBar: nil stateBar:[NSNumber numberWithBool:!hidden] fullscreen:nil];
- (void)setStateBarHidden:(BOOL)hidden {
[self update:nil tabBar:nil stateBar:[NSNumber numberWithBool:!hidden] fullscreen:nil];
}
- (UIViewController *) getCurrentViewController {
return self.contentViewController;
- (UIViewController *)getCurrentViewController {
return self.contentViewController;
}
- (BOOL)currentViewSupportsLandscape {
return currentViewDescription ? currentViewDescription.landscapeMode : FALSE;
return currentViewDescription ? currentViewDescription.landscapeMode : FALSE;
}
@end

View file

@ -4,16 +4,16 @@
*
* 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 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* the Free Software Foundation; either version 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
@ -26,39 +26,34 @@
@synthesize stateImage;
@synthesize pauseButton;
#pragma mark - Lifecycle Functions
- (id)init {
return [super initWithNibName:@"UIConferenceHeader" bundle:[NSBundle mainBundle]];
return [super initWithNibName:@"UIConferenceHeader" bundle:[NSBundle mainBundle]];
}
#pragma mark - ViewController Functions
- (void)viewDidLoad {
[super viewDidLoad];
// Set selected+over background: IB lack !
[pauseButton setImage:[UIImage imageNamed:@"call_state_pause_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[pauseButton setType:UIPauseButtonType_Conference call:nil];
[super viewDidLoad];
// Set selected+over background: IB lack !
[pauseButton setImage:[UIImage imageNamed:@"call_state_pause_over.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[pauseButton setType:UIPauseButtonType_Conference call:nil];
}
#pragma mark - Static size Functions
+ (int)getHeight {
return 50;
return 50;
}
#pragma mark -
#pragma mark -
- (void)update {
[self view]; // Force view load
[stateImage setHidden:true];
[pauseButton update];
[self view]; // Force view load
[stateImage setHidden:true];
[pauseButton update];
}
@end

View file

@ -28,111 +28,106 @@
@synthesize avatarImage;
@synthesize contact;
#pragma mark - Lifecycle Functions
- (id)initWithIdentifier:(NSString*)identifier {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"UIContactCell"
owner:self
options:nil];
- (id)initWithIdentifier:(NSString *)identifier {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"UIContactCell" owner:self options:nil];
if ([arrayOfViews count] >= 1) {
[self.contentView addSubview:[arrayOfViews objectAtIndex:0] ];
}
}
return self;
if ([arrayOfViews count] >= 1) {
[self.contentView addSubview:[arrayOfViews objectAtIndex:0]];
}
}
return self;
}
#pragma mark - Property Functions
- (void)setContact:(ABRecordRef)acontact {
contact = acontact;
[self update];
contact = acontact;
[self update];
}
#pragma mark -
- (void)touchUp:(id) sender {
[self setHighlighted:true animated:true];
- (void)touchUp:(id)sender {
[self setHighlighted:true animated:true];
}
- (void)touchDown:(id) sender {
[self setHighlighted:false animated:true];
- (void)touchDown:(id)sender {
[self setHighlighted:false animated:true];
}
- (NSString *)accessibilityLabel {
return [NSString stringWithFormat:@"%@ %@", firstNameLabel.text, lastNameLabel.text];
return [NSString stringWithFormat:@"%@ %@", firstNameLabel.text, lastNameLabel.text];
}
- (void)update {
if(contact == NULL) {
LOGW(@"Cannot update contact cell: null contact");
return;
}
if (contact == NULL) {
LOGW(@"Cannot update contact cell: null contact");
return;
}
NSString* lFirstName = CFBridgingRelease(ABRecordCopyValue(contact, kABPersonFirstNameProperty));
NSString* lLocalizedFirstName = [FastAddressBook localizedLabel:lFirstName];
NSString *lFirstName = CFBridgingRelease(ABRecordCopyValue(contact, kABPersonFirstNameProperty));
NSString *lLocalizedFirstName = [FastAddressBook localizedLabel:lFirstName];
NSString* lLastName = CFBridgingRelease(ABRecordCopyValue(contact, kABPersonLastNameProperty));
NSString* lLocalizedLastName = [FastAddressBook localizedLabel:lLastName];
NSString *lLastName = CFBridgingRelease(ABRecordCopyValue(contact, kABPersonLastNameProperty));
NSString *lLocalizedLastName = [FastAddressBook localizedLabel:lLastName];
NSString* lOrganization = CFBridgingRelease(ABRecordCopyValue(contact, kABPersonOrganizationProperty));
NSString* lLocalizedOrganization = [FastAddressBook localizedLabel:lOrganization];
NSString *lOrganization = CFBridgingRelease(ABRecordCopyValue(contact, kABPersonOrganizationProperty));
NSString *lLocalizedOrganization = [FastAddressBook localizedLabel:lOrganization];
[firstNameLabel setText:(NSString *)(lLocalizedFirstName)];
[lastNameLabel setText:(NSString *)(lLocalizedLastName)];
if(lLocalizedFirstName == nil && lLocalizedLastName == nil) {
if (lLocalizedFirstName == nil && lLocalizedLastName == nil) {
[firstNameLabel setText:(NSString *)(lLocalizedOrganization)];
}
}
- (void)layoutSubviews {
[super layoutSubviews];
//
// Adapt size
//
CGRect firstNameFrame = [firstNameLabel frame];
CGRect lastNameFrame = [lastNameLabel frame];
[super layoutSubviews];
//
// Adapt size
//
CGRect firstNameFrame = [firstNameLabel frame];
CGRect lastNameFrame = [lastNameLabel frame];
// Compute firstName size
CGSize firstNameSize = [[firstNameLabel text] sizeWithFont:[firstNameLabel font]];
CGSize lastNameSize = [[lastNameLabel text] sizeWithFont:[lastNameLabel font]];
float sum = firstNameSize.width + 5 + lastNameSize.width;
float limit = self.bounds.size.width - 5 - firstNameFrame.origin.x;
if(sum >limit) {
firstNameSize.width *= limit/sum;
lastNameSize.width *= limit/sum;
}
// Compute firstName size
CGSize firstNameSize = [[firstNameLabel text] sizeWithFont:[firstNameLabel font]];
CGSize lastNameSize = [[lastNameLabel text] sizeWithFont:[lastNameLabel font]];
float sum = firstNameSize.width + 5 + lastNameSize.width;
float limit = self.bounds.size.width - 5 - firstNameFrame.origin.x;
if (sum > limit) {
firstNameSize.width *= limit / sum;
lastNameSize.width *= limit / sum;
}
firstNameFrame.size.width = firstNameSize.width;
lastNameFrame.size.width = lastNameSize.width;
firstNameFrame.size.width = firstNameSize.width;
lastNameFrame.size.width = lastNameSize.width;
// Compute lastName size & position
lastNameFrame.origin.x = firstNameFrame.origin.x + firstNameFrame.size.width;
if(firstNameFrame.size.width)
lastNameFrame.origin.x += 5;
// Compute lastName size & position
lastNameFrame.origin.x = firstNameFrame.origin.x + firstNameFrame.size.width;
if (firstNameFrame.size.width)
lastNameFrame.origin.x += 5;
[firstNameLabel setFrame: firstNameFrame];
[lastNameLabel setFrame: lastNameFrame];
[firstNameLabel setFrame:firstNameFrame];
[lastNameLabel setFrame:lastNameFrame];
}
- (void)setHighlighted:(BOOL)highlighted {
[self setHighlighted:highlighted animated:FALSE];
[self setHighlighted:highlighted animated:FALSE];
}
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {
[super setHighlighted:highlighted animated:animated];
if(highlighted) {
[lastNameLabel setTextColor:[UIColor whiteColor]];
[firstNameLabel setTextColor:[UIColor whiteColor]];
} else {
[lastNameLabel setTextColor:[UIColor blackColor]];
[firstNameLabel setTextColor:[UIColor blackColor]];
}
[super setHighlighted:highlighted animated:animated];
if (highlighted) {
[lastNameLabel setTextColor:[UIColor whiteColor]];
[firstNameLabel setTextColor:[UIColor whiteColor]];
} else {
[lastNameLabel setTextColor:[UIColor blackColor]];
[firstNameLabel setTextColor:[UIColor blackColor]];
}
}
@end

View file

@ -4,18 +4,18 @@
*
* 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 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* the Free Software Foundation; either version 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "UIContactDetailsFooter.h"
@ -24,55 +24,51 @@
@synthesize removeButton;
@synthesize contactDetailsDelegate;
#pragma mark - Lifecycle Functions
- (void)initUIContactDetailsFooter {
}
- (id)init {
self = [super init];
if(self != nil) {
[self initUIContactDetailsFooter];
}
return self;
self = [super init];
if (self != nil) {
[self initUIContactDetailsFooter];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if(self != nil) {
[self initUIContactDetailsFooter];
}
return self;
self = [super initWithCoder:aDecoder];
if (self != nil) {
[self initUIContactDetailsFooter];
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if(self != nil) {
[self initUIContactDetailsFooter];
}
return self;
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self != nil) {
[self initUIContactDetailsFooter];
}
return self;
}
#pragma mark - Action Functions
- (IBAction)onRemoveClick:(id)event {
if(contactDetailsDelegate != nil) {
[contactDetailsDelegate onRemove:event];
}
if (contactDetailsDelegate != nil) {
[contactDetailsDelegate onRemove:event];
}
}
#pragma mark -
+ (CGFloat)height:(BOOL)editing {
if(editing) {
return 80.0f;
} else {
return 0.000001f; // Hack UITableView = 0
}
if (editing) {
return 80.0f;
} else {
return 0.000001f; // Hack UITableView = 0
}
}
@end

View file

@ -41,326 +41,335 @@
#pragma mark - Lifecycle Functions
- (void)initUIContactDetailsHeader {
propertyList = [[NSArray alloc] initWithObjects:
[NSNumber numberWithInt:kABPersonFirstNameProperty],
[NSNumber numberWithInt:kABPersonLastNameProperty],
[NSNumber numberWithInt:kABPersonOrganizationProperty], nil];
editing = FALSE;
propertyList = [[NSArray alloc] initWithObjects:[NSNumber numberWithInt:kABPersonFirstNameProperty],
[NSNumber numberWithInt:kABPersonLastNameProperty],
[NSNumber numberWithInt:kABPersonOrganizationProperty], nil];
editing = FALSE;
}
- (id)init {
self = [super init];
if(self != nil) {
[self initUIContactDetailsHeader];
}
return self;
self = [super init];
if (self != nil) {
[self initUIContactDetailsHeader];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if(self != nil) {
[self initUIContactDetailsHeader];
}
return self;
self = [super initWithCoder:aDecoder];
if (self != nil) {
[self initUIContactDetailsHeader];
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if(self != nil) {
[self initUIContactDetailsHeader];
}
return self;
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self != nil) {
[self initUIContactDetailsHeader];
}
return self;
}
#pragma mark - ViewController Functions
- (void)viewDidLoad {
[super viewDidLoad];
[tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4
[tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
[normalView setAlpha:1.0f];
[editView setAlpha:0.0f];
[tableView setEditing:TRUE animated:false];
tableView.accessibilityIdentifier = @"Contact Name Table";
[super viewDidLoad];
[tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4
[tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
[normalView setAlpha:1.0f];
[editView setAlpha:0.0f];
[tableView setEditing:TRUE animated:false];
tableView.accessibilityIdentifier = @"Contact Name Table";
}
#pragma mark - Propery Functions
- (void)setContact:(ABRecordRef)acontact {
contact = acontact;
[self update];
contact = acontact;
[self update];
}
#pragma mark -
- (BOOL)isValid {
for (int i = 0; i < [propertyList count]; ++i) {
UIEditableTableViewCell *cell = (UIEditableTableViewCell *)[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
if([cell.detailTextField.text length] > 0)
return true;
}
return false;
for (int i = 0; i < [propertyList count]; ++i) {
UIEditableTableViewCell *cell =
(UIEditableTableViewCell *)[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
if ([cell.detailTextField.text length] > 0)
return true;
}
return false;
}
- (void)update {
if(contact == NULL) {
LOGW(@"Cannot update contact details header: null contact");
return;
}
if (contact == NULL) {
LOGW(@"Cannot update contact details header: null contact");
return;
}
// Avatar image
{
UIImage *image = [FastAddressBook getContactImage:contact thumbnail:false];
if(image == nil) {
image = [UIImage imageNamed:@"avatar_unknown_small.png"];
}
[avatarImage setImage:image];
}
// Avatar image
{
UIImage *image = [FastAddressBook getContactImage:contact thumbnail:false];
if (image == nil) {
image = [UIImage imageNamed:@"avatar_unknown_small.png"];
}
[avatarImage setImage:image];
}
// Contact label
{
[addressLabel setText:[FastAddressBook getContactDisplayName:contact]];
}
// Contact label
{ [addressLabel setText:[FastAddressBook getContactDisplayName:contact]]; }
[tableView reloadData];
[tableView reloadData];
}
+ (CGFloat)height:(BOOL)editing {
if(editing) {
return 170.0f;
} else {
return 80.0f;
}
if (editing) {
return 170.0f;
} else {
return 80.0f;
}
}
- (void)setEditing:(BOOL)aediting animated:(BOOL)animated {
editing = aediting;
// Resign keyboard
if(!editing) {
[LinphoneUtils findAndResignFirstResponder:[self tableView]];
[self update];
}
if(animated) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
}
if(editing) {
[editView setAlpha:1.0f];
[normalView setAlpha:0.0f];
} else {
[editView setAlpha:0.0f];
[normalView setAlpha:1.0f];
}
if(animated) {
[UIView commitAnimations];
}
editing = aediting;
// Resign keyboard
if (!editing) {
[LinphoneUtils findAndResignFirstResponder:[self tableView]];
[self update];
}
if (animated) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
}
if (editing) {
[editView setAlpha:1.0f];
[normalView setAlpha:0.0f];
} else {
[editView setAlpha:0.0f];
[normalView setAlpha:1.0f];
}
if (animated) {
[UIView commitAnimations];
}
}
- (void)setEditing:(BOOL)aediting {
[self setEditing:aediting animated:FALSE];
[self setEditing:aediting animated:FALSE];
}
- (BOOL)isEditing {
return editing;
return editing;
}
- (void)updateModification {
[contactDetailsDelegate onModification:nil];
[contactDetailsDelegate onModification:nil];
}
#pragma mark - UITableViewDataSource Functions
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [propertyList count];
return [propertyList count];
}
- (UITableViewCell *)tableView:(UITableView *)atableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *kCellId = @"ContactDetailsHeaderCell";
UIEditableTableViewCell *cell = [atableView dequeueReusableCellWithIdentifier:kCellId];
if (cell == nil) {
cell = [[UIEditableTableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:kCellId];
[cell.detailTextField setAutocapitalizationType:UITextAutocapitalizationTypeWords];
[cell.detailTextField setAutocorrectionType:UITextAutocorrectionTypeNo];
[cell.detailTextField setKeyboardType:UIKeyboardTypeDefault];
[cell setBackgroundColor:[UIColor whiteColor]];
}
static NSString *kCellId = @"ContactDetailsHeaderCell";
UIEditableTableViewCell *cell = [atableView dequeueReusableCellWithIdentifier:kCellId];
if (cell == nil) {
cell = [[UIEditableTableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:kCellId];
[cell.detailTextField setAutocapitalizationType:UITextAutocapitalizationTypeWords];
[cell.detailTextField setAutocorrectionType:UITextAutocorrectionTypeNo];
[cell.detailTextField setKeyboardType:UIKeyboardTypeDefault];
[cell setBackgroundColor:[UIColor whiteColor]];
}
// setup placeholder
ABPropertyID property = [[propertyList objectAtIndex:[indexPath row]] intValue];
if(property == kABPersonFirstNameProperty) {
[cell.detailTextField setPlaceholder:NSLocalizedString(@"First name", nil)];
} else if (property == kABPersonLastNameProperty) {
[cell.detailTextField setPlaceholder:NSLocalizedString(@"Last name", nil)];
} else if (property == kABPersonOrganizationProperty) {
[cell.detailTextField setPlaceholder:NSLocalizedString(@"Company name", nil)];
}
// setup placeholder
ABPropertyID property = [[propertyList objectAtIndex:[indexPath row]] intValue];
if (property == kABPersonFirstNameProperty) {
[cell.detailTextField setPlaceholder:NSLocalizedString(@"First name", nil)];
} else if (property == kABPersonLastNameProperty) {
[cell.detailTextField setPlaceholder:NSLocalizedString(@"Last name", nil)];
} else if (property == kABPersonOrganizationProperty) {
[cell.detailTextField setPlaceholder:NSLocalizedString(@"Company name", nil)];
}
[cell.detailTextField setKeyboardType:UIKeyboardTypeDefault];
[cell.detailTextField setKeyboardType:UIKeyboardTypeDefault];
// setup values, if they exist
if(contact) {
NSString* lValue = CFBridgingRelease( ABRecordCopyValue(contact, property) );
if(lValue != NULL) {
[cell.detailTextLabel setText:lValue];
[cell.detailTextField setText:lValue];
} else {
[cell.detailTextLabel setText:@""];
[cell.detailTextField setText:@""];
}
}
[cell.detailTextField setDelegate:self];
// setup values, if they exist
if (contact) {
NSString *lValue = CFBridgingRelease(ABRecordCopyValue(contact, property));
if (lValue != NULL) {
[cell.detailTextLabel setText:lValue];
[cell.detailTextField setText:lValue];
} else {
[cell.detailTextLabel setText:@""];
[cell.detailTextField setText:@""];
}
}
[cell.detailTextField setDelegate:self];
return cell;
return cell;
}
#pragma mark - Action Functions
- (IBAction)onAvatarClick:(id)event {
if(self.isEditing) {
void (^showAppropriateController)(UIImagePickerControllerSourceType) = ^(UIImagePickerControllerSourceType type) {
UICompositeViewDescription *description = [ImagePickerViewController compositeViewDescription];
ImagePickerViewController *controller;
if([LinphoneManager runningOnIpad]) {
controller = DYNAMIC_CAST([[PhoneMainView instance].mainViewController getCachedController:description.content], ImagePickerViewController);
// keep a reference to this controller so that in case of memory pressure we keep it
self.popoverController = controller;
} else {
controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:description push:TRUE], ImagePickerViewController);
}
if(controller != nil) {
controller.sourceType = type;
if (self.isEditing) {
void (^showAppropriateController)(UIImagePickerControllerSourceType) =
^(UIImagePickerControllerSourceType type) {
UICompositeViewDescription *description = [ImagePickerViewController compositeViewDescription];
ImagePickerViewController *controller;
if ([LinphoneManager runningOnIpad]) {
controller = DYNAMIC_CAST(
[[PhoneMainView instance].mainViewController getCachedController:description.content],
ImagePickerViewController);
// keep a reference to this controller so that in case of memory pressure we keep it
self.popoverController = controller;
} else {
controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:description push:TRUE],
ImagePickerViewController);
}
if (controller != nil) {
controller.sourceType = type;
// Displays a control that allows the user to choose picture or
// movie capture, if both are available:
controller.mediaTypes = [NSArray arrayWithObject:(NSString *)kUTTypeImage];
// Displays a control that allows the user to choose picture or
// movie capture, if both are available:
controller.mediaTypes = [NSArray arrayWithObject:(NSString *)kUTTypeImage];
// Hides the controls for moving & scaling pictures, or for
// trimming movies. To instead show the controls, use YES.
controller.allowsEditing = NO;
controller.imagePickerDelegate = self;
// Hides the controls for moving & scaling pictures, or for
// trimming movies. To instead show the controls, use YES.
controller.allowsEditing = NO;
controller.imagePickerDelegate = self;
if([LinphoneManager runningOnIpad]) {
[controller.popoverController presentPopoverFromRect:[avatarImage frame] inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:FALSE];
}
}
};
DTActionSheet *sheet = [[DTActionSheet alloc] initWithTitle:NSLocalizedString(@"Select picture source",nil)];
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
[sheet addButtonWithTitle:NSLocalizedString(@"Camera",nil) block:^(){
showAppropriateController(UIImagePickerControllerSourceTypeCamera);
}];
}
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
[sheet addButtonWithTitle:NSLocalizedString(@"Photo library",nil) block:^(){
showAppropriateController(UIImagePickerControllerSourceTypePhotoLibrary);
}];
}
if([FastAddressBook getContactImage:contact thumbnail:true] != nil) {
[sheet addDestructiveButtonWithTitle:NSLocalizedString(@"Remove", nil) block:^(){
CFErrorRef error = NULL;
if(!ABPersonRemoveImageData(contact, (CFErrorRef*)&error)) {
LOGI(@"Can't remove entry: %@", [(__bridge NSError*)error localizedDescription]);
}
[self update];
}];
}
[sheet addCancelButtonWithTitle:NSLocalizedString(@"Cancel",nil) block:^{
self.popoverController = nil;
}];
if ([LinphoneManager runningOnIpad]) {
[controller.popoverController presentPopoverFromRect:[avatarImage frame]
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:FALSE];
}
}
};
DTActionSheet *sheet = [[DTActionSheet alloc] initWithTitle:NSLocalizedString(@"Select picture source", nil)];
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
[sheet addButtonWithTitle:NSLocalizedString(@"Camera", nil)
block:^() {
showAppropriateController(UIImagePickerControllerSourceTypeCamera);
}];
}
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
[sheet addButtonWithTitle:NSLocalizedString(@"Photo library", nil)
block:^() {
showAppropriateController(UIImagePickerControllerSourceTypePhotoLibrary);
}];
}
if ([FastAddressBook getContactImage:contact thumbnail:true] != nil) {
[sheet addDestructiveButtonWithTitle:NSLocalizedString(@"Remove", nil)
block:^() {
CFErrorRef error = NULL;
if (!ABPersonRemoveImageData(contact, (CFErrorRef *)&error)) {
LOGI(@"Can't remove entry: %@",
[(__bridge NSError *)error localizedDescription]);
}
[self update];
}];
}
[sheet addCancelButtonWithTitle:NSLocalizedString(@"Cancel", nil)
block:^{
self.popoverController = nil;
}];
[sheet showInView:[PhoneMainView instance].view];
}
[sheet showInView:[PhoneMainView instance].view];
}
}
#pragma mark - ContactDetailsImagePickerDelegate Functions
- (void)imagePickerDelegateImage:(UIImage*)image info:(NSDictionary *)info{
// Dismiss popover on iPad
if([LinphoneManager runningOnIpad]) {
UICompositeViewDescription *description = [ImagePickerViewController compositeViewDescription];
ImagePickerViewController *controller = DYNAMIC_CAST([[PhoneMainView instance].mainViewController getCachedController:description.content], ImagePickerViewController);
if(controller != nil) {
[controller.popoverController dismissPopoverAnimated:TRUE];
- (void)imagePickerDelegateImage:(UIImage *)image info:(NSDictionary *)info {
// Dismiss popover on iPad
if ([LinphoneManager runningOnIpad]) {
UICompositeViewDescription *description = [ImagePickerViewController compositeViewDescription];
ImagePickerViewController *controller =
DYNAMIC_CAST([[PhoneMainView instance].mainViewController getCachedController:description.content],
ImagePickerViewController);
if (controller != nil) {
[controller.popoverController dismissPopoverAnimated:TRUE];
self.popoverController = nil;
}
}
FastAddressBook* fab = [LinphoneManager instance].fastAddressBook;
CFErrorRef error = NULL;
if(!ABPersonRemoveImageData(contact, (CFErrorRef*)&error)) {
LOGI(@"Can't remove entry: %@", [(__bridge NSError*)error localizedDescription]);
}
NSData *dataRef = UIImageJPEGRepresentation(image, 0.9f);
CFDataRef cfdata = CFDataCreate(NULL,[dataRef bytes], [dataRef length]);
}
}
FastAddressBook *fab = [LinphoneManager instance].fastAddressBook;
CFErrorRef error = NULL;
if (!ABPersonRemoveImageData(contact, (CFErrorRef *)&error)) {
LOGI(@"Can't remove entry: %@", [(__bridge NSError *)error localizedDescription]);
}
NSData *dataRef = UIImageJPEGRepresentation(image, 0.9f);
CFDataRef cfdata = CFDataCreate(NULL, [dataRef bytes], [dataRef length]);
[fab saveAddressBook];
if(!ABPersonSetImageData(contact, cfdata, (CFErrorRef*)&error)) {
LOGI(@"Can't add entry: %@", [(__bridge NSError*)error localizedDescription]);
if (!ABPersonSetImageData(contact, cfdata, (CFErrorRef *)&error)) {
LOGI(@"Can't add entry: %@", [(__bridge NSError *)error localizedDescription]);
} else {
[fab saveAddressBook];
}
CFRelease(cfdata);
CFRelease(cfdata);
[self update];
[self update];
}
#pragma mark - UITableViewDelegate Functions
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleNone;
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView
editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleNone;
}
#pragma mark - UITextFieldDelegate Functions
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
[textField resignFirstResponder];
return YES;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if(contactDetailsDelegate != nil) {
//add a mini delay to have the text updated BEFORE notifying the selector
[self performSelector:@selector(updateModification) withObject:nil afterDelay:0.1];
}
return YES;
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
if (contactDetailsDelegate != nil) {
// add a mini delay to have the text updated BEFORE notifying the selector
[self performSelector:@selector(updateModification) withObject:nil afterDelay:0.1];
}
return YES;
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
UIView *view = [textField superview];
// Find TableViewCell
while(view != nil && ![view isKindOfClass:[UIEditableTableViewCell class]]) view = [view superview];
UIView *view = [textField superview];
// Find TableViewCell
while (view != nil && ![view isKindOfClass:[UIEditableTableViewCell class]])
view = [view superview];
if(view != nil) {
UIEditableTableViewCell *cell = (UIEditableTableViewCell*)view;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
ABPropertyID property = [[propertyList objectAtIndex:[indexPath row]] intValue];
[cell.detailTextLabel setText:[textField text]];
CFErrorRef error = NULL;
ABRecordSetValue(contact, property, (__bridge CFTypeRef)([textField text]), (CFErrorRef*)&error);
if (error != NULL) {
LOGE(@"Error when saving property %i in contact %p: Fail(%@)", property, contact, [(__bridge NSError*)error localizedDescription]);
}
} else {
LOGW(@"Not valid UIEditableTableViewCell");
}
if(contactDetailsDelegate != nil) {
//add a mini delay to have the text updated BEFORE notifying the selector
[self performSelector:@selector(updateModification) withObject:nil afterDelay:0.1];
}
return TRUE;
if (view != nil) {
UIEditableTableViewCell *cell = (UIEditableTableViewCell *)view;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
ABPropertyID property = [[propertyList objectAtIndex:[indexPath row]] intValue];
[cell.detailTextLabel setText:[textField text]];
CFErrorRef error = NULL;
ABRecordSetValue(contact, property, (__bridge CFTypeRef)([textField text]), (CFErrorRef *)&error);
if (error != NULL) {
LOGE(@"Error when saving property %i in contact %p: Fail(%@)", property, contact,
[(__bridge NSError *)error localizedDescription]);
}
} else {
LOGW(@"Not valid UIEditableTableViewCell");
}
if (contactDetailsDelegate != nil) {
// add a mini delay to have the text updated BEFORE notifying the selector
[self performSelector:@selector(updateModification) withObject:nil afterDelay:0.1];
}
return TRUE;
}
@end

View file

@ -4,18 +4,18 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "UIDigitButton.h"
#include "linphone/linphonecore.h"
@ -27,46 +27,45 @@
@synthesize digit;
@synthesize addressField;
#pragma mark - Lifecycle Functions
- (void)initUIDigitButton {
dtmf = FALSE;
dtmf = FALSE;
[self addTarget:self action:@selector(touchDown:) forControlEvents:UIControlEventTouchDown];
[self addTarget:self action:@selector(touchUp:) forControlEvents:UIControlEventTouchUpInside|UIControlEventTouchUpOutside];
[self addTarget:self
action:@selector(touchUp:)
forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
}
- (id)init {
self = [super init];
if (self) {
self = [super init];
if (self) {
[self initUIDigitButton];
}
return self;
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self = [super initWithFrame:frame];
if (self) {
[self initUIDigitButton];
}
return self;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
self = [super initWithCoder:decoder];
if (self) {
[self initUIDigitButton];
}
return self;
}
return self;
}
#pragma mark - Actions Functions
- (void)touchDown:(id) sender {
if (addressField && (!dtmf || !linphone_core_in_call([LinphoneManager getLc]))) {
NSString* newAddress = [NSString stringWithFormat:@"%@%c",addressField.text, digit];
- (void)touchDown:(id)sender {
if (addressField && (!dtmf || !linphone_core_in_call([LinphoneManager getLc]))) {
NSString *newAddress = [NSString stringWithFormat:@"%@%c", addressField.text, digit];
[addressField setText:newAddress];
linphone_core_play_dtmf([LinphoneManager getLc], digit, -1);
} else {
@ -75,7 +74,7 @@
}
}
- (void)touchUp:(id) sender {
- (void)touchUp:(id)sender {
linphone_core_stop_dtmf([LinphoneManager getLc]);
}

View file

@ -27,7 +27,8 @@
}
- (void)onLongTouch {
NSString* newAddress = [[self.addressField.text substringToIndex: [self.addressField.text length]-1] stringByAppendingString:@"+"];
NSString *newAddress =
[[self.addressField.text substringToIndex:[self.addressField.text length] - 1] stringByAppendingString:@"+"];
[self.addressField setText:newAddress];
}

View file

@ -31,12 +31,14 @@
- (void)onLongTouch {
if ([self voiceMailEnabled]) {
LinphoneManager *lm = [LinphoneManager instance];
[lm call:[lm lpConfigStringForKey:@"voice_mail_uri"] displayName:NSLocalizedString(@"Voice mail",nil) transfer:FALSE];
[lm call:[lm lpConfigStringForKey:@"voice_mail_uri"]
displayName:NSLocalizedString(@"Voice mail", nil)
transfer:FALSE];
}
}
- (BOOL) voiceMailEnabled {
NSString * voiceMailUri = [[LinphoneManager instance] lpConfigStringForKey:@"voice_mail_uri" withDefault:NULL];
- (BOOL)voiceMailEnabled {
NSString *voiceMailUri = [[LinphoneManager instance] lpConfigStringForKey:@"voice_mail_uri" withDefault:NULL];
return (voiceMailUri != NULL);
}
@ -48,8 +50,8 @@
name = [name stringByAppendingString:@"voicemail_"];
}
[self setImage:[UIImage imageNamed:[name stringByAppendingString:@"default.png"]] forState: UIControlStateNormal];
[self setImage:[UIImage imageNamed:[name stringByAppendingString:@"over.png"]] forState: UIControlStateHighlighted];
[self setImage:[UIImage imageNamed:[name stringByAppendingString:@"default.png"]] forState:UIControlStateNormal];
[self setImage:[UIImage imageNamed:[name stringByAppendingString:@"over.png"]] forState:UIControlStateHighlighted];
}
@end

View file

@ -4,18 +4,18 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "UIEditableTableViewCell.h"
@ -24,91 +24,84 @@
@synthesize detailTextField;
@synthesize verticalSep;
#pragma mark - Lifecycle Functions
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
UITextField* tf = [[UITextField alloc] init];
[tf setHidden:TRUE];
[tf setClearButtonMode: UITextFieldViewModeWhileEditing];
[tf setContentVerticalAlignment: UIControlContentVerticalAlignmentCenter];
self.detailTextField = tf;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
UITextField *tf = [[UITextField alloc] init];
[tf setHidden:TRUE];
[tf setClearButtonMode:UITextFieldViewModeWhileEditing];
[tf setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];
self.detailTextField = tf;
UIFont *font = [UIFont fontWithName:@"Helvetica-Bold" size:[UIFont systemFontSize]];
[self.detailTextLabel setFont:font];
[self.detailTextField setFont:font];
[self.contentView addSubview:detailTextField];
UIFont *font = [UIFont fontWithName:@"Helvetica-Bold" size:[UIFont systemFontSize]];
[self.detailTextLabel setFont:font];
[self.detailTextField setFont:font];
[self.contentView addSubview:detailTextField];
// a vertical separator that will come between the text and detailed text
UIView* v = [[UIView alloc] initWithFrame:CGRectMake(80, 5, 1, 34)];
[v setBackgroundColor:[UIColor lightGrayColor]];
[v setHidden:TRUE];
// a vertical separator that will come between the text and detailed text
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(80, 5, 1, 34)];
[v setBackgroundColor:[UIColor lightGrayColor]];
[v setHidden:TRUE];
self.verticalSep = v;
self.verticalSep = v;
[self.contentView addSubview:verticalSep];
}
return self;
[self.contentView addSubview:verticalSep];
}
return self;
}
#pragma mark - View Functions
- (void)layoutSubviews {
[super layoutSubviews];
[super layoutSubviews];
CGRect detailEditFrame;
detailEditFrame.origin.x = 15;
detailEditFrame.origin.y = 0;
detailEditFrame.size.height = 44;
CGRect detailEditFrame;
detailEditFrame.origin.x = 15;
detailEditFrame.origin.y = 0;
detailEditFrame.size.height = 44;
if([[self.textLabel text] length] != 0) {
detailEditFrame.origin.x += [self.textLabel frame].size.width + 8;
if ([[self.textLabel text] length] != 0) {
detailEditFrame.origin.x += [self.textLabel frame].size.width + 8;
// shrink left text width by 10px
CGRect leftLabelFrame = [self.textLabel frame];
leftLabelFrame.size.width -= 10;
[self.textLabel setFrame:leftLabelFrame];
// shrink left text width by 10px
CGRect leftLabelFrame = [self.textLabel frame];
leftLabelFrame.size.width -= 10;
[self.textLabel setFrame:leftLabelFrame];
// place separator between left text and detailed text
CGRect separatorFrame = [self.verticalSep frame];
separatorFrame.origin.x = leftLabelFrame.size.width + leftLabelFrame.origin.x + 5;
[self.verticalSep setFrame:separatorFrame];
[self.verticalSep setHidden:FALSE];
}
// place separator between left text and detailed text
CGRect separatorFrame = [self.verticalSep frame];
separatorFrame.origin.x = leftLabelFrame.size.width + leftLabelFrame.origin.x + 5;
[self.verticalSep setFrame:separatorFrame];
[self.verticalSep setHidden:FALSE];
}
// put the detailed text edit view at the correct position
CGRect superframe = [[self.detailTextField superview] frame];
detailEditFrame.size.width = superframe.size.width - detailEditFrame.origin.x;
[self.detailTextField setFrame:detailEditFrame];
// put the detailed text edit view at the correct position
CGRect superframe = [[self.detailTextField superview] frame];
detailEditFrame.size.width = superframe.size.width - detailEditFrame.origin.x;
[self.detailTextField setFrame:detailEditFrame];
}
#pragma mark - UITableViewCell Functions
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
if(editing) {
[self.detailTextField setHidden:FALSE];
[self.detailTextLabel setHidden:TRUE];
} else {
[self.detailTextField setHidden:TRUE];
[self.detailTextLabel setHidden:FALSE];
}
[super setEditing:editing animated:animated];
if (editing) {
[self.detailTextField setHidden:FALSE];
[self.detailTextLabel setHidden:TRUE];
} else {
[self.detailTextField setHidden:TRUE];
[self.detailTextLabel setHidden:FALSE];
}
}
- (void)setEditing:(BOOL)editing {
[self setEditing:editing animated:FALSE];
[self setEditing:editing animated:FALSE];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
}
@end

View file

@ -4,27 +4,25 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "UIEraseButton.h"
@implementation UIEraseButton
@synthesize addressField;
#pragma mark - Lifecycle Functions
- (void)initUIEraseButton {
@ -32,50 +30,48 @@
}
- (id)init {
self = [super init];
if (self) {
self = [super init];
if (self) {
[self initUIEraseButton];
}
return self;
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self = [super initWithFrame:frame];
if (self) {
[self initUIEraseButton];
}
return self;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
self = [super initWithCoder:decoder];
if (self) {
[self initUIEraseButton];
}
return self;
}
return self;
}
- (void)dealloc {
addressField = nil;
}
#pragma mark - Action Functions
-(void) touchDown:(id) sender {
if ([addressField.text length] > 0) {
[addressField setText:[addressField.text substringToIndex:[addressField.text length]-1]];
}
- (void)touchDown:(id)sender {
if ([addressField.text length] > 0) {
[addressField setText:[addressField.text substringToIndex:[addressField.text length] - 1]];
}
}
#pragma mark - UILongTouchButtonDelegate Functions
- (void)onRepeatTouch {
}
- (void)onLongTouch {
[addressField setText:@""];
[addressField setText:@""];
}
@end

View file

@ -4,113 +4,107 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "UIHangUpButton.h"
#import "LinphoneManager.h"
@implementation UIHangUpButton
#pragma mark - Static Functions
+ (bool)isInConference:(LinphoneCall*) call {
if (!call)
return false;
return linphone_call_is_in_conference(call);
+ (bool)isInConference:(LinphoneCall *)call {
if (!call)
return false;
return linphone_call_is_in_conference(call);
}
+ (int)callCount:(LinphoneCore*) lc {
int count = 0;
const MSList* calls = linphone_core_get_calls(lc);
while (calls != 0) {
if (![UIHangUpButton isInConference:((LinphoneCall*)calls->data)]) {
count++;
}
calls = calls->next;
}
return count;
}
+ (int)callCount:(LinphoneCore *)lc {
int count = 0;
const MSList *calls = linphone_core_get_calls(lc);
while (calls != 0) {
if (![UIHangUpButton isInConference:((LinphoneCall *)calls->data)]) {
count++;
}
calls = calls->next;
}
return count;
}
#pragma mark - Lifecycle Functions
- (void)initUIHangUpButton {
[self addTarget:self action:@selector(touchUp:) forControlEvents:UIControlEventTouchUpInside];
[self addTarget:self action:@selector(touchUp:) forControlEvents:UIControlEventTouchUpInside];
}
- (id)init{
self = [super init];
if (self) {
- (id)init {
self = [super init];
if (self) {
[self initUIHangUpButton];
}
return self;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
self = [super initWithCoder:decoder];
if (self) {
[self initUIHangUpButton];
}
return self;
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self = [super initWithFrame:frame];
if (self) {
[self initUIHangUpButton];
}
return self;
}
return self;
}
#pragma mark -
#pragma mark -
- (void)update {
LinphoneCore * lc = [LinphoneManager getLc];
if(linphone_core_get_calls_nb(lc) == 1 || // One call
linphone_core_get_current_call(lc) != NULL || // In call
linphone_core_is_in_conference(lc) || // In conference
(linphone_core_get_conference_size(lc) > 0 && [UIHangUpButton callCount:lc] == 0) // Only one conf
) {
[self setEnabled:true];
return;
}
[self setEnabled:false];
LinphoneCore *lc = [LinphoneManager getLc];
if (linphone_core_get_calls_nb(lc) == 1 || // One call
linphone_core_get_current_call(lc) != NULL || // In call
linphone_core_is_in_conference(lc) || // In conference
(linphone_core_get_conference_size(lc) > 0 && [UIHangUpButton callCount:lc] == 0) // Only one conf
) {
[self setEnabled:true];
return;
}
[self setEnabled:false];
}
#pragma mark - Action Functions
-(void) touchUp:(id) sender {
LinphoneCore* lc = [LinphoneManager getLc];
LinphoneCall* currentcall = linphone_core_get_current_call(lc);
if (linphone_core_is_in_conference(lc) || // In conference
(linphone_core_get_conference_size(lc) > 0 && [UIHangUpButton callCount:lc] == 0) // Only one conf
) {
linphone_core_terminate_conference(lc);
} else if(currentcall != NULL) { // In a call
linphone_core_terminate_call(lc, currentcall);
} else {
const MSList* calls = linphone_core_get_calls(lc);
if (ms_list_size(calls) == 1) { // Only one call
linphone_core_terminate_call(lc,(LinphoneCall*)(calls->data));
}
}
- (void)touchUp:(id)sender {
LinphoneCore *lc = [LinphoneManager getLc];
LinphoneCall *currentcall = linphone_core_get_current_call(lc);
if (linphone_core_is_in_conference(lc) || // In conference
(linphone_core_get_conference_size(lc) > 0 && [UIHangUpButton callCount:lc] == 0) // Only one conf
) {
linphone_core_terminate_conference(lc);
} else if (currentcall != NULL) { // In a call
linphone_core_terminate_call(lc, currentcall);
} else {
const MSList *calls = linphone_core_get_calls(lc);
if (ms_list_size(calls) == 1) { // Only one call
linphone_core_terminate_call(lc, (LinphoneCall *)(calls->data));
}
}
}
@end

View file

@ -32,143 +32,143 @@
#pragma mark - Lifecycle Functions
- (id)initWithIdentifier:(NSString*)identifier {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"UIHistoryCell"
owner:self
options:nil];
- (id)initWithIdentifier:(NSString *)identifier {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"UIHistoryCell" owner:self options:nil];
if ([arrayOfViews count] >= 1) {
[self.contentView addSubview:[arrayOfViews objectAtIndex:0]];
}
if ([arrayOfViews count] >= 1) {
[self.contentView addSubview:[arrayOfViews objectAtIndex:0]];
}
self->callLog = NULL;
}
return self;
self->callLog = NULL;
}
return self;
}
#pragma mark - Action Functions
- (void)setCallLog:(LinphoneCallLog *)acallLog {
callLog = acallLog;
[self update];
callLog = acallLog;
[self update];
}
#pragma mark - Action Functions
- (IBAction)onDetails:(id) event {
if(callLog != NULL && linphone_call_log_get_call_id(callLog) != NULL) {
// Go to History details view
HistoryDetailsViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[HistoryDetailsViewController compositeViewDescription] push:TRUE], HistoryDetailsViewController);
if(controller != nil) {
[controller setCallLogId: [NSString stringWithUTF8String:linphone_call_log_get_call_id(callLog)]];
}
}
- (IBAction)onDetails:(id)event {
if (callLog != NULL && linphone_call_log_get_call_id(callLog) != NULL) {
// Go to History details view
HistoryDetailsViewController *controller = DYNAMIC_CAST(
[[PhoneMainView instance] changeCurrentView:[HistoryDetailsViewController compositeViewDescription]
push:TRUE],
HistoryDetailsViewController);
if (controller != nil) {
[controller setCallLogId:[NSString stringWithUTF8String:linphone_call_log_get_call_id(callLog)]];
}
}
}
- (IBAction)onDelete:(id)event {
if(callLog != NULL) {
UIView *view = [self superview];
// Find TableViewCell
while(view != nil && ![view isKindOfClass:[UITableView class]]) view = [view superview];
if(view != nil) {
UITableView *tableView = (UITableView*) view;
NSIndexPath *indexPath = [tableView indexPathForCell:self];
[[tableView dataSource] tableView:tableView commitEditingStyle:UITableViewCellEditingStyleDelete forRowAtIndexPath:indexPath];
}
}
if (callLog != NULL) {
UIView *view = [self superview];
// Find TableViewCell
while (view != nil && ![view isKindOfClass:[UITableView class]])
view = [view superview];
if (view != nil) {
UITableView *tableView = (UITableView *)view;
NSIndexPath *indexPath = [tableView indexPathForCell:self];
[[tableView dataSource] tableView:tableView
commitEditingStyle:UITableViewCellEditingStyleDelete
forRowAtIndexPath:indexPath];
}
}
}
#pragma mark -
- (NSString *)accessibilityValue {
// TODO: localize?
BOOL incoming = linphone_call_log_get_dir(callLog) == LinphoneCallIncoming;
BOOL missed = linphone_call_log_get_status(callLog) == LinphoneCallMissed;
// TODO: localize?
BOOL incoming = linphone_call_log_get_dir(callLog) == LinphoneCallIncoming;
BOOL missed = linphone_call_log_get_status(callLog) == LinphoneCallMissed;
NSString* call_type = @"Outgoing";
if( incoming ){
call_type = missed?@"Missed" : @"Incoming";
}
NSString *call_type = @"Outgoing";
if (incoming) {
call_type = missed ? @"Missed" : @"Incoming";
}
return [NSString stringWithFormat:@"%@ from %@", call_type, addressLabel.text];
return [NSString stringWithFormat:@"%@ from %@", call_type, addressLabel.text];
}
- (void)update {
if(callLog == NULL) {
LOGW(@"Cannot update history cell: null callLog");
return;
}
if (callLog == NULL) {
LOGW(@"Cannot update history cell: null callLog");
return;
}
// Set up the cell...
LinphoneAddress* addr;
// Set up the cell...
LinphoneAddress *addr;
UIImage *image;
if (linphone_call_log_get_dir(callLog) == LinphoneCallIncoming) {
if (linphone_call_log_get_status(callLog) != LinphoneCallMissed) {
image = [UIImage imageNamed:@"call_status_incoming.png"];
} else {
image = [UIImage imageNamed:@"call_status_missed.png"];
}
if (linphone_call_log_get_status(callLog) != LinphoneCallMissed) {
image = [UIImage imageNamed:@"call_status_incoming.png"];
} else {
image = [UIImage imageNamed:@"call_status_missed.png"];
}
addr = linphone_call_log_get_from(callLog);
} else {
image = [UIImage imageNamed:@"call_status_outgoing.png"];
addr = linphone_call_log_get_to(callLog);
}
NSString* address = nil;
if(addr != NULL) {
BOOL useLinphoneAddress = true;
// contact name
char* lAddress = linphone_address_as_string_uri_only(addr);
if(lAddress) {
NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:[NSString stringWithUTF8String:lAddress]];
ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:normalizedSipAddress];
if(contact) {
address = [FastAddressBook getContactDisplayName:contact];
useLinphoneAddress = false;
}
ms_free(lAddress);
}
if(useLinphoneAddress) {
const char* lDisplayName = linphone_address_get_display_name(addr);
const char* lUserName = linphone_address_get_username(addr);
if (lDisplayName)
address = [NSString stringWithUTF8String:lDisplayName];
else if(lUserName)
address = [NSString stringWithUTF8String:lUserName];
}
}
if(address == nil) {
address = NSLocalizedString(@"Unknown", nil);
}
NSString *address = nil;
if (addr != NULL) {
BOOL useLinphoneAddress = true;
// contact name
char *lAddress = linphone_address_as_string_uri_only(addr);
if (lAddress) {
NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:[NSString stringWithUTF8String:lAddress]];
ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:normalizedSipAddress];
if (contact) {
address = [FastAddressBook getContactDisplayName:contact];
useLinphoneAddress = false;
}
ms_free(lAddress);
}
if (useLinphoneAddress) {
const char *lDisplayName = linphone_address_get_display_name(addr);
const char *lUserName = linphone_address_get_username(addr);
if (lDisplayName)
address = [NSString stringWithUTF8String:lDisplayName];
else if (lUserName)
address = [NSString stringWithUTF8String:lUserName];
}
}
if (address == nil) {
address = NSLocalizedString(@"Unknown", nil);
}
[addressLabel setText:address];
[imageView setImage: image];
[addressLabel setText:address];
[imageView setImage:image];
}
- (void)setEditing:(BOOL)editing {
[self setEditing:editing animated:FALSE];
[self setEditing:editing animated:FALSE];
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
if(animated) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
}
if(editing) {
[deleteButton setAlpha:1.0f];
[detailsButton setAlpha:0.0f];
} else {
[detailsButton setAlpha:1.0f];
[deleteButton setAlpha:0.0f];
}
if(animated) {
[UIView commitAnimations];
}
if (animated) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
}
if (editing) {
[deleteButton setAlpha:1.0f];
[detailsButton setAlpha:0.0f];
} else {
[detailsButton setAlpha:1.0f];
[deleteButton setAlpha:0.0f];
}
if (animated) {
[UIView commitAnimations];
}
}
@end

View file

@ -26,103 +26,101 @@
@implementation UIColor (LightAndDark)
- (UIColor *)lumColor:(float)mult {
float hsbH, hsbS, hsbB;
float rgbaR, rgbaG, rgbaB, rgbaA;
float hsbH, hsbS, hsbB;
float rgbaR, rgbaG, rgbaB, rgbaA;
// Get RGB
CGColorRef cgColor = [self CGColor];
CGColorSpaceRef cgColorSpace = CGColorGetColorSpace(cgColor);
if(CGColorSpaceGetModel(cgColorSpace) != kCGColorSpaceModelRGB) {
LOGW(@"Can't convert not RGB color");
return self;
} else {
const CGFloat *colors = CGColorGetComponents(cgColor);
rgbaR = colors[0];
rgbaG = colors[1];
rgbaB = colors[2];
rgbaA = CGColorGetAlpha(cgColor);
}
// Get RGB
CGColorRef cgColor = [self CGColor];
CGColorSpaceRef cgColorSpace = CGColorGetColorSpace(cgColor);
if (CGColorSpaceGetModel(cgColorSpace) != kCGColorSpaceModelRGB) {
LOGW(@"Can't convert not RGB color");
return self;
} else {
const CGFloat *colors = CGColorGetComponents(cgColor);
rgbaR = colors[0];
rgbaG = colors[1];
rgbaB = colors[2];
rgbaA = CGColorGetAlpha(cgColor);
}
RGB2HSL(rgbaR, rgbaG, rgbaB, &hsbH, &hsbS, &hsbB);
RGB2HSL(rgbaR, rgbaG, rgbaB, &hsbH, &hsbS, &hsbB);
hsbB = MIN(MAX(hsbB * mult, 0.0), 1.0);
hsbB = MIN(MAX(hsbB * mult, 0.0), 1.0);
HSL2RGB(hsbH, hsbS, hsbB, &rgbaR, &rgbaG, &rgbaB);
HSL2RGB(hsbH, hsbS, hsbB, &rgbaR, &rgbaG, &rgbaB);
return [UIColor colorWithRed:rgbaR green:rgbaG blue:rgbaB alpha:rgbaA];
return [UIColor colorWithRed:rgbaR green:rgbaG blue:rgbaB alpha:rgbaA];
}
- (UIColor *)adjustHue:(float)hm saturation:(float)sm brightness:(float)bm alpha:(float)am {
float hsbH, hsbS, hsbB;
float rgbaR, rgbaG, rgbaB, rgbaA;
float hsbH, hsbS, hsbB;
float rgbaR, rgbaG, rgbaB, rgbaA;
// Get RGB
CGColorRef cgColor = [self CGColor];
CGColorSpaceRef cgColorSpace = CGColorGetColorSpace(cgColor);
if (CGColorSpaceGetModel(cgColorSpace) != kCGColorSpaceModelRGB) {
LOGW(@"Can't convert not RGB color");
return self;
} else {
const CGFloat *colors = CGColorGetComponents(cgColor);
rgbaR = colors[0];
rgbaG = colors[1];
rgbaB = colors[2];
rgbaA = CGColorGetAlpha(cgColor);
}
// Get RGB
CGColorRef cgColor = [self CGColor];
CGColorSpaceRef cgColorSpace = CGColorGetColorSpace(cgColor);
if(CGColorSpaceGetModel(cgColorSpace) != kCGColorSpaceModelRGB) {
LOGW(@"Can't convert not RGB color");
return self;
} else {
const CGFloat *colors = CGColorGetComponents(cgColor);
rgbaR = colors[0];
rgbaG = colors[1];
rgbaB = colors[2];
rgbaA = CGColorGetAlpha(cgColor);
}
RGB2HSL(rgbaR, rgbaG, rgbaB, &hsbH, &hsbS, &hsbB);
RGB2HSL(rgbaR, rgbaG, rgbaB, &hsbH, &hsbS, &hsbB);
hsbH = MIN(MAX(hsbH + hm, 0.0), 1.0);
hsbS = MIN(MAX(hsbS + sm, 0.0), 1.0);
hsbB = MIN(MAX(hsbB + bm, 0.0), 1.0);
rgbaA = MIN(MAX(rgbaA + am, 0.0), 1.0);
hsbH = MIN(MAX(hsbH + hm, 0.0), 1.0);
hsbS = MIN(MAX(hsbS + sm, 0.0), 1.0);
hsbB = MIN(MAX(hsbB + bm, 0.0), 1.0);
rgbaA = MIN(MAX(rgbaA + am, 0.0), 1.0);
HSL2RGB(hsbH, hsbS, hsbB, &rgbaR, &rgbaG, &rgbaB);
HSL2RGB(hsbH, hsbS, hsbB, &rgbaR, &rgbaG, &rgbaB);
return [UIColor colorWithRed:rgbaR green:rgbaG blue:rgbaB alpha:rgbaA];
return [UIColor colorWithRed:rgbaR green:rgbaG blue:rgbaB alpha:rgbaA];
}
- (UIColor *)lighterColor {
return [self lumColor:1.3];
return [self lumColor:1.3];
}
- (UIColor *)darkerColor {
return [self lumColor:0.75];
return [self lumColor:0.75];
}
@end
@implementation UIImage (ForceDecode)
+ (UIImage *)decodedImageWithImage:(UIImage *)image
{
CGImageRef imageRef = image.CGImage;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL,
CGImageGetWidth(imageRef),
CGImageGetHeight(imageRef),
8,
// Just always return width * 4 will be enough
CGImageGetWidth(imageRef) * 4,
// System only supports RGB, set explicitly
colorSpace,
// Makes system don't need to do extra conversion when displayed.
// NOTE: here we remove the alpha channel for performance. Most of the time, images loaded
// from the network are jpeg with no alpha channel. As a TODO, finding a way to detect
// if alpha channel is necessary would be nice.
kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Little);
CGColorSpaceRelease(colorSpace);
if (!context) return nil;
+ (UIImage *)decodedImageWithImage:(UIImage *)image {
CGImageRef imageRef = image.CGImage;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(
NULL, CGImageGetWidth(imageRef), CGImageGetHeight(imageRef), 8,
// Just always return width * 4 will be enough
CGImageGetWidth(imageRef) * 4,
// System only supports RGB, set explicitly
colorSpace,
// Makes system don't need to do extra conversion when displayed.
// NOTE: here we remove the alpha channel for performance. Most of the time, images loaded
// from the network are jpeg with no alpha channel. As a TODO, finding a way to detect
// if alpha channel is necessary would be nice.
kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Little);
CGColorSpaceRelease(colorSpace);
if (!context)
return nil;
CGRect rect = (CGRect){CGPointZero,{CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)}};
CGContextDrawImage(context, rect, imageRef);
CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGRect rect = (CGRect){CGPointZero, {CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)}};
CGContextDrawImage(context, rect, imageRef);
CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context);
CGContextRelease(context);
UIImage *decompressedImage = [[UIImage alloc] initWithCGImage:decompressedImageRef scale:image.scale orientation:image.imageOrientation];
CGImageRelease(decompressedImageRef);
return decompressedImage;
UIImage *decompressedImage =
[[UIImage alloc] initWithCGImage:decompressedImageRef scale:image.scale orientation:image.imageOrientation];
CGImageRelease(decompressedImageRef);
return decompressedImage;
}
@end

View file

@ -23,56 +23,55 @@
@synthesize backgroundNinePatch;
@synthesize backgroundOverNinePatch;
#pragma mark - Lifecycle Functions
- (void)initUILinphoneButton {
self.backgroundNinePatch = [TUNinePatch ninePatchNamed:@"button_background_default"];
self.backgroundOverNinePatch = [TUNinePatch ninePatchNamed:@"button_background_over"];
[self setBackgroundImage:nil forState:UIControlStateNormal];
[self setBackgroundImage:nil forState:UIControlStateHighlighted];
[self setContentMode:UIViewContentModeRedraw];
self.backgroundNinePatch = [TUNinePatch ninePatchNamed:@"button_background_default"];
self.backgroundOverNinePatch = [TUNinePatch ninePatchNamed:@"button_background_over"];
[self setBackgroundImage:nil forState:UIControlStateNormal];
[self setBackgroundImage:nil forState:UIControlStateHighlighted];
[self setContentMode:UIViewContentModeRedraw];
}
- (id)init {
self = [super init];
if(self != nil) {
[self initUILinphoneButton];
}
return self;
self = [super init];
if (self != nil) {
[self initUILinphoneButton];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if(self != nil) {
[self initUILinphoneButton];
}
return self;
self = [super initWithCoder:aDecoder];
if (self != nil) {
[self initUILinphoneButton];
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if(self != nil) {
[self initUILinphoneButton];
}
return self;
self = [super initWithFrame:frame];
if (self != nil) {
[self initUILinphoneButton];
}
return self;
}
- (void)setHighlighted:(BOOL)highlighted {
[super setHighlighted:highlighted];
[self setNeedsDisplay];
[super setHighlighted:highlighted];
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect {
// we ignore the rect and redraw the entire view
CGContextRef context = UIGraphicsGetCurrentContext();
if (context) {
if(self.highlighted) {
[self.backgroundOverNinePatch inContext:context drawInRect:[self bounds]];
} else {
[self.backgroundNinePatch inContext:context drawInRect:[self bounds]];
}
}
// we ignore the rect and redraw the entire view
CGContextRef context = UIGraphicsGetCurrentContext();
if (context) {
if (self.highlighted) {
[self.backgroundOverNinePatch inContext:context drawInRect:[self bounds]];
} else {
[self.backgroundNinePatch inContext:context drawInRect:[self bounds]];
}
}
}
@end

View file

@ -23,58 +23,56 @@
@synthesize backgroundNinePatch;
#pragma mark - Lifecycle Functions
- (void)initUILinphoneTextField {
self.backgroundNinePatch = [TUNinePatch ninePatchNamed:@"field_background"];
self.background = nil;
[self setContentMode:UIViewContentModeRedraw];
self.backgroundNinePatch = [TUNinePatch ninePatchNamed:@"field_background"];
self.background = nil;
[self setContentMode:UIViewContentModeRedraw];
}
- (id)init {
self = [super init];
if(self != nil) {
[self initUILinphoneTextField];
}
return self;
self = [super init];
if (self != nil) {
[self initUILinphoneTextField];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if(self != nil) {
[self initUILinphoneTextField];
}
return self;
self = [super initWithCoder:aDecoder];
if (self != nil) {
[self initUILinphoneTextField];
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if(self != nil) {
[self initUILinphoneTextField];
}
return self;
self = [super initWithFrame:frame];
if (self != nil) {
[self initUILinphoneTextField];
}
return self;
}
- (CGRect)textRectForBounds:(CGRect)bounds {
return CGRectInset(bounds, 6, 4);
return CGRectInset(bounds, 6, 4);
}
- (CGRect)placeholderRectForBounds:(CGRect)bounds {
return CGRectInset(bounds, 6, 4);
return CGRectInset(bounds, 6, 4);
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
return CGRectInset(bounds, 6, 4);
return CGRectInset(bounds, 6, 4);
}
- (void)drawRect:(CGRect)rect {
// we ignore the rect and redraw the entire view
CGContextRef context = UIGraphicsGetCurrentContext();
if (context) {
[self.backgroundNinePatch inContext:context drawInRect:[self bounds]];
}
// we ignore the rect and redraw the entire view
CGContextRef context = UIGraphicsGetCurrentContext();
if (context) {
[self.backgroundNinePatch inContext:context drawInRect:[self bounds]];
}
}
@end

View file

@ -21,75 +21,72 @@
@implementation UILoadingImageView
@synthesize waitIndicatorView;
#pragma mark - Lifecycle Functions
- (void)initUIRemoteImageView {
waitIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
waitIndicatorView.hidesWhenStopped = TRUE;
waitIndicatorView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
waitIndicatorView.center = self.center;
[self addSubview:waitIndicatorView];
waitIndicatorView =
[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
waitIndicatorView.hidesWhenStopped = TRUE;
waitIndicatorView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
waitIndicatorView.center = self.center;
[self addSubview:waitIndicatorView];
}
- (id)init {
self = [super init];
if(self != nil) {
[self initUIRemoteImageView];
}
return self;
self = [super init];
if (self != nil) {
[self initUIRemoteImageView];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if(self != nil) {
[self initUIRemoteImageView];
}
return self;
self = [super initWithCoder:aDecoder];
if (self != nil) {
[self initUIRemoteImageView];
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if(self != nil) {
[self initUIRemoteImageView];
}
return self;
self = [super initWithFrame:frame];
if (self != nil) {
[self initUIRemoteImageView];
}
return self;
}
- (id)initWithImage:(UIImage *)image {
self = [super initWithImage:image];
if(self != nil) {
[self initUIRemoteImageView];
}
return self;
self = [super initWithImage:image];
if (self != nil) {
[self initUIRemoteImageView];
}
return self;
}
- (id)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highlightedImage {
self = [super initWithImage:image highlightedImage:highlightedImage];
if(self != nil) {
[self initUIRemoteImageView];
}
return self;
self = [super initWithImage:image highlightedImage:highlightedImage];
if (self != nil) {
[self initUIRemoteImageView];
}
return self;
}
#pragma mark -
- (void)startLoading {
[waitIndicatorView startAnimating];
[waitIndicatorView startAnimating];
}
- (void)stopLoading {
[waitIndicatorView stopAnimating];
[waitIndicatorView stopAnimating];
}
- (BOOL)isLoading {
return [waitIndicatorView isAnimating];
return [waitIndicatorView isAnimating];
}
@end

View file

@ -4,78 +4,84 @@
*
* 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 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* the Free Software Foundation; either version 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "UILongTouchButton.h"
@implementation UILongTouchButton
#pragma mark - Lifecycle Functions
- (id)initUILongTouchButton {
[self addTarget:self action:@selector(___touchDown:) forControlEvents:UIControlEventTouchDown];
[self addTarget:self action:@selector(___touchUp:) forControlEvents:UIControlEventTouchUpInside|UIControlEventTouchUpOutside];
[self addTarget:self
action:@selector(___touchUp:)
forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
return self;
}
- (id)init {
self = [super init];
if (self) {
if (!(self = [self initUILongTouchButton])) return nil;
}
return self;
self = [super init];
if (self) {
if (!(self = [self initUILongTouchButton]))
return nil;
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
if (!(self = [self initUILongTouchButton])) return nil;
}
return self;
self = [super initWithFrame:frame];
if (self) {
if (!(self = [self initUILongTouchButton]))
return nil;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
if (!(self = [self initUILongTouchButton])) return nil;
self = [super initWithCoder:decoder];
if (self) {
if (!(self = [self initUILongTouchButton]))
return nil;
}
return self;
}
return self;
}
- (void)dealloc {
[self removeTarget:self action:@selector(___touchDown:) forControlEvents:UIControlEventTouchDown];
[self removeTarget:self action:@selector(___touchUp:) forControlEvents:UIControlEventTouchUpInside|UIControlEventTouchUpOutside];
[self removeTarget:self
action:@selector(___touchUp:)
forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
}
- (void)___touchDown:(id) sender {
[self performSelector:@selector(doLongTouch) withObject:nil afterDelay:0.5];
- (void)___touchDown:(id)sender {
[self performSelector:@selector(doLongTouch) withObject:nil afterDelay:0.5];
}
- (void)___touchUp:(id) sender {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(doLongTouch) object:nil];
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(doRepeatTouch) object:nil];
- (void)___touchUp:(id)sender {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(doLongTouch) object:nil];
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(doRepeatTouch) object:nil];
}
- (void)doLongTouch {
[self onLongTouch];
[self onRepeatTouch];
[self onLongTouch];
[self onRepeatTouch];
[self performSelector:@selector(doRepeatTouch) withObject:nil afterDelay:0.1];
}
- (void)doRepeatTouch {
[self onRepeatTouch];
[self onRepeatTouch];
[self performSelector:@selector(doRepeatTouch) withObject:nil afterDelay:0.1];
}

View file

@ -23,10 +23,9 @@
@implementation UIMainBar
static NSString * const kBounceAnimation = @"bounce";
static NSString * const kAppearAnimation = @"appear";
static NSString * const kDisappearAnimation = @"disappear";
static NSString *const kBounceAnimation = @"bounce";
static NSString *const kAppearAnimation = @"appear";
static NSString *const kDisappearAnimation = @"disappear";
@synthesize historyButton;
@synthesize contactsButton;
@ -41,420 +40,412 @@ static NSString * const kDisappearAnimation = @"disappear";
#pragma mark - Lifecycle Functions
- (id)init {
return [super initWithNibName:@"UIMainBar" bundle:[NSBundle mainBundle]];
return [super initWithNibName:@"UIMainBar" bundle:[NSBundle mainBundle]];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - ViewController Functions
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(changeViewEvent:)
name:kLinphoneMainViewChange
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(callUpdate:)
name:kLinphoneCallUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(textReceived:)
name:kLinphoneTextReceived
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(settingsUpdate:)
name:kLinphoneSettingsUpdate
object:nil];
[self update:FALSE];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(changeViewEvent:)
name:kLinphoneMainViewChange
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(callUpdate:)
name:kLinphoneCallUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(textReceived:)
name:kLinphoneTextReceived
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(settingsUpdate:)
name:kLinphoneSettingsUpdate
object:nil];
[self update:FALSE];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneMainViewChange
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneCallUpdate
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneTextReceived
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneSettingsUpdate
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneMainViewChange object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneCallUpdate object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneTextReceived object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneSettingsUpdate object:nil];
}
- (void)flipImageForButton:(UIButton*)button {
UIControlState states[] = { UIControlStateNormal, UIControlStateDisabled, UIControlStateSelected, UIControlStateHighlighted, -1 };
UIControlState *state = states;
- (void)flipImageForButton:(UIButton *)button {
UIControlState states[] = {UIControlStateNormal, UIControlStateDisabled, UIControlStateSelected,
UIControlStateHighlighted, -1};
UIControlState *state = states;
while (*state != -1) {
UIImage* bgImage = [button backgroundImageForState:*state];
while (*state != -1) {
UIImage *bgImage = [button backgroundImageForState:*state];
UIImage* flippedImage = [UIImage imageWithCGImage:bgImage.CGImage
scale:bgImage.scale
orientation:UIImageOrientationUpMirrored];
[button setBackgroundImage:flippedImage forState:*state];
state++;
}
UIImage *flippedImage =
[UIImage imageWithCGImage:bgImage.CGImage scale:bgImage.scale orientation:UIImageOrientationUpMirrored];
[button setBackgroundImage:flippedImage forState:*state];
state++;
}
}
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillEnterForeground:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillEnterForeground:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
{
UIButton *historyButtonLandscape = (UIButton*) [landscapeView viewWithTag:[historyButton tag]];
// Set selected+over background: IB lack !
[historyButton setBackgroundImage:[UIImage imageNamed:@"history_selected.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
{
UIButton *historyButtonLandscape = (UIButton *)[landscapeView viewWithTag:[historyButton tag]];
// Set selected+over background: IB lack !
[historyButton setBackgroundImage:[UIImage imageNamed:@"history_selected.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+over background: IB lack !
[historyButtonLandscape setBackgroundImage:[UIImage imageNamed:@"history_selected_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+over background: IB lack !
[historyButtonLandscape setBackgroundImage:[UIImage imageNamed:@"history_selected_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStatesForTabs:historyButton];
[LinphoneUtils buttonFixStatesForTabs:historyButtonLandscape];
}
[LinphoneUtils buttonFixStatesForTabs:historyButton];
[LinphoneUtils buttonFixStatesForTabs:historyButtonLandscape];
}
{
UIButton *contactsButtonLandscape = (UIButton*) [landscapeView viewWithTag:[contactsButton tag]];
// Set selected+over background: IB lack !
[contactsButton setBackgroundImage:[UIImage imageNamed:@"contacts_selected.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
{
UIButton *contactsButtonLandscape = (UIButton *)[landscapeView viewWithTag:[contactsButton tag]];
// Set selected+over background: IB lack !
[contactsButton setBackgroundImage:[UIImage imageNamed:@"contacts_selected.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+over background: IB lack !
[contactsButtonLandscape setBackgroundImage:[UIImage imageNamed:@"contacts_selected_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+over background: IB lack !
[contactsButtonLandscape setBackgroundImage:[UIImage imageNamed:@"contacts_selected_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStatesForTabs:contactsButton];
[LinphoneUtils buttonFixStatesForTabs:contactsButtonLandscape];
}
{
UIButton *dialerButtonLandscape = (UIButton*) [landscapeView viewWithTag:[dialerButton tag]];
// Set selected+over background: IB lack !
[dialerButton setBackgroundImage:[UIImage imageNamed:@"dialer_selected.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStatesForTabs:contactsButton];
[LinphoneUtils buttonFixStatesForTabs:contactsButtonLandscape];
}
{
UIButton *dialerButtonLandscape = (UIButton *)[landscapeView viewWithTag:[dialerButton tag]];
// Set selected+over background: IB lack !
[dialerButton setBackgroundImage:[UIImage imageNamed:@"dialer_selected.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+over background: IB lack !
[dialerButtonLandscape setBackgroundImage:[UIImage imageNamed:@"dialer_selected_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+over background: IB lack !
[dialerButtonLandscape setBackgroundImage:[UIImage imageNamed:@"dialer_selected_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStatesForTabs:dialerButton];
[LinphoneUtils buttonFixStatesForTabs:dialerButtonLandscape];
}
{
UIButton *settingsButtonLandscape = (UIButton*) [landscapeView viewWithTag:[settingsButton tag]];
// Set selected+over background: IB lack !
[settingsButton setBackgroundImage:[UIImage imageNamed:@"settings_selected.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStatesForTabs:dialerButton];
[LinphoneUtils buttonFixStatesForTabs:dialerButtonLandscape];
}
{
UIButton *settingsButtonLandscape = (UIButton *)[landscapeView viewWithTag:[settingsButton tag]];
// Set selected+over background: IB lack !
[settingsButton setBackgroundImage:[UIImage imageNamed:@"settings_selected.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+over background: IB lack !
[settingsButtonLandscape setBackgroundImage:[UIImage imageNamed:@"settings_selected_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+over background: IB lack !
[settingsButtonLandscape setBackgroundImage:[UIImage imageNamed:@"settings_selected_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStatesForTabs:settingsButton];
[LinphoneUtils buttonFixStatesForTabs:settingsButtonLandscape];
}
[LinphoneUtils buttonFixStatesForTabs:settingsButton];
[LinphoneUtils buttonFixStatesForTabs:settingsButtonLandscape];
}
{
UIButton *chatButtonLandscape = (UIButton*) [landscapeView viewWithTag:[chatButton tag]];
// Set selected+over background: IB lack !
[chatButton setBackgroundImage:[UIImage imageNamed:@"chat_selected.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
{
UIButton *chatButtonLandscape = (UIButton *)[landscapeView viewWithTag:[chatButton tag]];
// Set selected+over background: IB lack !
[chatButton setBackgroundImage:[UIImage imageNamed:@"chat_selected.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+over background: IB lack !
[chatButtonLandscape setBackgroundImage:[UIImage imageNamed:@"chat_selected_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+over background: IB lack !
[chatButtonLandscape setBackgroundImage:[UIImage imageNamed:@"chat_selected_landscape.png"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStatesForTabs:chatButton];
[LinphoneUtils buttonFixStatesForTabs:chatButtonLandscape];
}
if ([LinphoneManager langageDirectionIsRTL]){
[self flipImageForButton:historyButton];
[self flipImageForButton:settingsButton];
[self flipImageForButton:dialerButton];
[self flipImageForButton:chatButton];
[self flipImageForButton:contactsButton];
}
[LinphoneUtils buttonFixStatesForTabs:chatButton];
[LinphoneUtils buttonFixStatesForTabs:chatButtonLandscape];
}
if ([LinphoneManager langageDirectionIsRTL]) {
[self flipImageForButton:historyButton];
[self flipImageForButton:settingsButton];
[self flipImageForButton:dialerButton];
[self flipImageForButton:chatButton];
[self flipImageForButton:contactsButton];
}
[super viewDidLoad]; // Have to be after due to TPMultiLayoutViewController
[super viewDidLoad]; // Have to be after due to TPMultiLayoutViewController
}
- (void)viewDidUnload {
[super viewDidUnload];
[super viewDidUnload];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationWillEnterForegroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationWillEnterForegroundNotification
object:nil];
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
// Force the animations
[[self.view layer] removeAllAnimations];
[historyNotificationView.layer setTransform:CATransform3DIdentity];
[chatNotificationView.layer setTransform:CATransform3DIdentity];
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {
// Force the animations
[[self.view layer] removeAllAnimations];
[historyNotificationView.layer setTransform:CATransform3DIdentity];
[chatNotificationView.layer setTransform:CATransform3DIdentity];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[chatNotificationView setHidden:TRUE];
[historyNotificationView setHidden:TRUE];
[self update:FALSE];
[chatNotificationView setHidden:TRUE];
[historyNotificationView setHidden:TRUE];
[self update:FALSE];
}
#pragma mark - Event Functions
- (void)applicationWillEnterForeground:(NSNotification*)notif {
// Force the animations
[[self.view layer] removeAllAnimations];
[historyNotificationView.layer setTransform:CATransform3DIdentity];
[chatNotificationView.layer setTransform:CATransform3DIdentity];
[chatNotificationView setHidden:TRUE];
[historyNotificationView setHidden:TRUE];
[self update:FALSE];
- (void)applicationWillEnterForeground:(NSNotification *)notif {
// Force the animations
[[self.view layer] removeAllAnimations];
[historyNotificationView.layer setTransform:CATransform3DIdentity];
[chatNotificationView.layer setTransform:CATransform3DIdentity];
[chatNotificationView setHidden:TRUE];
[historyNotificationView setHidden:TRUE];
[self update:FALSE];
}
- (void)callUpdate:(NSNotification*)notif {
//LinphoneCall *call = [[notif.userInfo objectForKey: @"call"] pointerValue];
//LinphoneCallState state = [[notif.userInfo objectForKey: @"state"] intValue];
[self updateMissedCall:linphone_core_get_missed_calls_count([LinphoneManager getLc]) appear:TRUE];
- (void)callUpdate:(NSNotification *)notif {
// LinphoneCall *call = [[notif.userInfo objectForKey: @"call"] pointerValue];
// LinphoneCallState state = [[notif.userInfo objectForKey: @"state"] intValue];
[self updateMissedCall:linphone_core_get_missed_calls_count([LinphoneManager getLc]) appear:TRUE];
}
- (void)changeViewEvent:(NSNotification*)notif {
//UICompositeViewDescription *view = [notif.userInfo objectForKey: @"view"];
//if(view != nil)
[self updateView:[[PhoneMainView instance] firstView]];
- (void)changeViewEvent:(NSNotification *)notif {
// UICompositeViewDescription *view = [notif.userInfo objectForKey: @"view"];
// if(view != nil)
[self updateView:[[PhoneMainView instance] firstView]];
}
- (void)settingsUpdate:(NSNotification*)notif {
if([[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"] == false) {
[self stopBounceAnimation:kBounceAnimation target:chatNotificationView];
chatNotificationView.layer.transform = CATransform3DIdentity;
[self stopBounceAnimation:kBounceAnimation target:historyNotificationView];
historyNotificationView.layer.transform = CATransform3DIdentity;
} else {
if(![chatNotificationView isHidden] && [chatNotificationView.layer animationForKey:kBounceAnimation] == nil) {
[self startBounceAnimation:kBounceAnimation target:chatNotificationView];
}
if(![historyNotificationView isHidden] && [historyNotificationView.layer animationForKey:kBounceAnimation] == nil) {
[self startBounceAnimation:kBounceAnimation target:historyNotificationView];
}
}
- (void)settingsUpdate:(NSNotification *)notif {
if ([[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"] == false) {
[self stopBounceAnimation:kBounceAnimation target:chatNotificationView];
chatNotificationView.layer.transform = CATransform3DIdentity;
[self stopBounceAnimation:kBounceAnimation target:historyNotificationView];
historyNotificationView.layer.transform = CATransform3DIdentity;
} else {
if (![chatNotificationView isHidden] && [chatNotificationView.layer animationForKey:kBounceAnimation] == nil) {
[self startBounceAnimation:kBounceAnimation target:chatNotificationView];
}
if (![historyNotificationView isHidden] &&
[historyNotificationView.layer animationForKey:kBounceAnimation] == nil) {
[self startBounceAnimation:kBounceAnimation target:historyNotificationView];
}
}
}
- (void)textReceived:(NSNotification*)notif {
[self updateUnreadMessage:TRUE];
- (void)textReceived:(NSNotification *)notif {
[self updateUnreadMessage:TRUE];
}
#pragma mark -
- (void)update:(BOOL)appear{
[self updateView:[[PhoneMainView instance] firstView]];
[self updateMissedCall:linphone_core_get_missed_calls_count([LinphoneManager getLc]) appear:appear];
[self updateUnreadMessage:appear];
- (void)update:(BOOL)appear {
[self updateView:[[PhoneMainView instance] firstView]];
[self updateMissedCall:linphone_core_get_missed_calls_count([LinphoneManager getLc]) appear:appear];
[self updateUnreadMessage:appear];
}
- (void)updateUnreadMessage:(BOOL)appear{
int unreadMessage = [LinphoneManager unreadMessageCount];
if (unreadMessage > 0) {
if([chatNotificationView isHidden]) {
[chatNotificationView setHidden:FALSE];
if([[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"] == true) {
if(appear) {
[self appearAnimation:kAppearAnimation target:chatNotificationView completion:^(BOOL finished){
[self startBounceAnimation:kBounceAnimation target:chatNotificationView];
[chatNotificationView.layer removeAnimationForKey:kAppearAnimation];
}];
} else {
[self startBounceAnimation:kBounceAnimation target:chatNotificationView];
}
}
}
[chatNotificationLabel setText:[NSString stringWithFormat:@"%i", unreadMessage]];
} else {
if(![chatNotificationView isHidden]) {
[self stopBounceAnimation:kBounceAnimation target:chatNotificationView];
if(appear) {
[self disappearAnimation:kDisappearAnimation target:chatNotificationView completion:^(BOOL finished){
[chatNotificationView setHidden:TRUE];
[chatNotificationView.layer removeAnimationForKey:kDisappearAnimation];
}];
} else {
[chatNotificationView setHidden:TRUE];
}
}
}
- (void)updateUnreadMessage:(BOOL)appear {
int unreadMessage = [LinphoneManager unreadMessageCount];
if (unreadMessage > 0) {
if ([chatNotificationView isHidden]) {
[chatNotificationView setHidden:FALSE];
if ([[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"] == true) {
if (appear) {
[self appearAnimation:kAppearAnimation
target:chatNotificationView
completion:^(BOOL finished) {
[self startBounceAnimation:kBounceAnimation target:chatNotificationView];
[chatNotificationView.layer removeAnimationForKey:kAppearAnimation];
}];
} else {
[self startBounceAnimation:kBounceAnimation target:chatNotificationView];
}
}
}
[chatNotificationLabel setText:[NSString stringWithFormat:@"%i", unreadMessage]];
} else {
if (![chatNotificationView isHidden]) {
[self stopBounceAnimation:kBounceAnimation target:chatNotificationView];
if (appear) {
[self disappearAnimation:kDisappearAnimation
target:chatNotificationView
completion:^(BOOL finished) {
[chatNotificationView setHidden:TRUE];
[chatNotificationView.layer removeAnimationForKey:kDisappearAnimation];
}];
} else {
[chatNotificationView setHidden:TRUE];
}
}
}
}
- (void)updateMissedCall:(int)missedCall appear:(BOOL)appear{
if (missedCall > 0) {
if([historyNotificationView isHidden]) {
[historyNotificationView setHidden:FALSE];
if([[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"] == true) {
if(appear) {
[self appearAnimation:kAppearAnimation target:historyNotificationView completion:^(BOOL finished){
[self startBounceAnimation:kBounceAnimation target:historyNotificationView];
[historyNotificationView.layer removeAnimationForKey:kAppearAnimation];
}];
} else {
[self startBounceAnimation:kBounceAnimation target:historyNotificationView];
}
}
}
[historyNotificationLabel setText:[NSString stringWithFormat:@"%i", missedCall]];
} else {
if(![historyNotificationView isHidden]) {
[self stopBounceAnimation:kBounceAnimation target:historyNotificationView];
if(appear) {
[self disappearAnimation:kDisappearAnimation target:historyNotificationView completion:^(BOOL finished){
[historyNotificationView setHidden:TRUE];
[historyNotificationView.layer removeAnimationForKey:kDisappearAnimation];
}];
} else {
[historyNotificationView setHidden:TRUE];
}
}
}
- (void)updateMissedCall:(int)missedCall appear:(BOOL)appear {
if (missedCall > 0) {
if ([historyNotificationView isHidden]) {
[historyNotificationView setHidden:FALSE];
if ([[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"] == true) {
if (appear) {
[self appearAnimation:kAppearAnimation
target:historyNotificationView
completion:^(BOOL finished) {
[self startBounceAnimation:kBounceAnimation target:historyNotificationView];
[historyNotificationView.layer removeAnimationForKey:kAppearAnimation];
}];
} else {
[self startBounceAnimation:kBounceAnimation target:historyNotificationView];
}
}
}
[historyNotificationLabel setText:[NSString stringWithFormat:@"%i", missedCall]];
} else {
if (![historyNotificationView isHidden]) {
[self stopBounceAnimation:kBounceAnimation target:historyNotificationView];
if (appear) {
[self disappearAnimation:kDisappearAnimation
target:historyNotificationView
completion:^(BOOL finished) {
[historyNotificationView setHidden:TRUE];
[historyNotificationView.layer removeAnimationForKey:kDisappearAnimation];
}];
} else {
[historyNotificationView setHidden:TRUE];
}
}
}
}
- (void)appearAnimation:(NSString*)animationID target:(UIView*)target completion:(void (^)(BOOL finished))completion {
CABasicAnimation *appear = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
appear.duration = 0.4;
appear.fromValue = [NSNumber numberWithDouble:0.0f];
appear.toValue = [NSNumber numberWithDouble:1.0f];
appear.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
appear.fillMode = kCAFillModeForwards;
appear.removedOnCompletion = NO;
[appear setCompletion:completion];
[target.layer addAnimation:appear forKey:animationID];
- (void)appearAnimation:(NSString *)animationID target:(UIView *)target completion:(void (^)(BOOL finished))completion {
CABasicAnimation *appear = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
appear.duration = 0.4;
appear.fromValue = [NSNumber numberWithDouble:0.0f];
appear.toValue = [NSNumber numberWithDouble:1.0f];
appear.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
appear.fillMode = kCAFillModeForwards;
appear.removedOnCompletion = NO;
[appear setCompletion:completion];
[target.layer addAnimation:appear forKey:animationID];
}
- (void)disappearAnimation:(NSString*)animationID target:(UIView*)target completion:(void (^)(BOOL finished))completion {
CABasicAnimation *disappear = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
disappear.duration = 0.4;
disappear.fromValue = [NSNumber numberWithDouble:1.0f];
disappear.toValue = [NSNumber numberWithDouble:0.0f];
disappear.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
disappear.fillMode = kCAFillModeForwards;
disappear.removedOnCompletion = NO;
[disappear setCompletion:completion];
[target.layer addAnimation:disappear forKey:animationID];
- (void)disappearAnimation:(NSString *)animationID
target:(UIView *)target
completion:(void (^)(BOOL finished))completion {
CABasicAnimation *disappear = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
disappear.duration = 0.4;
disappear.fromValue = [NSNumber numberWithDouble:1.0f];
disappear.toValue = [NSNumber numberWithDouble:0.0f];
disappear.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
disappear.fillMode = kCAFillModeForwards;
disappear.removedOnCompletion = NO;
[disappear setCompletion:completion];
[target.layer addAnimation:disappear forKey:animationID];
}
- (void)startBounceAnimation:(NSString *)animationID target:(UIView *)target {
CABasicAnimation *bounce = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
bounce.duration = 0.3;
bounce.fromValue = [NSNumber numberWithDouble:0.0f];
bounce.toValue = [NSNumber numberWithDouble:8.0f];
bounce.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
bounce.autoreverses = TRUE;
bounce.repeatCount = HUGE_VALF;
[target.layer addAnimation:bounce forKey:animationID];
CABasicAnimation *bounce = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
bounce.duration = 0.3;
bounce.fromValue = [NSNumber numberWithDouble:0.0f];
bounce.toValue = [NSNumber numberWithDouble:8.0f];
bounce.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
bounce.autoreverses = TRUE;
bounce.repeatCount = HUGE_VALF;
[target.layer addAnimation:bounce forKey:animationID];
}
- (void)stopBounceAnimation:(NSString *)animationID target:(UIView *)target {
[target.layer removeAnimationForKey:animationID];
[target.layer removeAnimationForKey:animationID];
}
- (void)updateView:(UICompositeViewDescription*) view {
// Update buttons
if([view equal:[HistoryViewController compositeViewDescription]]) {
historyButton.selected = TRUE;
} else {
historyButton.selected = FALSE;
}
if([view equal:[ContactsViewController compositeViewDescription]]) {
contactsButton.selected = TRUE;
} else {
contactsButton.selected = FALSE;
}
if([view equal:[DialerViewController compositeViewDescription]]) {
dialerButton.selected = TRUE;
} else {
dialerButton.selected = FALSE;
}
if([view equal:[SettingsViewController compositeViewDescription]]) {
settingsButton.selected = TRUE;
} else {
settingsButton.selected = FALSE;
}
if([view equal:[ChatViewController compositeViewDescription]]) {
chatButton.selected = TRUE;
} else {
chatButton.selected = FALSE;
}
- (void)updateView:(UICompositeViewDescription *)view {
// Update buttons
if ([view equal:[HistoryViewController compositeViewDescription]]) {
historyButton.selected = TRUE;
} else {
historyButton.selected = FALSE;
}
if ([view equal:[ContactsViewController compositeViewDescription]]) {
contactsButton.selected = TRUE;
} else {
contactsButton.selected = FALSE;
}
if ([view equal:[DialerViewController compositeViewDescription]]) {
dialerButton.selected = TRUE;
} else {
dialerButton.selected = FALSE;
}
if ([view equal:[SettingsViewController compositeViewDescription]]) {
settingsButton.selected = TRUE;
} else {
settingsButton.selected = FALSE;
}
if ([view equal:[ChatViewController compositeViewDescription]]) {
chatButton.selected = TRUE;
} else {
chatButton.selected = FALSE;
}
}
#pragma mark - Action Functions
- (IBAction)onHistoryClick:(id)event {
[[PhoneMainView instance] changeCurrentView:[HistoryViewController compositeViewDescription]];
[[PhoneMainView instance] changeCurrentView:[HistoryViewController compositeViewDescription]];
}
- (IBAction)onContactsClick:(id)event {
[ContactSelection setSelectionMode:ContactSelectionModeNone];
[ContactSelection setAddAddress:nil];
[ContactSelection setSipFilter:nil];
[ContactSelection enableEmailFilter:FALSE];
[ContactSelection setNameOrEmailFilter:nil];
[[PhoneMainView instance] changeCurrentView:[ContactsViewController compositeViewDescription]];
[ContactSelection setSelectionMode:ContactSelectionModeNone];
[ContactSelection setAddAddress:nil];
[ContactSelection setSipFilter:nil];
[ContactSelection enableEmailFilter:FALSE];
[ContactSelection setNameOrEmailFilter:nil];
[[PhoneMainView instance] changeCurrentView:[ContactsViewController compositeViewDescription]];
}
- (IBAction)onDialerClick:(id)event {
[[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]];
[[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]];
}
- (IBAction)onSettingsClick:(id)event {
[[PhoneMainView instance] changeCurrentView:[SettingsViewController compositeViewDescription]];
[[PhoneMainView instance] changeCurrentView:[SettingsViewController compositeViewDescription]];
}
- (IBAction)onChatClick:(id)event {
[[PhoneMainView instance] changeCurrentView:[ChatViewController compositeViewDescription]];
[[PhoneMainView instance] changeCurrentView:[ChatViewController compositeViewDescription]];
}
#pragma mark - TPMultiLayoutViewController Functions
- (NSDictionary*)attributesForView:(UIView*)view {
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
- (NSDictionary *)attributesForView:(UIView *)view {
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
[attributes setObject:[NSValue valueWithCGRect:view.frame] forKey:@"frame"];
[attributes setObject:[NSValue valueWithCGRect:view.bounds] forKey:@"bounds"];
if([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)view;
[LinphoneUtils buttonMultiViewAddAttributes:attributes button:button];
}
[attributes setObject:[NSNumber numberWithInteger:view.autoresizingMask] forKey:@"autoresizingMask"];
[attributes setObject:[NSValue valueWithCGRect:view.frame] forKey:@"frame"];
[attributes setObject:[NSValue valueWithCGRect:view.bounds] forKey:@"bounds"];
if ([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)view;
[LinphoneUtils buttonMultiViewAddAttributes:attributes button:button];
}
[attributes setObject:[NSNumber numberWithInteger:view.autoresizingMask] forKey:@"autoresizingMask"];
return attributes;
return attributes;
}
- (void)applyAttributes:(NSDictionary*)attributes toView:(UIView*)view {
view.frame = [[attributes objectForKey:@"frame"] CGRectValue];
view.bounds = [[attributes objectForKey:@"bounds"] CGRectValue];
if([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)view;
[LinphoneUtils buttonMultiViewApplyAttributes:attributes button:button];
}
view.autoresizingMask = [[attributes objectForKey:@"autoresizingMask"] integerValue];
- (void)applyAttributes:(NSDictionary *)attributes toView:(UIView *)view {
view.frame = [[attributes objectForKey:@"frame"] CGRectValue];
view.bounds = [[attributes objectForKey:@"bounds"] CGRectValue];
if ([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)view;
[LinphoneUtils buttonMultiViewApplyAttributes:attributes button:button];
}
view.autoresizingMask = [[attributes objectForKey:@"autoresizingMask"] integerValue];
}
@end

View file

@ -4,18 +4,18 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "UIMicroButton.h"
@ -32,8 +32,7 @@
}
- (bool)onUpdate {
return linphone_core_is_mic_muted([LinphoneManager getLc]) == false;
return linphone_core_is_mic_muted([LinphoneManager getLc]) == false;
}
@end

View file

@ -22,192 +22,178 @@
#include "linphone/linphonecore.h"
@implementation UIPauseButton
#pragma mark - Lifecycle Functions
- (void)initUIPauseButton {
type = UIPauseButtonType_CurrentCall;
type = UIPauseButtonType_CurrentCall;
}
- (id)init{
self = [super init];
if (self) {
- (id)init {
self = [super init];
if (self) {
[self initUIPauseButton];
}
return self;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
self = [super initWithCoder:decoder];
if (self) {
[self initUIPauseButton];
}
return self;
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self = [super initWithFrame:frame];
if (self) {
[self initUIPauseButton];
}
return self;
}
return self;
}
#pragma mark - Static Functions
+ (bool)isInConference: (LinphoneCall*) call {
if (!call)
return false;
return linphone_call_is_in_conference(call);
+ (bool)isInConference:(LinphoneCall *)call {
if (!call)
return false;
return linphone_call_is_in_conference(call);
}
+ (int)notInConferenceCallCount: (LinphoneCore*) lc {
int count = 0;
const MSList* calls = linphone_core_get_calls(lc);
+ (int)notInConferenceCallCount:(LinphoneCore *)lc {
int count = 0;
const MSList *calls = linphone_core_get_calls(lc);
while (calls != 0) {
if (![UIPauseButton isInConference: (LinphoneCall*)calls->data]) {
count++;
}
calls = calls->next;
}
return count;
while (calls != 0) {
if (![UIPauseButton isInConference:(LinphoneCall *)calls->data]) {
count++;
}
calls = calls->next;
}
return count;
}
+ (LinphoneCall*)getCall {
LinphoneCore* lc = [LinphoneManager getLc];
LinphoneCall* currentCall = linphone_core_get_current_call(lc);
+ (LinphoneCall *)getCall {
LinphoneCore *lc = [LinphoneManager getLc];
LinphoneCall *currentCall = linphone_core_get_current_call(lc);
if (currentCall == nil && linphone_core_get_calls_nb(lc) == 1) {
currentCall = (LinphoneCall*) linphone_core_get_calls(lc)->data;
}
return currentCall;
currentCall = (LinphoneCall *)linphone_core_get_calls(lc)->data;
}
return currentCall;
}
#pragma mark -
- (void)setType:(UIPauseButtonType) atype call:(LinphoneCall*)acall {
type = atype;
call = acall;
- (void)setType:(UIPauseButtonType)atype call:(LinphoneCall *)acall {
type = atype;
call = acall;
}
#pragma mark - UIToggleButtonDelegate Functions
- (void)onOn {
switch (type) {
case UIPauseButtonType_Call:
{
if (call != nil) {
linphone_core_pause_call([LinphoneManager getLc], call);
} else {
LOGW(@"Cannot toggle pause buttton, because no current call");
}
break;
}
case UIPauseButtonType_Conference:
{
linphone_core_leave_conference([LinphoneManager getLc]);
switch (type) {
case UIPauseButtonType_Call: {
if (call != nil) {
linphone_core_pause_call([LinphoneManager getLc], call);
} else {
LOGW(@"Cannot toggle pause buttton, because no current call");
}
break;
}
case UIPauseButtonType_Conference: {
linphone_core_leave_conference([LinphoneManager getLc]);
// Fake event
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneCallUpdate object:self];
break;
}
case UIPauseButtonType_CurrentCall:
{
LinphoneCall* currentCall = [UIPauseButton getCall];
if (currentCall != nil) {
linphone_core_pause_call([LinphoneManager getLc], currentCall);
} else {
LOGW(@"Cannot toggle pause buttton, because no current call");
}
break;
}
}
// Fake event
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneCallUpdate object:self];
break;
}
case UIPauseButtonType_CurrentCall: {
LinphoneCall *currentCall = [UIPauseButton getCall];
if (currentCall != nil) {
linphone_core_pause_call([LinphoneManager getLc], currentCall);
} else {
LOGW(@"Cannot toggle pause buttton, because no current call");
}
break;
}
}
}
- (void)onOff {
switch (type) {
case UIPauseButtonType_Call:
{
if (call != nil) {
linphone_core_resume_call([LinphoneManager getLc], call);
} else {
LOGW(@"Cannot toggle pause buttton, because no current call");
}
break;
}
case UIPauseButtonType_Conference:
{
linphone_core_enter_conference([LinphoneManager getLc]);
// Fake event
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneCallUpdate object:self];
break;
}
case UIPauseButtonType_CurrentCall:
{
LinphoneCall* currentCall = [UIPauseButton getCall];
if (currentCall != nil) {
linphone_core_resume_call([LinphoneManager getLc], currentCall);
} else {
LOGW(@"Cannot toggle pause buttton, because no current call");
}
break;
}
}
switch (type) {
case UIPauseButtonType_Call: {
if (call != nil) {
linphone_core_resume_call([LinphoneManager getLc], call);
} else {
LOGW(@"Cannot toggle pause buttton, because no current call");
}
break;
}
case UIPauseButtonType_Conference: {
linphone_core_enter_conference([LinphoneManager getLc]);
// Fake event
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneCallUpdate object:self];
break;
}
case UIPauseButtonType_CurrentCall: {
LinphoneCall *currentCall = [UIPauseButton getCall];
if (currentCall != nil) {
linphone_core_resume_call([LinphoneManager getLc], currentCall);
} else {
LOGW(@"Cannot toggle pause buttton, because no current call");
}
break;
}
}
}
- (bool)onUpdate {
bool ret = false;
// TODO: disable pause on not running call
LinphoneCore *lc = [LinphoneManager getLc];
switch (type) {
case UIPauseButtonType_Call:
{
if (call != nil) {
LinphoneCallState state = linphone_call_get_state(call);
if(state == LinphoneCallPaused || state == LinphoneCallPausing) {
ret = true;
}
[self setEnabled:TRUE];
} else {
[self setEnabled:FALSE];
}
break;
}
case UIPauseButtonType_Conference:
{
if(linphone_core_get_conference_size(lc) > 0) {
if (!linphone_core_is_in_conference(lc)) {
ret = true;
}
[self setEnabled:TRUE];
} else {
[self setEnabled:FALSE];
}
break;
}
case UIPauseButtonType_CurrentCall:
{
LinphoneCall* currentCall = [UIPauseButton getCall];
if (currentCall != nil) {
LinphoneCallState state = linphone_call_get_state(currentCall);
if(state == LinphoneCallPaused || state == LinphoneCallPausing) {
ret = true;
}
[self setEnabled:TRUE];
} else {
[self setEnabled:FALSE];
}
break;
}
}
bool ret = false;
// TODO: disable pause on not running call
LinphoneCore *lc = [LinphoneManager getLc];
switch (type) {
case UIPauseButtonType_Call: {
if (call != nil) {
LinphoneCallState state = linphone_call_get_state(call);
if (state == LinphoneCallPaused || state == LinphoneCallPausing) {
ret = true;
}
[self setEnabled:TRUE];
} else {
[self setEnabled:FALSE];
}
break;
}
case UIPauseButtonType_Conference: {
if (linphone_core_get_conference_size(lc) > 0) {
if (!linphone_core_is_in_conference(lc)) {
ret = true;
}
[self setEnabled:TRUE];
} else {
[self setEnabled:FALSE];
}
break;
}
case UIPauseButtonType_CurrentCall: {
LinphoneCall *currentCall = [UIPauseButton getCall];
if (currentCall != nil) {
LinphoneCallState state = linphone_call_get_state(currentCall);
if (state == LinphoneCallPaused || state == LinphoneCallPausing) {
ret = true;
}
[self setEnabled:TRUE];
} else {
[self setEnabled:FALSE];
}
break;
}
}
return ret;
return ret;
}
@end

View file

@ -11,22 +11,21 @@
@implementation UIRoundedImageView
- (id) init {
self = [super init];
if (self ){
[self setRoundRadius:TRUE];
}
return self;
- (id)init {
self = [super init];
if (self) {
[self setRoundRadius:TRUE];
}
return self;
}
- (void) setImage:(UIImage *)image {
- (void)setImage:(UIImage *)image {
[self setImage:image withRoundedRadius:TRUE];
}
- (void) setImage:(UIImage *)image withRoundedRadius:(BOOL)rounded {
[super setImage:image];
[self setRoundRadius:rounded];
- (void)setImage:(UIImage *)image withRoundedRadius:(BOOL)rounded {
[super setImage:image];
[self setRoundRadius:rounded];
}
// warning: for non-squared image, this function will generate an ellipsoidal image, not a round image!
@ -41,5 +40,4 @@
[imageLayer setMasksToBounds:YES];
}
@end

View file

@ -4,18 +4,18 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import <AudioToolbox/AudioToolbox.h>
#import "UISpeakerButton.h"
@ -26,60 +26,60 @@
@implementation UISpeakerButton
#pragma mark - Static Functions
static void audioRouteChangeListenerCallback (
void *inUserData, // 1
AudioSessionPropertyID inPropertyID, // 2
UInt32 inPropertyValueSize, // 3
const void *inPropertyValue // 4
) {
if (inPropertyID != kAudioSessionProperty_AudioRouteChange) return; // 5
UISpeakerButton* button = (__bridge UISpeakerButton*)inUserData;
[button update];
static void audioRouteChangeListenerCallback(void *inUserData, // 1
AudioSessionPropertyID inPropertyID, // 2
UInt32 inPropertyValueSize, // 3
const void *inPropertyValue // 4
) {
if (inPropertyID != kAudioSessionProperty_AudioRouteChange)
return; // 5
UISpeakerButton *button = (__bridge UISpeakerButton *)inUserData;
[button update];
}
- (void)initUISpeakerButton {
AudioSessionInitialize(NULL, NULL, NULL, NULL);
OSStatus lStatus = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, audioRouteChangeListenerCallback, (__bridge void *)(self));
if (lStatus) {
LOGE(@"cannot register route change handler [%ld]",lStatus);
}
AudioSessionInitialize(NULL, NULL, NULL, NULL);
OSStatus lStatus = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange,
audioRouteChangeListenerCallback, (__bridge void *)(self));
if (lStatus) {
LOGE(@"cannot register route change handler [%ld]", lStatus);
}
}
- (id)init {
self = [super init];
if (self) {
self = [super init];
if (self) {
[self initUISpeakerButton];
}
return self;
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self = [super initWithFrame:frame];
if (self) {
[self initUISpeakerButton];
}
return self;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
self = [super initWithCoder:decoder];
if (self) {
[self initUISpeakerButton];
}
return self;
}
return self;
}
- (void)dealloc {
OSStatus lStatus = AudioSessionRemovePropertyListenerWithUserData(kAudioSessionProperty_AudioRouteChange, audioRouteChangeListenerCallback, (__bridge void *)(self));
OSStatus lStatus = AudioSessionRemovePropertyListenerWithUserData(
kAudioSessionProperty_AudioRouteChange, audioRouteChangeListenerCallback, (__bridge void *)(self));
if (lStatus) {
LOGE(@"cannot un register route change handler [%ld]", lStatus);
}
}
#pragma mark - UIToggleButtonDelegate Functions
- (void)onOn {
@ -87,12 +87,12 @@ static void audioRouteChangeListenerCallback (
}
- (void)onOff {
[[LinphoneManager instance] setSpeakerEnabled:FALSE];
[[LinphoneManager instance] setSpeakerEnabled:FALSE];
}
- (bool)onUpdate {
[self setEnabled:[[LinphoneManager instance] allowSpeaker]];
return [[LinphoneManager instance] speakerEnabled];
[self setEnabled:[[LinphoneManager instance] allowSpeaker]];
return [[LinphoneManager instance] speakerEnabled];
}
@end

View file

@ -26,7 +26,6 @@
NSTimer *callQualityTimer;
NSTimer *callSecurityTimer;
int messagesUnreadCount;
}
@synthesize registrationStateImage;
@ -39,7 +38,7 @@
- (id)init {
self = [super initWithNibName:@"UIStateBar" bundle:[NSBundle mainBundle]];
if(self != nil) {
if (self != nil) {
self->callSecurityImage = nil;
self->callQualityImage = nil;
self->securitySheet = nil;
@ -47,12 +46,11 @@
return self;
}
- (void) dealloc {
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[callQualityTimer invalidate];
}
#pragma mark - ViewController Functions
- (void)viewWillAppear:(BOOL)animated {
@ -67,97 +65,86 @@
// Set callQualityTimer
callSecurityTimer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:@selector(callSecurityUpdate)
userInfo:nil
repeats:YES];
target:self
selector:@selector(callSecurityUpdate)
userInfo:nil
repeats:YES];
// Set observer
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(registrationUpdate:)
name:kLinphoneRegistrationUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(registrationUpdate:)
name:kLinphoneRegistrationUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(globalStateUpdate:)
name:kLinphoneGlobalStateUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(globalStateUpdate:)
name:kLinphoneGlobalStateUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(notifyReceived:)
name:kLinphoneNotifyReceived
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(notifyReceived:)
name:kLinphoneNotifyReceived
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(callUpdate:)
name:kLinphoneCallUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(callUpdate:)
name:kLinphoneCallUpdate
object:nil];
[callQualityImage setHidden:true];
[callSecurityImage setHidden:true];
[callQualityImage setHidden: true];
[callSecurityImage setHidden: true];
// Update to default state
LinphoneProxyConfig *config = NULL;
linphone_core_get_default_proxy([LinphoneManager getLc], &config);
messagesUnreadCount =
lp_config_get_int(linphone_core_get_config([LinphoneManager getLc]), "app", "voice_mail_messages_count", 0);
// Update to default state
LinphoneProxyConfig* config = NULL;
linphone_core_get_default_proxy([LinphoneManager getLc], &config);
messagesUnreadCount = lp_config_get_int(linphone_core_get_config([LinphoneManager getLc]), "app", "voice_mail_messages_count", 0);
[self proxyConfigUpdate: config];
[self proxyConfigUpdate:config];
[self updateVoicemail];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
// Remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneRegistrationUpdate
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneGlobalStateUpdate
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneNotifyReceived
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneCallUpdate
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneRegistrationUpdate object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneGlobalStateUpdate object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneNotifyReceived object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneCallUpdate object:nil];
if(callQualityTimer != nil) {
if (callQualityTimer != nil) {
[callQualityTimer invalidate];
callQualityTimer = nil;
}
if(callSecurityTimer != nil) {
if (callSecurityTimer != nil) {
[callSecurityTimer invalidate];
callSecurityTimer = nil;
}
}
#pragma mark - Event Functions
- (void)registrationUpdate: (NSNotification*) notif {
LinphoneProxyConfig* config = NULL;
- (void)registrationUpdate:(NSNotification *)notif {
LinphoneProxyConfig *config = NULL;
linphone_core_get_default_proxy([LinphoneManager getLc], &config);
[self proxyConfigUpdate:config];
}
- (void) globalStateUpdate:(NSNotification*) notif {
- (void)globalStateUpdate:(NSNotification *)notif {
[self registrationUpdate:notif];
}
- (void) notifyReceived:(NSNotification*) notif {
const LinphoneContent * content = [[notif.userInfo objectForKey: @"content"] pointerValue];
- (void)notifyReceived:(NSNotification *)notif {
const LinphoneContent *content = [[notif.userInfo objectForKey:@"content"] pointerValue];
if ((content == NULL)
|| (strcmp("application", linphone_content_get_type(content)) != 0)
|| (strcmp("simple-message-summary", linphone_content_get_subtype(content)) != 0)
|| (linphone_content_get_buffer(content) == NULL)) {
if ((content == NULL) || (strcmp("application", linphone_content_get_type(content)) != 0) ||
(strcmp("simple-message-summary", linphone_content_get_subtype(content)) != 0) ||
(linphone_content_get_buffer(content) == NULL)) {
return;
}
const char* body = linphone_content_get_buffer(content);
if ((body = strstr(body, "voice-message: ")) == NULL) {
const char *body = linphone_content_get_buffer(content);
if ((body = strstr(body, "voice-message: ")) == NULL) {
LOGW(@"Received new NOTIFY from voice mail but could not find 'voice-message' in BODY. Ignoring it.");
return;
}
@ -167,40 +154,41 @@
LOGI(@"Received new NOTIFY from voice mail: there is/are now %d message(s) unread", messagesUnreadCount);
// save in lpconfig for future
lp_config_set_int(linphone_core_get_config([LinphoneManager getLc]), "app", "voice_mail_messages_count", messagesUnreadCount);
lp_config_set_int(linphone_core_get_config([LinphoneManager getLc]), "app", "voice_mail_messages_count",
messagesUnreadCount);
[self updateVoicemail];
}
- (void) updateVoicemail {
- (void)updateVoicemail {
if (messagesUnreadCount > 0) {
self.voicemailCount.hidden = (linphone_core_get_calls([LinphoneManager getLc]) != NULL);
self.voicemailCount.text = [[NSString stringWithFormat:NSLocalizedString(@"%d unread messages", @"%d"), messagesUnreadCount] uppercaseString];
self.voicemailCount.text = [[NSString
stringWithFormat:NSLocalizedString(@"%d unread messages", @"%d"), messagesUnreadCount] uppercaseString];
} else {
self.voicemailCount.hidden = TRUE;
}
}
- (void) callUpdate:(NSNotification*) notif {
//show voice mail only when there is no call
- (void)callUpdate:(NSNotification *)notif {
// show voice mail only when there is no call
[self updateVoicemail];
}
#pragma mark -
- (void)proxyConfigUpdate: (LinphoneProxyConfig*) config {
- (void)proxyConfigUpdate:(LinphoneProxyConfig *)config {
LinphoneRegistrationState state = LinphoneRegistrationNone;
NSString* message = nil;
UIImage* image = nil;
LinphoneCore* lc = [LinphoneManager getLc];
NSString *message = nil;
UIImage *image = nil;
LinphoneCore *lc = [LinphoneManager getLc];
LinphoneGlobalState gstate = linphone_core_get_global_state(lc);
if( gstate == LinphoneGlobalConfiguring ){
if (gstate == LinphoneGlobalConfiguring) {
message = NSLocalizedString(@"Fetching remote configuration", nil);
} else if (config == NULL) {
state = LinphoneRegistrationNone;
if(linphone_core_is_network_reachable([LinphoneManager getLc]))
if (linphone_core_is_network_reachable([LinphoneManager getLc]))
message = NSLocalizedString(@"No SIP account configured", nil);
else
message = NSLocalizedString(@"Network down", nil);
@ -208,44 +196,48 @@
state = linphone_proxy_config_get_state(config);
switch (state) {
case LinphoneRegistrationOk:
message = NSLocalizedString(@"Registered", nil); break;
case LinphoneRegistrationNone:
case LinphoneRegistrationCleared:
message = NSLocalizedString(@"Not registered", nil); break;
case LinphoneRegistrationFailed:
message = NSLocalizedString(@"Registration failed", nil); break;
case LinphoneRegistrationProgress:
message = NSLocalizedString(@"Registration in progress", nil); break;
default: break;
case LinphoneRegistrationOk:
message = NSLocalizedString(@"Registered", nil);
break;
case LinphoneRegistrationNone:
case LinphoneRegistrationCleared:
message = NSLocalizedString(@"Not registered", nil);
break;
case LinphoneRegistrationFailed:
message = NSLocalizedString(@"Registration failed", nil);
break;
case LinphoneRegistrationProgress:
message = NSLocalizedString(@"Registration in progress", nil);
break;
default:
break;
}
}
registrationStateLabel.hidden = NO;
switch(state) {
case LinphoneRegistrationFailed:
registrationStateImage.hidden = NO;
image = [UIImage imageNamed:@"led_error.png"];
break;
case LinphoneRegistrationCleared:
case LinphoneRegistrationNone:
registrationStateImage.hidden = NO;
image = [UIImage imageNamed:@"led_disconnected.png"];
break;
case LinphoneRegistrationProgress:
registrationStateImage.hidden = NO;
image = [UIImage imageNamed:@"led_inprogress.png"];
break;
case LinphoneRegistrationOk:
registrationStateImage.hidden = NO;
image = [UIImage imageNamed:@"led_connected.png"];
break;
switch (state) {
case LinphoneRegistrationFailed:
registrationStateImage.hidden = NO;
image = [UIImage imageNamed:@"led_error.png"];
break;
case LinphoneRegistrationCleared:
case LinphoneRegistrationNone:
registrationStateImage.hidden = NO;
image = [UIImage imageNamed:@"led_disconnected.png"];
break;
case LinphoneRegistrationProgress:
registrationStateImage.hidden = NO;
image = [UIImage imageNamed:@"led_inprogress.png"];
break;
case LinphoneRegistrationOk:
registrationStateImage.hidden = NO;
image = [UIImage imageNamed:@"led_connected.png"];
break;
}
[registrationStateLabel setText:message];
[registrationStateImage setImage:image];
}
#pragma mark -
- (void)callSecurityUpdate {
@ -254,28 +246,28 @@
const MSList *list = linphone_core_get_calls([LinphoneManager getLc]);
if(list == NULL) {
if(securitySheet) {
if (list == NULL) {
if (securitySheet) {
[securitySheet dismissWithClickedButtonIndex:securitySheet.destructiveButtonIndex animated:TRUE];
}
[callSecurityImage setHidden:true];
return;
}
while(list != NULL) {
LinphoneCall *call = (LinphoneCall*) list->data;
while (list != NULL) {
LinphoneCall *call = (LinphoneCall *)list->data;
LinphoneMediaEncryption enc = linphone_call_params_get_media_encryption(linphone_call_get_current_params(call));
if(enc == LinphoneMediaEncryptionNone)
if (enc == LinphoneMediaEncryptionNone)
security = false;
else if(enc == LinphoneMediaEncryptionZRTP) {
if(!linphone_call_get_authentication_token_verified(call)) {
else if (enc == LinphoneMediaEncryptionZRTP) {
if (!linphone_call_get_authentication_token_verified(call)) {
pending = true;
}
}
list = list->next;
}
if(security) {
if(pending) {
if (security) {
if (pending) {
[callSecurityImage setImage:[UIImage imageNamed:@"security_pending.png"]];
} else {
[callSecurityImage setImage:[UIImage imageNamed:@"security_ok.png"]];
@ -283,26 +275,26 @@
} else {
[callSecurityImage setImage:[UIImage imageNamed:@"security_ko.png"]];
}
[callSecurityImage setHidden: false];
[callSecurityImage setHidden:false];
}
- (void)callQualityUpdate {
UIImage *image = nil;
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
if(call != NULL) {
//FIXME double check call state before computing, may cause core dump
float quality = linphone_call_get_average_quality(call);
if(quality < 1) {
image = [UIImage imageNamed:@"call_quality_indicator_0.png"];
} else if (quality < 2) {
image = [UIImage imageNamed:@"call_quality_indicator_1.png"];
} else if (quality < 3) {
image = [UIImage imageNamed:@"call_quality_indicator_2.png"];
} else {
image = [UIImage imageNamed:@"call_quality_indicator_3.png"];
}
}
if(image != nil) {
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
if (call != NULL) {
// FIXME double check call state before computing, may cause core dump
float quality = linphone_call_get_average_quality(call);
if (quality < 1) {
image = [UIImage imageNamed:@"call_quality_indicator_0.png"];
} else if (quality < 2) {
image = [UIImage imageNamed:@"call_quality_indicator_1.png"];
} else if (quality < 3) {
image = [UIImage imageNamed:@"call_quality_indicator_2.png"];
} else {
image = [UIImage imageNamed:@"call_quality_indicator_3.png"];
}
}
if (image != nil) {
[callQualityImage setHidden:false];
[callQualityImage setImage:image];
} else {
@ -310,35 +302,38 @@
}
}
#pragma mark - Action Functions
- (IBAction)doSecurityClick:(id)sender {
if(linphone_core_get_calls_nb([LinphoneManager getLc])) {
if (linphone_core_get_calls_nb([LinphoneManager getLc])) {
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
if(call != NULL) {
LinphoneMediaEncryption enc = linphone_call_params_get_media_encryption(linphone_call_get_current_params(call));
if(enc == LinphoneMediaEncryptionZRTP) {
if (call != NULL) {
LinphoneMediaEncryption enc =
linphone_call_params_get_media_encryption(linphone_call_get_current_params(call));
if (enc == LinphoneMediaEncryptionZRTP) {
bool valid = linphone_call_get_authentication_token_verified(call);
NSString *message = nil;
if(valid) {
message = NSLocalizedString(@"Remove trust in the peer?",nil);
if (valid) {
message = NSLocalizedString(@"Remove trust in the peer?", nil);
} else {
message = [NSString stringWithFormat:NSLocalizedString(@"Confirm the following SAS with the peer:\n%s",nil),
linphone_call_get_authentication_token(call)];
message = [NSString
stringWithFormat:NSLocalizedString(@"Confirm the following SAS with the peer:\n%s", nil),
linphone_call_get_authentication_token(call)];
}
if( securitySheet == nil ){
__block __strong UIStateBar* weakSelf = self;
if (securitySheet == nil) {
__block __strong UIStateBar *weakSelf = self;
securitySheet = [[DTActionSheet alloc] initWithTitle:message];
[securitySheet setDelegate:self];
[securitySheet addButtonWithTitle:NSLocalizedString(@"Ok",nil) block:^(){
linphone_call_set_authentication_token_verified(call, !valid);
weakSelf->securitySheet = nil;
}];
[securitySheet addButtonWithTitle:NSLocalizedString(@"Ok", nil)
block:^() {
linphone_call_set_authentication_token_verified(call, !valid);
weakSelf->securitySheet = nil;
}];
[securitySheet addDestructiveButtonWithTitle:NSLocalizedString(@"Cancel",nil) block:^(){
weakSelf->securitySheet = nil;
}];
[securitySheet addDestructiveButtonWithTitle:NSLocalizedString(@"Cancel", nil)
block:^() {
weakSelf->securitySheet = nil;
}];
[securitySheet showInView:[PhoneMainView instance].view];
}
}
@ -346,13 +341,13 @@
}
}
-(void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex{
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
securitySheet = nil;
}
#pragma mark - TPMultiLayoutViewController Functions
- (NSDictionary*)attributesForView:(UIView*)view {
- (NSDictionary *)attributesForView:(UIView *)view {
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
[attributes setObject:[NSValue valueWithCGRect:view.frame] forKey:@"frame"];
@ -362,7 +357,7 @@
return attributes;
}
- (void)applyAttributes:(NSDictionary*)attributes toView:(UIView*)view {
- (void)applyAttributes:(NSDictionary *)attributes toView:(UIView *)view {
view.frame = [[attributes objectForKey:@"frame"] CGRectValue];
view.bounds = [[attributes objectForKey:@"bounds"] CGRectValue];
view.autoresizingMask = [[attributes objectForKey:@"autoresizingMask"] integerValue];

View file

@ -12,27 +12,35 @@
@implementation UITextField (DoneButton)
- (void) addDoneButton {
- (void)addDoneButton {
// actually on iPad there is a done button
if (! [LinphoneManager runningOnIpad]) {
UIToolbar* numberToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
numberToolbar.items = [NSArray arrayWithObjects:
[[UIBarButtonItem alloc]initWithTitle:NSLocalizedString(@"Cancel", nil) style:UIBarButtonItemStyleBordered target:self action:@selector(cancelNumberPad)],
[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
[[UIBarButtonItem alloc]initWithTitle:NSLocalizedString(@"Done", nil) style:UIBarButtonItemStyleDone target:self action:@selector(doneWithNumberPad)],
nil];
if (![LinphoneManager runningOnIpad]) {
UIToolbar *numberToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
numberToolbar.items = [NSArray
arrayWithObjects:[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Cancel", nil)
style:UIBarButtonItemStyleBordered
target:self
action:@selector(cancelNumberPad)],
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil
action:nil],
[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Done", nil)
style:UIBarButtonItemStyleDone
target:self
action:@selector(doneWithNumberPad)],
nil];
[numberToolbar sizeToFit];
self.inputAccessoryView = numberToolbar;
}
}
-(void)cancelNumberPad{
- (void)cancelNumberPad {
[self resignFirstResponder];
self.text = @"";
}
-(void)doneWithNumberPad{
- (void)doneWithNumberPad {
[self resignFirstResponder];
}
@end

View file

@ -12,15 +12,15 @@
@synthesize allowSelectAll;
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender{
// disable "define" option, since it messes with the keyboard
if ([[NSStringFromSelector(action) lowercaseString] rangeOfString:@"define"].location != NSNotFound) {
return NO;
} else if(action == @selector(selectAll:) && allowSelectAll ) {
return YES;
} else {
return [super canPerformAction:action withSender:sender];
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
// disable "define" option, since it messes with the keyboard
if ([[NSStringFromSelector(action) lowercaseString] rangeOfString:@"define"].location != NSNotFound) {
return NO;
} else if (action == @selector(selectAll:) && allowSelectAll) {
return YES;
} else {
return [super canPerformAction:action withSender:sender];
}
}
@end

View file

@ -4,69 +4,66 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "UIToggleButton.h"
@implementation UIToggleButton
#pragma mark - Lifecycle Functions
- (void)initUIToggleButton {
[self update];
[self update];
[self addTarget:self action:@selector(touchUp:) forControlEvents:UIControlEventTouchUpInside];
}
- (id)init {
self = [super init];
if (self) {
self = [super init];
if (self) {
[self initUIToggleButton];
}
return self;
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self = [super initWithFrame:frame];
if (self) {
[self initUIToggleButton];
}
return self;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
self = [super initWithCoder:decoder];
if (self) {
[self initUIToggleButton];
}
return self;
}
return self;
}
#pragma mark -
#pragma mark -
- (void)touchUp:(id) sender {
- (void)touchUp:(id)sender {
[self toggle];
}
- (bool)toggle {
if (self.selected) {
self.selected=!self.selected;
self.selected = !self.selected;
[self onOff];
} else {
self.selected=!self.selected;
self.selected = !self.selected;
[self onOn];
}
return self.selected;
@ -89,23 +86,22 @@
return self.selected;
}
#pragma mark - UIToggleButtonDelegate Functions
-(void) onOn {
/*[NSException raise:NSInternalInconsistencyException
format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];*/
- (void)onOn {
/*[NSException raise:NSInternalInconsistencyException
format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];*/
}
-(void) onOff {
/*[NSException raise:NSInternalInconsistencyException
format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];*/
- (void)onOff {
/*[NSException raise:NSInternalInconsistencyException
format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];*/
}
-(bool) onUpdate {
/*[NSException raise:NSInternalInconsistencyException
format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];*/
return false;
- (bool)onUpdate {
/*[NSException raise:NSInternalInconsistencyException
format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];*/
return false;
}
@end

View file

@ -4,18 +4,18 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "UITransferButton.h"
#import "LinphoneManager.h"
@ -28,39 +28,37 @@
#pragma mark - Lifecycle Functions
- (void)initUICallButton {
[self addTarget:self action:@selector(touchUp:) forControlEvents:UIControlEventTouchUpInside];
[self addTarget:self action:@selector(touchUp:) forControlEvents:UIControlEventTouchUpInside];
}
- (id)init {
self = [super init];
if (self) {
self = [super init];
if (self) {
[self initUICallButton];
}
return self;
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self = [super initWithFrame:frame];
if (self) {
[self initUICallButton];
}
return self;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
self = [super initWithCoder:decoder];
if (self) {
[self initUICallButton];
}
return self;
}
return self;
}
#pragma mark -
- (void)touchUp:(id) sender {
[[LinphoneManager instance] call:[addressField text] displayName:nil transfer:TRUE];
- (void)touchUp:(id)sender {
[[LinphoneManager instance] call:[addressField text] displayName:nil transfer:TRUE];
}
@end

View file

@ -21,19 +21,17 @@
@implementation UITransparentTVCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Set transparent background
[self setBackgroundColor:[UIColor clearColor]];
}
return self;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Set transparent background
[self setBackgroundColor:[UIColor clearColor]];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
}
@end

View file

@ -4,41 +4,41 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "UITransparentView.h"
@implementation UITransparentView
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
BOOL pointInside = NO;
for(UIView *child in [self subviews]) {
if(![child isHidden]) {
if(CGRectContainsPoint(child.frame, point)) {
CGPoint newPoint = point;
newPoint.x -= child.frame.origin.x;
newPoint.y -= child.frame.origin.y;
if([child pointInside:newPoint withEvent:event]) {
pointInside = YES;
break;
}
}
}
}
return pointInside;
BOOL pointInside = NO;
for (UIView *child in [self subviews]) {
if (![child isHidden]) {
if (CGRectContainsPoint(child.frame, point)) {
CGPoint newPoint = point;
newPoint.x -= child.frame.origin.x;
newPoint.y -= child.frame.origin.y;
if ([child pointInside:newPoint withEvent:event]) {
pointInside = YES;
break;
}
}
}
}
return pointInside;
}
@end

View file

@ -4,121 +4,120 @@
*
* 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 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* the Free Software Foundation; either version 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "UIVideoButton.h"
#include "LinphoneManager.h"
@implementation UIVideoButton {
BOOL last_update_state;
BOOL last_update_state;
}
@synthesize waitView;
- (void)initUIVideoButton {
last_update_state = FALSE;
last_update_state = FALSE;
}
- (id)init{
self = [super init];
if (self) {
- (id)init {
self = [super init];
if (self) {
[self initUIVideoButton];
}
return self;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
self = [super initWithCoder:decoder];
if (self) {
[self initUIVideoButton];
}
return self;
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self = [super initWithFrame:frame];
if (self) {
[self initUIVideoButton];
}
return self;
}
return self;
}
- (void)onOn {
LinphoneCore* lc = [LinphoneManager getLc];
if (!linphone_core_video_enabled(lc))
return;
[self setEnabled: FALSE];
[waitView startAnimating];
LinphoneCall* call = linphone_core_get_current_call([LinphoneManager getLc]);
LinphoneCore *lc = [LinphoneManager getLc];
if (!linphone_core_video_enabled(lc))
return;
[self setEnabled:FALSE];
[waitView startAnimating];
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
if (call) {
LinphoneCallAppData* callAppData = (__bridge LinphoneCallAppData*)linphone_call_get_user_pointer(call);
callAppData->videoRequested=TRUE; /* will be used later to notify user if video was not activated because of the linphone core*/
LinphoneCallParams* call_params = linphone_call_params_copy(linphone_call_get_current_params(call));
linphone_call_params_enable_video(call_params, TRUE);
linphone_core_update_call(lc, call, call_params);
LinphoneCallAppData *callAppData = (__bridge LinphoneCallAppData *)linphone_call_get_user_pointer(call);
callAppData->videoRequested =
TRUE; /* will be used later to notify user if video was not activated because of the linphone core*/
LinphoneCallParams *call_params = linphone_call_params_copy(linphone_call_get_current_params(call));
linphone_call_params_enable_video(call_params, TRUE);
linphone_core_update_call(lc, call, call_params);
linphone_call_params_destroy(call_params);
} else {
} else {
LOGW(@"Cannot toggle video button, because no current call");
}
}
}
- (void)onOff {
LinphoneCore* lc = [LinphoneManager getLc];
if (!linphone_core_video_enabled(lc))
return;
[self setEnabled: FALSE];
[waitView startAnimating];
LinphoneCall* call = linphone_core_get_current_call([LinphoneManager getLc]);
if (call) {
LinphoneCallParams* call_params = linphone_call_params_copy(linphone_call_get_current_params(call));
linphone_call_params_enable_video(call_params, FALSE);
linphone_core_update_call(lc, call, call_params);
LinphoneCore *lc = [LinphoneManager getLc];
if (!linphone_core_video_enabled(lc))
return;
[self setEnabled:FALSE];
[waitView startAnimating];
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
if (call) {
LinphoneCallParams *call_params = linphone_call_params_copy(linphone_call_get_current_params(call));
linphone_call_params_enable_video(call_params, FALSE);
linphone_core_update_call(lc, call, call_params);
linphone_call_params_destroy(call_params);
} else {
} else {
LOGW(@"Cannot toggle video button, because no current call");
}
}
- (bool)onUpdate {
bool video_enabled = false;
bool video_enabled = false;
#ifdef VIDEO_ENABLED
LinphoneCall* currentCall = linphone_core_get_current_call([LinphoneManager getLc]);
if( linphone_core_video_enabled([LinphoneManager getLc])
&& currentCall
&& !linphone_call_media_in_progress(currentCall)
&& linphone_call_get_state(currentCall) == LinphoneCallStreamsRunning) {
video_enabled = TRUE;
}
#endif //VIDEO_ENABLED
LinphoneCall *currentCall = linphone_core_get_current_call([LinphoneManager getLc]);
if (linphone_core_video_enabled([LinphoneManager getLc]) && currentCall &&
!linphone_call_media_in_progress(currentCall) &&
linphone_call_get_state(currentCall) == LinphoneCallStreamsRunning) {
video_enabled = TRUE;
}
#endif // VIDEO_ENABLED
[self setEnabled:video_enabled];
if( last_update_state != video_enabled )
[waitView stopAnimating];
if( video_enabled ){
video_enabled = linphone_call_params_video_enabled(linphone_call_get_current_params(currentCall));
}
last_update_state = video_enabled;
[self setEnabled:video_enabled];
if (last_update_state != video_enabled)
[waitView stopAnimating];
if (video_enabled) {
video_enabled = linphone_call_params_video_enabled(linphone_call_get_current_params(currentCall));
}
last_update_state = video_enabled;
return video_enabled;
return video_enabled;
}
@end

View file

@ -4,18 +4,18 @@
*
* 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 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* the Free Software Foundation; either version 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import "VideoZoomHandler.h"
#include "linphone/linphonecore.h"
@ -23,89 +23,89 @@
@implementation VideoZoomHandler
- (void)zoomInOut:(UITapGestureRecognizer*) reco {
if (zoomLevel != 1)
zoomLevel = 1;
else
zoomLevel = 2;
if (zoomLevel != 1) {
CGPoint point = [reco locationInView:videoView];
cx = point.x / videoView.frame.size.width;
cy = 1 - point.y / videoView.frame.size.height;
} else {
cx = cy = 0.5;
}
linphone_call_zoom_video(linphone_core_get_current_call([LinphoneManager getLc]), zoomLevel, &cx, &cy);
- (void)zoomInOut:(UITapGestureRecognizer *)reco {
if (zoomLevel != 1)
zoomLevel = 1;
else
zoomLevel = 2;
if (zoomLevel != 1) {
CGPoint point = [reco locationInView:videoView];
cx = point.x / videoView.frame.size.width;
cy = 1 - point.y / videoView.frame.size.height;
} else {
cx = cy = 0.5;
}
linphone_call_zoom_video(linphone_core_get_current_call([LinphoneManager getLc]), zoomLevel, &cx, &cy);
}
- (void)videoPan:(UIPanGestureRecognizer*) reco {
if (zoomLevel <= 1.0)
return;
float x,y;
CGPoint translation = [reco translationInView:videoView];
if ([reco state] == UIGestureRecognizerStateEnded) {
cx -= translation.x / videoView.frame.size.width;
cy += translation.y / videoView.frame.size.height;
x = cx;
y = cy;
} else if ([reco state] == UIGestureRecognizerStateChanged) {
x = cx - translation.x / videoView.frame.size.width;
y = cy + translation.y / videoView.frame.size.height;
[reco setTranslation:CGPointMake(0, 0) inView:videoView];
} else {
return;
}
linphone_call_zoom_video(linphone_core_get_current_call([LinphoneManager getLc]), zoomLevel, &x, &y);
cx = x;
cy = y;
- (void)videoPan:(UIPanGestureRecognizer *)reco {
if (zoomLevel <= 1.0)
return;
float x, y;
CGPoint translation = [reco translationInView:videoView];
if ([reco state] == UIGestureRecognizerStateEnded) {
cx -= translation.x / videoView.frame.size.width;
cy += translation.y / videoView.frame.size.height;
x = cx;
y = cy;
} else if ([reco state] == UIGestureRecognizerStateChanged) {
x = cx - translation.x / videoView.frame.size.width;
y = cy + translation.y / videoView.frame.size.height;
[reco setTranslation:CGPointMake(0, 0) inView:videoView];
} else {
return;
}
linphone_call_zoom_video(linphone_core_get_current_call([LinphoneManager getLc]), zoomLevel, &x, &y);
cx = x;
cy = y;
}
- (void)pinch:(UIPinchGestureRecognizer*) reco {
float s = zoomLevel;
// CGPoint point = [reco locationInView:videoGroup];
// float ccx = cx + (point.x / videoGroup.frame.size.width - 0.5) / s;
// float ccy = cy - (point.y / videoGroup.frame.size.height - 0.5) / s;
if ([reco state] == UIGestureRecognizerStateEnded) {
zoomLevel = MAX(MIN(zoomLevel * reco.scale, 3.0), 1.0);
s = zoomLevel;
// cx = ccx;
// cy = ccy;
} else if ([reco state] == UIGestureRecognizerStateChanged) {
s = zoomLevel * reco.scale;
s = MAX(MIN(s, 3.0), 1.0);
} else if ([reco state] == UIGestureRecognizerStateBegan) {
} else {
return;
}
linphone_call_zoom_video(linphone_core_get_current_call([LinphoneManager getLc]), s, &cx, &cy);
- (void)pinch:(UIPinchGestureRecognizer *)reco {
float s = zoomLevel;
// CGPoint point = [reco locationInView:videoGroup];
// float ccx = cx + (point.x / videoGroup.frame.size.width - 0.5) / s;
// float ccy = cy - (point.y / videoGroup.frame.size.height - 0.5) / s;
if ([reco state] == UIGestureRecognizerStateEnded) {
zoomLevel = MAX(MIN(zoomLevel * reco.scale, 3.0), 1.0);
s = zoomLevel;
// cx = ccx;
// cy = ccy;
} else if ([reco state] == UIGestureRecognizerStateChanged) {
s = zoomLevel * reco.scale;
s = MAX(MIN(s, 3.0), 1.0);
} else if ([reco state] == UIGestureRecognizerStateBegan) {
} else {
return;
}
linphone_call_zoom_video(linphone_core_get_current_call([LinphoneManager getLc]), s, &cx, &cy);
}
- (void)resetZoom {
zoomLevel = 1;
cx = cy = 0.5;
zoomLevel = 1;
cx = cy = 0.5;
}
- (void)setup: (UIView*) view {
videoView = view;
UITapGestureRecognizer* doubleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(zoomInOut:)];
[doubleFingerTap setNumberOfTapsRequired:2];
[doubleFingerTap setNumberOfTouchesRequired:1];
[videoView addGestureRecognizer:doubleFingerTap];
- (void)setup:(UIView *)view {
videoView = view;
UIPanGestureRecognizer* pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(videoPan:)];
[videoView addGestureRecognizer:pan];
UIPinchGestureRecognizer* pinchReco = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)];
[videoView addGestureRecognizer:pinchReco];
UITapGestureRecognizer *doubleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(zoomInOut:)];
[doubleFingerTap setNumberOfTapsRequired:2];
[doubleFingerTap setNumberOfTouchesRequired:1];
[videoView addGestureRecognizer:doubleFingerTap];
[self resetZoom];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(videoPan:)];
[videoView addGestureRecognizer:pan];
UIPinchGestureRecognizer *pinchReco =
[[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)];
[videoView addGestureRecognizer:pinchReco];
[self resetZoom];
}
@end

File diff suppressed because it is too large Load diff

View file

@ -1,141 +1,135 @@
/*
ColorConverter
you can use it to convert color from RGB space to HSL space and back.
HSL2RGB copied from GLPaint Apple sample: http://developer.apple.com/library/ios/#samplecode/GLPaint/Introduction/Intro.html
HSL2RGB copied from GLPaint Apple sample:
http://developer.apple.com/library/ios/#samplecode/GLPaint/Introduction/Intro.html
RGB2HSL translated from http://www.geekymonkey.com/Programming/CSharp/RGB2HSL_HSL2RGB.htm
From: https://github.com/alessani/ColorConverter
*/
void HSL2RGB(float h, float s, float l, float* outR, float* outG, float* outB)
{
float temp1,
temp2;
float temp[3];
int i;
void HSL2RGB(float h, float s, float l, float *outR, float *outG, float *outB) {
float temp1, temp2;
float temp[3];
int i;
// Check for saturation. If there isn't any just return the luminance value for each, which results in gray.
if(s == 0.0) {
if(outR)
if (s == 0.0) {
if (outR)
*outR = l;
if(outG)
if (outG)
*outG = l;
if(outB)
if (outB)
*outB = l;
return;
}
// Test for luminance and compute temporary values based on luminance and saturation
if(l < 0.5)
if (l < 0.5)
temp2 = l * (1.0 + s);
else
temp2 = l + s - l * s;
temp1 = 2.0 * l - temp2;
temp1 = 2.0 * l - temp2;
// Compute intermediate values based on hue
temp[0] = h + 1.0 / 3.0;
temp[1] = h;
temp[2] = h - 1.0 / 3.0;
for(i = 0; i < 3; ++i) {
for (i = 0; i < 3; ++i) {
// Adjust the range
if(temp[i] < 0.0)
if (temp[i] < 0.0)
temp[i] += 1.0;
if(temp[i] > 1.0)
if (temp[i] > 1.0)
temp[i] -= 1.0;
if(6.0 * temp[i] < 1.0)
if (6.0 * temp[i] < 1.0)
temp[i] = temp1 + (temp2 - temp1) * 6.0 * temp[i];
else {
if(2.0 * temp[i] < 1.0)
if (2.0 * temp[i] < 1.0)
temp[i] = temp2;
else {
if(3.0 * temp[i] < 2.0)
if (3.0 * temp[i] < 2.0)
temp[i] = temp1 + (temp2 - temp1) * ((2.0 / 3.0) - temp[i]) * 6.0;
else
temp[i] = temp1;
}
}
}
// Assign temporary values to R, G, B
if(outR)
if (outR)
*outR = temp[0];
if(outG)
if (outG)
*outG = temp[1];
if(outB)
if (outB)
*outB = temp[2];
}
void RGB2HSL(float r, float g, float b, float *outH, float *outS, float *outL) {
/*r = r/255.0f;
g = g/255.0f;
b = b/255.0f;*/
void RGB2HSL(float r, float g, float b, float* outH, float* outS, float* outL)
{
/*r = r/255.0f;
g = g/255.0f;
b = b/255.0f;*/
float h,s, l, v, m, vm, r2, g2, b2;
h = 0;
s = 0;
v = MAX(r, g);
v = MAX(v, b);
m = MIN(r, g);
m = MIN(m, b);
l = (m+v)/2.0f;
if (l <= 0.0){
if(outH)
float h, s, l, v, m, vm, r2, g2, b2;
h = 0;
s = 0;
v = MAX(r, g);
v = MAX(v, b);
m = MIN(r, g);
m = MIN(m, b);
l = (m + v) / 2.0f;
if (l <= 0.0) {
if (outH)
*outH = h;
if(outS)
if (outS)
*outS = s;
if(outL)
if (outL)
*outL = l;
return;
}
vm = v - m;
s = vm;
if (s > 0.0f){
s/= (l <= 0.5f) ? (v + m) : (2.0 - v - m);
}else{
if(outH)
return;
}
vm = v - m;
s = vm;
if (s > 0.0f) {
s /= (l <= 0.5f) ? (v + m) : (2.0 - v - m);
} else {
if (outH)
*outH = h;
if(outS)
if (outS)
*outS = s;
if(outL)
if (outL)
*outL = l;
return;
}
r2 = (v - r)/vm;
g2 = (v - g)/vm;
b2 = (v - b)/vm;
if (r == v){
h = (g == m ? 5.0f + b2 : 1.0f - g2);
}else if (g == v){
h = (b == m ? 1.0f + r2 : 3.0 - b2);
}else{
h = (r == m ? 3.0f + g2 : 5.0f - r2);
}
h/=6.0f;
if(outH)
*outH = h;
if(outS)
*outS = s;
if(outL)
*outL = l;
return;
}
r2 = (v - r) / vm;
g2 = (v - g) / vm;
b2 = (v - b) / vm;
if (r == v) {
h = (g == m ? 5.0f + b2 : 1.0f - g2);
} else if (g == v) {
h = (b == m ? 1.0f + r2 : 3.0 - b2);
} else {
h = (r == m ? 3.0f + g2 : 5.0f - r2);
}
h /= 6.0f;
if (outH)
*outH = h;
if (outS)
*outS = s;
if (outL)
*outL = l;
}

View file

@ -22,23 +22,22 @@
@implementation FastAddressBook
static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef info, void *context);
static void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info, void *context);
+ (NSString*)getContactDisplayName:(ABRecordRef)contact {
NSString *retString = nil;
if (contact) {
retString = CFBridgingRelease(ABRecordCopyCompositeName(contact));
}
return retString;
+ (NSString *)getContactDisplayName:(ABRecordRef)contact {
NSString *retString = nil;
if (contact) {
retString = CFBridgingRelease(ABRecordCopyCompositeName(contact));
}
return retString;
}
+ (UIImage*)squareImageCrop:(UIImage*)image
{
+ (UIImage *)squareImageCrop:(UIImage *)image {
UIImage *ret = nil;
// This calculates the crop area.
float originalWidth = image.size.width;
float originalWidth = image.size.width;
float originalHeight = image.size.height;
float edge = fminf(originalWidth, originalHeight);
@ -46,117 +45,114 @@ static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef inf
float posX = (originalWidth - edge) / 2.0f;
float posY = (originalHeight - edge) / 2.0f;
CGRect cropSquare = CGRectMake(posX, posY,
edge, edge);
CGRect cropSquare = CGRectMake(posX, posY, edge, edge);
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropSquare);
ret = [UIImage imageWithCGImage:imageRef
scale:image.scale
orientation:image.imageOrientation];
ret = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation];
CGImageRelease(imageRef);
return ret;
}
+ (UIImage*)getContactImage:(ABRecordRef)contact thumbnail:(BOOL)thumbnail {
UIImage* retImage = nil;
if (contact && ABPersonHasImageData(contact)) {
NSData* imgData = CFBridgingRelease(ABPersonCopyImageDataWithFormat(contact, thumbnail?
kABPersonImageFormatThumbnail: kABPersonImageFormatOriginalSize));
+ (UIImage *)getContactImage:(ABRecordRef)contact thumbnail:(BOOL)thumbnail {
UIImage *retImage = nil;
if (contact && ABPersonHasImageData(contact)) {
NSData *imgData = CFBridgingRelease(ABPersonCopyImageDataWithFormat(
contact, thumbnail ? kABPersonImageFormatThumbnail : kABPersonImageFormatOriginalSize));
retImage = [UIImage imageWithData:imgData];
retImage = [UIImage imageWithData:imgData];
if (retImage != nil && retImage.size.width != retImage.size.height) {
LOGI(@"Image is not square : cropping it.");
return [self squareImageCrop:retImage];
}
}
}
return retImage;
return retImage;
}
- (ABRecordRef)getContact:(NSString*)address {
@synchronized (addressBookMap){
return (__bridge ABRecordRef)[addressBookMap objectForKey:address];
}
- (ABRecordRef)getContact:(NSString *)address {
@synchronized(addressBookMap) {
return (__bridge ABRecordRef)[addressBookMap objectForKey:address];
}
}
+ (BOOL)isSipURI:(NSString*)address {
return [address hasPrefix:@"sip:"] || [address hasPrefix:@"sips:"];
+ (BOOL)isSipURI:(NSString *)address {
return [address hasPrefix:@"sip:"] || [address hasPrefix:@"sips:"];
}
+ (NSString*)appendCountryCodeIfPossible:(NSString*)number {
if (![number hasPrefix:@"+"] && ![number hasPrefix:@"00"]) {
NSString* lCountryCode = [[LinphoneManager instance] lpConfigStringForKey:@"countrycode_preference"];
if (lCountryCode && [lCountryCode length]>0) {
//append country code
return [lCountryCode stringByAppendingString:number];
}
}
return number;
+ (NSString *)appendCountryCodeIfPossible:(NSString *)number {
if (![number hasPrefix:@"+"] && ![number hasPrefix:@"00"]) {
NSString *lCountryCode = [[LinphoneManager instance] lpConfigStringForKey:@"countrycode_preference"];
if (lCountryCode && [lCountryCode length] > 0) {
// append country code
return [lCountryCode stringByAppendingString:number];
}
}
return number;
}
+ (NSString*)normalizeSipURI:(NSString*)address {
// replace all whitespaces (non-breakable, utf8 nbsp etc.) by the "classical" whitespace
address = [[address componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] componentsJoinedByString:@" "];
NSString *normalizedSipAddress = nil;
LinphoneAddress* linphoneAddress = linphone_core_interpret_url([LinphoneManager getLc], [address UTF8String]);
if(linphoneAddress != NULL) {
char *tmp = linphone_address_as_string_uri_only(linphoneAddress);
if(tmp != NULL) {
normalizedSipAddress = [NSString stringWithUTF8String:tmp];
// remove transport, if any
NSRange pos = [normalizedSipAddress rangeOfString:@";"];
if (pos.location != NSNotFound) {
normalizedSipAddress = [normalizedSipAddress substringToIndex:pos.location];
}
ms_free(tmp);
}
linphone_address_destroy(linphoneAddress);
}
return normalizedSipAddress;
+ (NSString *)normalizeSipURI:(NSString *)address {
// replace all whitespaces (non-breakable, utf8 nbsp etc.) by the "classical" whitespace
address = [[address componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]
componentsJoinedByString:@" "];
NSString *normalizedSipAddress = nil;
LinphoneAddress *linphoneAddress = linphone_core_interpret_url([LinphoneManager getLc], [address UTF8String]);
if (linphoneAddress != NULL) {
char *tmp = linphone_address_as_string_uri_only(linphoneAddress);
if (tmp != NULL) {
normalizedSipAddress = [NSString stringWithUTF8String:tmp];
// remove transport, if any
NSRange pos = [normalizedSipAddress rangeOfString:@";"];
if (pos.location != NSNotFound) {
normalizedSipAddress = [normalizedSipAddress substringToIndex:pos.location];
}
ms_free(tmp);
}
linphone_address_destroy(linphoneAddress);
}
return normalizedSipAddress;
}
+ (NSString*)normalizePhoneNumber:(NSString*)address {
NSMutableString* lNormalizedAddress = [NSMutableString stringWithString:address];
[lNormalizedAddress replaceOccurrencesOfString:@" "
withString:@""
options:0
range:NSMakeRange(0, [lNormalizedAddress length])];
[lNormalizedAddress replaceOccurrencesOfString:@"("
withString:@""
options:0
range:NSMakeRange(0, [lNormalizedAddress length])];
[lNormalizedAddress replaceOccurrencesOfString:@")"
withString:@""
options:0
range:NSMakeRange(0, [lNormalizedAddress length])];
[lNormalizedAddress replaceOccurrencesOfString:@"-"
withString:@""
options:0
range:NSMakeRange(0, [lNormalizedAddress length])];
return [FastAddressBook appendCountryCodeIfPossible:lNormalizedAddress];
+ (NSString *)normalizePhoneNumber:(NSString *)address {
NSMutableString *lNormalizedAddress = [NSMutableString stringWithString:address];
[lNormalizedAddress replaceOccurrencesOfString:@" "
withString:@""
options:0
range:NSMakeRange(0, [lNormalizedAddress length])];
[lNormalizedAddress replaceOccurrencesOfString:@"("
withString:@""
options:0
range:NSMakeRange(0, [lNormalizedAddress length])];
[lNormalizedAddress replaceOccurrencesOfString:@")"
withString:@""
options:0
range:NSMakeRange(0, [lNormalizedAddress length])];
[lNormalizedAddress replaceOccurrencesOfString:@"-"
withString:@""
options:0
range:NSMakeRange(0, [lNormalizedAddress length])];
return [FastAddressBook appendCountryCodeIfPossible:lNormalizedAddress];
}
+ (BOOL)isAuthorized {
return !ABAddressBookGetAuthorizationStatus || ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized;
return !ABAddressBookGetAuthorizationStatus ||
ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized;
}
- (FastAddressBook*)init {
if ((self = [super init]) != nil) {
addressBookMap = [NSMutableDictionary dictionary];
addressBook = nil;
[self reload];
}
return self;
- (FastAddressBook *)init {
if ((self = [super init]) != nil) {
addressBookMap = [NSMutableDictionary dictionary];
addressBook = nil;
[self reload];
}
return self;
}
- (void)saveAddressBook {
if( addressBook != nil ){
if( !ABAddressBookSave(addressBook, nil) ){
if (addressBook != nil) {
if (!ABAddressBookSave(addressBook, nil)) {
LOGW(@"Couldn't save Address Book");
}
}
@ -166,107 +162,110 @@ static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef inf
CFErrorRef error;
// create if it doesn't exist
if( addressBook == nil ){
if (addressBook == nil) {
addressBook = ABAddressBookCreateWithOptions(NULL, &error);
}
if(addressBook != nil) {
__weak FastAddressBook* weakSelf = self;
if (addressBook != nil) {
__weak FastAddressBook *weakSelf = self;
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
if( !granted ) {
LOGE(@"Permission for address book acces was denied: %@", [(__bridge NSError*)error description]);
return;
}
if (!granted) {
LOGE(@"Permission for address book acces was denied: %@", [(__bridge NSError *)error description]);
return;
}
ABAddressBookRegisterExternalChangeCallback(addressBook, sync_address_book, (__bridge void *)(weakSelf));
[weakSelf loadData];
ABAddressBookRegisterExternalChangeCallback(addressBook, sync_address_book, (__bridge void *)(weakSelf));
[weakSelf loadData];
});
} else {
LOGE(@"Create AddressBook failed, reason: %@", [(__bridge NSError*)error localizedDescription]);
LOGE(@"Create AddressBook failed, reason: %@", [(__bridge NSError *)error localizedDescription]);
}
}
- (void)loadData {
ABAddressBookRevert(addressBook);
@synchronized (addressBookMap) {
[addressBookMap removeAllObjects];
ABAddressBookRevert(addressBook);
@synchronized(addressBookMap) {
[addressBookMap removeAllObjects];
CFArrayRef lContacts = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFArrayRef lContacts = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex count = CFArrayGetCount(lContacts);
for(CFIndex idx = 0; idx < count; idx++){
for (CFIndex idx = 0; idx < count; idx++) {
ABRecordRef lPerson = CFArrayGetValueAtIndex(lContacts, idx);
// Phone
{
ABMultiValueRef lMap = ABRecordCopyValue(lPerson, kABPersonPhoneProperty);
if(lMap) {
for (int i=0; i<ABMultiValueGetCount(lMap); i++) {
CFStringRef lValue = ABMultiValueCopyValueAtIndex(lMap, i);
// Phone
{
ABMultiValueRef lMap = ABRecordCopyValue(lPerson, kABPersonPhoneProperty);
if (lMap) {
for (int i = 0; i < ABMultiValueGetCount(lMap); i++) {
CFStringRef lValue = ABMultiValueCopyValueAtIndex(lMap, i);
NSString* lNormalizedKey = [FastAddressBook normalizePhoneNumber:(__bridge NSString *)(lValue)];
NSString* lNormalizedSipKey = [FastAddressBook normalizeSipURI:lNormalizedKey];
if (lNormalizedSipKey != NULL) lNormalizedKey = lNormalizedSipKey;
NSString *lNormalizedKey = [FastAddressBook normalizePhoneNumber:(__bridge NSString *)(lValue)];
NSString *lNormalizedSipKey = [FastAddressBook normalizeSipURI:lNormalizedKey];
if (lNormalizedSipKey != NULL)
lNormalizedKey = lNormalizedSipKey;
[addressBookMap setObject:(__bridge id)(lPerson) forKey:lNormalizedKey];
[addressBookMap setObject:(__bridge id)(lPerson)forKey:lNormalizedKey];
CFRelease(lValue);
}
CFRelease(lMap);
}
}
}
CFRelease(lMap);
}
}
// SIP
{
ABMultiValueRef lMap = ABRecordCopyValue(lPerson, kABPersonInstantMessageProperty);
if(lMap) {
for(int i = 0; i < ABMultiValueGetCount(lMap); ++i) {
CFDictionaryRef lDict = ABMultiValueCopyValueAtIndex(lMap, i);
BOOL add = false;
if(CFDictionaryContainsKey(lDict, kABPersonInstantMessageServiceKey)) {
if(CFStringCompare((CFStringRef)[LinphoneManager instance].contactSipField, CFDictionaryGetValue(lDict, kABPersonInstantMessageServiceKey), kCFCompareCaseInsensitive) == 0) {
add = true;
}
} else {
add = true;
}
if(add) {
NSString* lValue = (__bridge NSString*)CFDictionaryGetValue(lDict, kABPersonInstantMessageUsernameKey);
NSString* lNormalizedKey = [FastAddressBook normalizeSipURI:lValue];
if(lNormalizedKey != NULL) {
[addressBookMap setObject:(__bridge id)(lPerson) forKey:lNormalizedKey];
} else {
[addressBookMap setObject:(__bridge id)(lPerson) forKey:lValue];
}
}
CFRelease(lDict);
}
CFRelease(lMap);
}
}
}
// SIP
{
ABMultiValueRef lMap = ABRecordCopyValue(lPerson, kABPersonInstantMessageProperty);
if (lMap) {
for (int i = 0; i < ABMultiValueGetCount(lMap); ++i) {
CFDictionaryRef lDict = ABMultiValueCopyValueAtIndex(lMap, i);
BOOL add = false;
if (CFDictionaryContainsKey(lDict, kABPersonInstantMessageServiceKey)) {
if (CFStringCompare((CFStringRef)[LinphoneManager instance].contactSipField,
CFDictionaryGetValue(lDict, kABPersonInstantMessageServiceKey),
kCFCompareCaseInsensitive) == 0) {
add = true;
}
} else {
add = true;
}
if (add) {
NSString *lValue =
(__bridge NSString *)CFDictionaryGetValue(lDict, kABPersonInstantMessageUsernameKey);
NSString *lNormalizedKey = [FastAddressBook normalizeSipURI:lValue];
if (lNormalizedKey != NULL) {
[addressBookMap setObject:(__bridge id)(lPerson)forKey:lNormalizedKey];
} else {
[addressBookMap setObject:(__bridge id)(lPerson)forKey:lValue];
}
}
CFRelease(lDict);
}
CFRelease(lMap);
}
}
}
CFRelease(lContacts);
}
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneAddressBookUpdate object:self];
}
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneAddressBookUpdate object:self];
}
void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef info, void *context) {
FastAddressBook* fastAddressBook = (__bridge FastAddressBook*)context;
[fastAddressBook loadData];
void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info, void *context) {
FastAddressBook *fastAddressBook = (__bridge FastAddressBook *)context;
[fastAddressBook loadData];
}
- (void)dealloc {
ABAddressBookUnregisterExternalChangeCallback(addressBook, sync_address_book, (__bridge void *)(self));
CFRelease(addressBook);
ABAddressBookUnregisterExternalChangeCallback(addressBook, sync_address_book, (__bridge void *)(self));
CFRelease(addressBook);
}
#pragma mark - Tools
+(NSString *)localizedLabel:(NSString *)label {
if( label != nil ){
+ (NSString *)localizedLabel:(NSString *)label {
if (label != nil) {
return CFBridgingRelease(ABAddressBookCopyLocalizedLabel((__bridge CFStringRef)(label)));
}
return @"";
}
@end

View file

@ -23,23 +23,15 @@
#import "OrderedDictionary.h"
NSString *DescriptionForObject(NSObject *object, id locale, NSUInteger indent)
{
NSString *DescriptionForObject(NSObject *object, id locale, NSUInteger indent) {
NSString *objectString;
if ([object isKindOfClass:[NSString class]])
{
if ([object isKindOfClass:[NSString class]]) {
objectString = (NSString *)object;
}
else if ([object respondsToSelector:@selector(descriptionWithLocale:indent:)])
{
} else if ([object respondsToSelector:@selector(descriptionWithLocale:indent:)]) {
objectString = [(NSDictionary *)object descriptionWithLocale:locale indent:indent];
}
else if ([object respondsToSelector:@selector(descriptionWithLocale:)])
{
} else if ([object respondsToSelector:@selector(descriptionWithLocale:)]) {
objectString = [(NSSet *)object descriptionWithLocale:locale];
}
else
{
} else {
objectString = [object description];
}
return objectString;
@ -47,125 +39,101 @@ NSString *DescriptionForObject(NSObject *object, id locale, NSUInteger indent)
@implementation OrderedDictionary
- (void) initObjectsWithCapacity:(NSUInteger)capacity
{
if (self != nil)
{
- (void)initObjectsWithCapacity:(NSUInteger)capacity {
if (self != nil) {
dictionary = [[NSMutableDictionary alloc] initWithCapacity:capacity];
array = [[NSMutableArray alloc] initWithCapacity:capacity];
}
}
- (id)init
{
- (id)init {
self = [super init];
[self initObjectsWithCapacity:0];
return self;
}
- (id)initWithCapacity:(NSUInteger)capacity
{
- (id)initWithCapacity:(NSUInteger)capacity {
self = [super init];
[self initObjectsWithCapacity:0];
return self;
}
- (id)copy
{
- (id)copy {
return [self mutableCopy];
}
- (void)setObject:(id)anObject forKey:(id)aKey
{
if (![dictionary objectForKey:aKey])
{
- (void)setObject:(id)anObject forKey:(id)aKey {
if (![dictionary objectForKey:aKey]) {
[array addObject:aKey];
}
[dictionary setObject:anObject forKey:aKey];
}
- (void)removeObjectForKey:(id)aKey
{
- (void)removeObjectForKey:(id)aKey {
[dictionary removeObjectForKey:aKey];
[array removeObject:aKey];
}
- (NSUInteger)count
{
- (NSUInteger)count {
return [dictionary count];
}
- (id)objectForKey:(id)aKey
{
- (id)objectForKey:(id)aKey {
return [dictionary objectForKey:aKey];
}
- (NSEnumerator *)keyEnumerator
{
- (NSEnumerator *)keyEnumerator {
return [array objectEnumerator];
}
- (NSEnumerator *)reverseKeyEnumerator
{
- (NSEnumerator *)reverseKeyEnumerator {
return [array reverseObjectEnumerator];
}
// Added by Diorcet Yann
- (void)insertObject:(id)anObject forKey:(id)aKey selector:(SEL)comparator
{
if ([dictionary objectForKey:aKey])
{
- (void)insertObject:(id)anObject forKey:(id)aKey selector:(SEL)comparator {
if ([dictionary objectForKey:aKey]) {
[self removeObjectForKey:aKey];
}
NSUInteger anIndex;
NSUInteger anIndex;
IMP imp = [aKey methodForSelector:comparator];
NSComparisonResult (*func)(id, SEL, id) = (void *)imp;
for(anIndex = 0; anIndex < [array count]; ++anIndex) {
NSComparisonResult result = (NSComparisonResult) func(aKey, comparator, [array objectAtIndex: anIndex]);
if(result <= 0) {
break;
}
}
for (anIndex = 0; anIndex < [array count]; ++anIndex) {
NSComparisonResult result = (NSComparisonResult)func(aKey, comparator, [array objectAtIndex:anIndex]);
if (result <= 0) {
break;
}
}
[array insertObject:aKey atIndex:anIndex];
[dictionary setObject:anObject forKey:aKey];
}
//
- (void)insertObject:(id)anObject forKey:(id)aKey atIndex:(NSUInteger)anIndex
{
if ([dictionary objectForKey:aKey])
{
- (void)insertObject:(id)anObject forKey:(id)aKey atIndex:(NSUInteger)anIndex {
if ([dictionary objectForKey:aKey]) {
[self removeObjectForKey:aKey];
}
[array insertObject:aKey atIndex:anIndex];
[dictionary setObject:anObject forKey:aKey];
}
- (id)keyAtIndex:(NSUInteger)anIndex
{
- (id)keyAtIndex:(NSUInteger)anIndex {
return [array objectAtIndex:anIndex];
}
- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level
{
- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level {
NSMutableString *indentString = [NSMutableString string];
NSUInteger i, count = level;
for (i = 0; i < count; i++)
{
for (i = 0; i < count; i++) {
[indentString appendFormat:@" "];
}
NSMutableString *description = [NSMutableString string];
[description appendFormat:@"%@{\n", indentString];
for (NSObject *key in self)
{
[description appendFormat:@"%@ %@ = %@;\n",
indentString,
DescriptionForObject(key, locale, level),
DescriptionForObject([self objectForKey:key], locale, level)];
for (NSObject *key in self) {
[description appendFormat:@"%@ %@ = %@;\n", indentString, DescriptionForObject(key, locale, level),
DescriptionForObject([self objectForKey:key], locale, level)];
}
[description appendFormat:@"%@}\n", indentString];
return description;

View file

@ -17,7 +17,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import "Utils.h"
#include "linphone/linphonecore.h"
#import <CommonCrypto/CommonDigest.h>
@ -34,7 +33,7 @@
if (severity <= ORTP_DEBUG) {
// lol: ortp_debug(XXX) can be disabled at compile time, but ortp_log(ORTP_DEBUG, xxx) will always be valid even
// not in debug build...
ortp_debug("%*s:%3d - %s", filesize, file+MAX((int)strlen(file)-filesize,0), line, [str UTF8String]);
ortp_debug("%*s:%3d - %s", filesize, file + MAX((int)strlen(file) - filesize, 0), line, [str UTF8String]);
} else {
ortp_log(severity, "%*s:%3d - %s", filesize, file + MAX((int)strlen(file) - filesize, 0), line,
[str UTF8String]);
@ -43,9 +42,9 @@
+ (void)log:(OrtpLogLevel)severity file:(const char *)file line:(int)line format:(NSString *)format, ... {
va_list args;
va_start (args, format);
va_start(args, format);
[LinphoneLogger logv:severity file:file line:line format:format args:args];
va_end (args);
va_end(args);
}
#pragma mark - Logs Functions callbacks
@ -82,194 +81,261 @@ void linphone_iphone_log_handler(int lev, const char *fmt, va_list args) {
@implementation LinphoneUtils
+ (BOOL)findAndResignFirstResponder:(UIView*)view {
if (view.isFirstResponder) {
[view resignFirstResponder];
return YES;
}
for (UIView *subView in view.subviews) {
if ([LinphoneUtils findAndResignFirstResponder:subView])
return YES;
}
return NO;
+ (BOOL)findAndResignFirstResponder:(UIView *)view {
if (view.isFirstResponder) {
[view resignFirstResponder];
return YES;
}
for (UIView *subView in view.subviews) {
if ([LinphoneUtils findAndResignFirstResponder:subView])
return YES;
}
return NO;
}
+ (void)adjustFontSize:(UIView*)view mult:(float)mult{
if([view isKindOfClass:[UILabel class]]) {
UILabel *label = (UILabel*)view;
UIFont *font = [label font];
[label setFont:[UIFont fontWithName:font.fontName size:font.pointSize * mult]];
} else if([view isKindOfClass:[UITextField class]]) {
UITextField *label = (UITextField*)view;
UIFont *font = [label font];
[label setFont:[UIFont fontWithName:font.fontName size:font.pointSize * mult]];
} else if([view isKindOfClass:[UIButton class]]) {
UIButton* button = (UIButton*)view;
UIFont* font = button.titleLabel.font;
[button.titleLabel setFont:[UIFont fontWithName:font.fontName size:font.pointSize*mult]];
} else {
for(UIView *subView in [view subviews]) {
[LinphoneUtils adjustFontSize:subView mult:mult];
}
}
+ (void)adjustFontSize:(UIView *)view mult:(float)mult {
if ([view isKindOfClass:[UILabel class]]) {
UILabel *label = (UILabel *)view;
UIFont *font = [label font];
[label setFont:[UIFont fontWithName:font.fontName size:font.pointSize * mult]];
} else if ([view isKindOfClass:[UITextField class]]) {
UITextField *label = (UITextField *)view;
UIFont *font = [label font];
[label setFont:[UIFont fontWithName:font.fontName size:font.pointSize * mult]];
} else if ([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)view;
UIFont *font = button.titleLabel.font;
[button.titleLabel setFont:[UIFont fontWithName:font.fontName size:font.pointSize * mult]];
} else {
for (UIView *subView in [view subviews]) {
[LinphoneUtils adjustFontSize:subView mult:mult];
}
}
}
+ (void)buttonFixStates:(UIButton*)button {
// Set selected+over title: IB lack !
[button setTitle:[button titleForState:UIControlStateSelected]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
+ (void)buttonFixStates:(UIButton *)button {
// Set selected+over title: IB lack !
[button setTitle:[button titleForState:UIControlStateSelected]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+over titleColor: IB lack !
[button setTitleColor:[button titleColorForState:UIControlStateHighlighted]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+over titleColor: IB lack !
[button setTitleColor:[button titleColorForState:UIControlStateHighlighted]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+disabled title: IB lack !
[button setTitle:[button titleForState:UIControlStateSelected]
forState:(UIControlStateDisabled | UIControlStateSelected)];
// Set selected+disabled title: IB lack !
[button setTitle:[button titleForState:UIControlStateSelected]
forState:(UIControlStateDisabled | UIControlStateSelected)];
// Set selected+disabled titleColor: IB lack !
[button setTitleColor:[button titleColorForState:UIControlStateDisabled]
forState:(UIControlStateDisabled | UIControlStateSelected)];
// Set selected+disabled titleColor: IB lack !
[button setTitleColor:[button titleColorForState:UIControlStateDisabled]
forState:(UIControlStateDisabled | UIControlStateSelected)];
}
+ (void)buttonFixStatesForTabs:(UIButton*)button {
// Set selected+over title: IB lack !
[button setTitle:[button titleForState:UIControlStateSelected]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
+ (void)buttonFixStatesForTabs:(UIButton *)button {
// Set selected+over title: IB lack !
[button setTitle:[button titleForState:UIControlStateSelected]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+over titleColor: IB lack !
[button setTitleColor:[button titleColorForState:UIControlStateSelected]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+over titleColor: IB lack !
[button setTitleColor:[button titleColorForState:UIControlStateSelected]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
// Set selected+disabled title: IB lack !
[button setTitle:[button titleForState:UIControlStateSelected]
forState:(UIControlStateDisabled | UIControlStateSelected)];
// Set selected+disabled title: IB lack !
[button setTitle:[button titleForState:UIControlStateSelected]
forState:(UIControlStateDisabled | UIControlStateSelected)];
// Set selected+disabled titleColor: IB lack !
[button setTitleColor:[button titleColorForState:UIControlStateDisabled]
forState:(UIControlStateDisabled | UIControlStateSelected)];
// Set selected+disabled titleColor: IB lack !
[button setTitleColor:[button titleColorForState:UIControlStateDisabled]
forState:(UIControlStateDisabled | UIControlStateSelected)];
}
+ (void)buttonMultiViewAddAttributes:(NSMutableDictionary*)attributes button:(UIButton*)button {
[LinphoneUtils addDictEntry:attributes item:[button titleForState:UIControlStateNormal] key:@"title-normal"];
[LinphoneUtils addDictEntry:attributes item:[button titleForState:UIControlStateHighlighted] key:@"title-highlighted"];
[LinphoneUtils addDictEntry:attributes item:[button titleForState:UIControlStateDisabled] key:@"title-disabled"];
[LinphoneUtils addDictEntry:attributes item:[button titleForState:UIControlStateSelected] key:@"title-selected"];
[LinphoneUtils addDictEntry:attributes item:[button titleForState:UIControlStateDisabled | UIControlStateHighlighted] key:@"title-disabled-highlighted"];
[LinphoneUtils addDictEntry:attributes item:[button titleForState:UIControlStateSelected | UIControlStateHighlighted] key:@"title-selected-highlighted"];
[LinphoneUtils addDictEntry:attributes item:[button titleForState:UIControlStateSelected | UIControlStateDisabled] key:@"title-selected-disabled"];
+ (void)buttonMultiViewAddAttributes:(NSMutableDictionary *)attributes button:(UIButton *)button {
[LinphoneUtils addDictEntry:attributes item:[button titleForState:UIControlStateNormal] key:@"title-normal"];
[LinphoneUtils addDictEntry:attributes
item:[button titleForState:UIControlStateHighlighted]
key:@"title-highlighted"];
[LinphoneUtils addDictEntry:attributes item:[button titleForState:UIControlStateDisabled] key:@"title-disabled"];
[LinphoneUtils addDictEntry:attributes item:[button titleForState:UIControlStateSelected] key:@"title-selected"];
[LinphoneUtils addDictEntry:attributes
item:[button titleForState:UIControlStateDisabled | UIControlStateHighlighted]
key:@"title-disabled-highlighted"];
[LinphoneUtils addDictEntry:attributes
item:[button titleForState:UIControlStateSelected | UIControlStateHighlighted]
key:@"title-selected-highlighted"];
[LinphoneUtils addDictEntry:attributes
item:[button titleForState:UIControlStateSelected | UIControlStateDisabled]
key:@"title-selected-disabled"];
[LinphoneUtils addDictEntry:attributes item:[button titleColorForState:UIControlStateNormal] key:@"title-color-normal"];
[LinphoneUtils addDictEntry:attributes item:[button titleColorForState:UIControlStateHighlighted] key:@"title-color-highlighted"];
[LinphoneUtils addDictEntry:attributes item:[button titleColorForState:UIControlStateDisabled] key:@"title-color-disabled"];
[LinphoneUtils addDictEntry:attributes item:[button titleColorForState:UIControlStateSelected] key:@"title-color-selected"];
[LinphoneUtils addDictEntry:attributes item:[button titleColorForState:UIControlStateDisabled | UIControlStateHighlighted] key:@"title-color-disabled-highlighted"];
[LinphoneUtils addDictEntry:attributes item:[button titleColorForState:UIControlStateSelected | UIControlStateHighlighted] key:@"title-color-selected-highlighted"];
[LinphoneUtils addDictEntry:attributes item:[button titleColorForState:UIControlStateSelected | UIControlStateDisabled] key:@"title-color-selected-disabled"];
[LinphoneUtils addDictEntry:attributes
item:[button titleColorForState:UIControlStateNormal]
key:@"title-color-normal"];
[LinphoneUtils addDictEntry:attributes
item:[button titleColorForState:UIControlStateHighlighted]
key:@"title-color-highlighted"];
[LinphoneUtils addDictEntry:attributes
item:[button titleColorForState:UIControlStateDisabled]
key:@"title-color-disabled"];
[LinphoneUtils addDictEntry:attributes
item:[button titleColorForState:UIControlStateSelected]
key:@"title-color-selected"];
[LinphoneUtils addDictEntry:attributes
item:[button titleColorForState:UIControlStateDisabled | UIControlStateHighlighted]
key:@"title-color-disabled-highlighted"];
[LinphoneUtils addDictEntry:attributes
item:[button titleColorForState:UIControlStateSelected | UIControlStateHighlighted]
key:@"title-color-selected-highlighted"];
[LinphoneUtils addDictEntry:attributes
item:[button titleColorForState:UIControlStateSelected | UIControlStateDisabled]
key:@"title-color-selected-disabled"];
[LinphoneUtils addDictEntry:attributes item:NSStringFromUIEdgeInsets([button titleEdgeInsets]) key:@"title-edge"];
[LinphoneUtils addDictEntry:attributes item:NSStringFromUIEdgeInsets([button contentEdgeInsets]) key:@"content-edge"];
[LinphoneUtils addDictEntry:attributes
item:NSStringFromUIEdgeInsets([button contentEdgeInsets])
key:@"content-edge"];
[LinphoneUtils addDictEntry:attributes item:NSStringFromUIEdgeInsets([button imageEdgeInsets]) key:@"image-edge"];
[LinphoneUtils addDictEntry:attributes item:[button imageForState:UIControlStateNormal] key:@"image-normal"];
[LinphoneUtils addDictEntry:attributes item:[button imageForState:UIControlStateHighlighted] key:@"image-highlighted"];
[LinphoneUtils addDictEntry:attributes item:[button imageForState:UIControlStateDisabled] key:@"image-disabled"];
[LinphoneUtils addDictEntry:attributes item:[button imageForState:UIControlStateSelected] key:@"image-selected"];
[LinphoneUtils addDictEntry:attributes item:[button imageForState:UIControlStateDisabled | UIControlStateHighlighted] key:@"image-disabled-highlighted"];
[LinphoneUtils addDictEntry:attributes item:[button imageForState:UIControlStateSelected | UIControlStateHighlighted] key:@"image-selected-highlighted"];
[LinphoneUtils addDictEntry:attributes item:[button imageForState:UIControlStateSelected | UIControlStateDisabled] key:@"image-selected-disabled"];
[LinphoneUtils addDictEntry:attributes item:[button imageForState:UIControlStateNormal] key:@"image-normal"];
[LinphoneUtils addDictEntry:attributes
item:[button imageForState:UIControlStateHighlighted]
key:@"image-highlighted"];
[LinphoneUtils addDictEntry:attributes item:[button imageForState:UIControlStateDisabled] key:@"image-disabled"];
[LinphoneUtils addDictEntry:attributes item:[button imageForState:UIControlStateSelected] key:@"image-selected"];
[LinphoneUtils addDictEntry:attributes
item:[button imageForState:UIControlStateDisabled | UIControlStateHighlighted]
key:@"image-disabled-highlighted"];
[LinphoneUtils addDictEntry:attributes
item:[button imageForState:UIControlStateSelected | UIControlStateHighlighted]
key:@"image-selected-highlighted"];
[LinphoneUtils addDictEntry:attributes
item:[button imageForState:UIControlStateSelected | UIControlStateDisabled]
key:@"image-selected-disabled"];
[LinphoneUtils addDictEntry:attributes item:[button backgroundImageForState:UIControlStateNormal] key:@"background-normal"];
[LinphoneUtils addDictEntry:attributes item:[button backgroundImageForState:UIControlStateHighlighted] key:@"background-highlighted"];
[LinphoneUtils addDictEntry:attributes item:[button backgroundImageForState:UIControlStateDisabled] key:@"background-disabled"];
[LinphoneUtils addDictEntry:attributes item:[button backgroundImageForState:UIControlStateSelected] key:@"background-selected"];
[LinphoneUtils addDictEntry:attributes item:[button backgroundImageForState:UIControlStateDisabled | UIControlStateHighlighted] key:@"background-disabled-highlighted"];
[LinphoneUtils addDictEntry:attributes item:[button backgroundImageForState:UIControlStateSelected | UIControlStateHighlighted] key:@"background-selected-highlighted"];
[LinphoneUtils addDictEntry:attributes item:[button backgroundImageForState:UIControlStateSelected | UIControlStateDisabled] key:@"background-selected-disabled"];
[LinphoneUtils addDictEntry:attributes
item:[button backgroundImageForState:UIControlStateNormal]
key:@"background-normal"];
[LinphoneUtils addDictEntry:attributes
item:[button backgroundImageForState:UIControlStateHighlighted]
key:@"background-highlighted"];
[LinphoneUtils addDictEntry:attributes
item:[button backgroundImageForState:UIControlStateDisabled]
key:@"background-disabled"];
[LinphoneUtils addDictEntry:attributes
item:[button backgroundImageForState:UIControlStateSelected]
key:@"background-selected"];
[LinphoneUtils addDictEntry:attributes
item:[button backgroundImageForState:UIControlStateDisabled | UIControlStateHighlighted]
key:@"background-disabled-highlighted"];
[LinphoneUtils addDictEntry:attributes
item:[button backgroundImageForState:UIControlStateSelected | UIControlStateHighlighted]
key:@"background-selected-highlighted"];
[LinphoneUtils addDictEntry:attributes
item:[button backgroundImageForState:UIControlStateSelected | UIControlStateDisabled]
key:@"background-selected-disabled"];
}
+ (void)buttonMultiViewApplyAttributes:(NSDictionary*)attributes button:(UIButton*)button {
[button setTitle:[LinphoneUtils getDictEntry:attributes key:@"title-normal"] forState:UIControlStateNormal];
[button setTitle:[LinphoneUtils getDictEntry:attributes key:@"title-highlighted"] forState:UIControlStateHighlighted];
[button setTitle:[LinphoneUtils getDictEntry:attributes key:@"title-disabled"] forState:UIControlStateDisabled];
[button setTitle:[LinphoneUtils getDictEntry:attributes key:@"title-selected"] forState:UIControlStateSelected];
[button setTitle:[LinphoneUtils getDictEntry:attributes key:@"title-disabled-highlighted"] forState:UIControlStateDisabled | UIControlStateHighlighted];
[button setTitle:[LinphoneUtils getDictEntry:attributes key:@"title-selected-highlighted"] forState:UIControlStateSelected | UIControlStateHighlighted];
[button setTitle:[LinphoneUtils getDictEntry:attributes key:@"title-selected-disabled"] forState:UIControlStateSelected | UIControlStateDisabled];
+ (void)buttonMultiViewApplyAttributes:(NSDictionary *)attributes button:(UIButton *)button {
[button setTitle:[LinphoneUtils getDictEntry:attributes key:@"title-normal"] forState:UIControlStateNormal];
[button setTitle:[LinphoneUtils getDictEntry:attributes key:@"title-highlighted"]
forState:UIControlStateHighlighted];
[button setTitle:[LinphoneUtils getDictEntry:attributes key:@"title-disabled"] forState:UIControlStateDisabled];
[button setTitle:[LinphoneUtils getDictEntry:attributes key:@"title-selected"] forState:UIControlStateSelected];
[button setTitle:[LinphoneUtils getDictEntry:attributes key:@"title-disabled-highlighted"]
forState:UIControlStateDisabled | UIControlStateHighlighted];
[button setTitle:[LinphoneUtils getDictEntry:attributes key:@"title-selected-highlighted"]
forState:UIControlStateSelected | UIControlStateHighlighted];
[button setTitle:[LinphoneUtils getDictEntry:attributes key:@"title-selected-disabled"]
forState:UIControlStateSelected | UIControlStateDisabled];
[button setTitleColor:[LinphoneUtils getDictEntry:attributes key:@"title-color-normal"] forState:UIControlStateNormal];
[button setTitleColor:[LinphoneUtils getDictEntry:attributes key:@"title-color-highlighted"] forState:UIControlStateHighlighted];
[button setTitleColor:[LinphoneUtils getDictEntry:attributes key:@"title-color-disabled"] forState:UIControlStateDisabled];
[button setTitleColor:[LinphoneUtils getDictEntry:attributes key:@"title-color-selected"] forState:UIControlStateSelected];
[button setTitleColor:[LinphoneUtils getDictEntry:attributes key:@"title-color-disabled-highlighted"] forState:UIControlStateDisabled | UIControlStateHighlighted];
[button setTitleColor:[LinphoneUtils getDictEntry:attributes key:@"title-color-selected-highlighted"] forState:UIControlStateSelected | UIControlStateHighlighted];
[button setTitleColor:[LinphoneUtils getDictEntry:attributes key:@"title-color-selected-disabled"] forState:UIControlStateSelected | UIControlStateDisabled];
[button setTitleColor:[LinphoneUtils getDictEntry:attributes key:@"title-color-normal"]
forState:UIControlStateNormal];
[button setTitleColor:[LinphoneUtils getDictEntry:attributes key:@"title-color-highlighted"]
forState:UIControlStateHighlighted];
[button setTitleColor:[LinphoneUtils getDictEntry:attributes key:@"title-color-disabled"]
forState:UIControlStateDisabled];
[button setTitleColor:[LinphoneUtils getDictEntry:attributes key:@"title-color-selected"]
forState:UIControlStateSelected];
[button setTitleColor:[LinphoneUtils getDictEntry:attributes key:@"title-color-disabled-highlighted"]
forState:UIControlStateDisabled | UIControlStateHighlighted];
[button setTitleColor:[LinphoneUtils getDictEntry:attributes key:@"title-color-selected-highlighted"]
forState:UIControlStateSelected | UIControlStateHighlighted];
[button setTitleColor:[LinphoneUtils getDictEntry:attributes key:@"title-color-selected-disabled"]
forState:UIControlStateSelected | UIControlStateDisabled];
[button setTitleEdgeInsets:UIEdgeInsetsFromString([LinphoneUtils getDictEntry:attributes key:@"title-edge"])];
[button setContentEdgeInsets:UIEdgeInsetsFromString([LinphoneUtils getDictEntry:attributes key:@"content-edge"])];
[button setImageEdgeInsets:UIEdgeInsetsFromString([LinphoneUtils getDictEntry:attributes key:@"image-edge"])];
[button setImage:[LinphoneUtils getDictEntry:attributes key:@"image-normal"] forState:UIControlStateNormal];
[button setImage:[LinphoneUtils getDictEntry:attributes key:@"image-highlighted"] forState:UIControlStateHighlighted];
[button setImage:[LinphoneUtils getDictEntry:attributes key:@"image-disabled"] forState:UIControlStateDisabled];
[button setImage:[LinphoneUtils getDictEntry:attributes key:@"image-selected"] forState:UIControlStateSelected];
[button setImage:[LinphoneUtils getDictEntry:attributes key:@"image-disabled-highlighted"] forState:UIControlStateDisabled | UIControlStateHighlighted];
[button setImage:[LinphoneUtils getDictEntry:attributes key:@"image-selected-highlighted"] forState:UIControlStateSelected | UIControlStateHighlighted];
[button setImage:[LinphoneUtils getDictEntry:attributes key:@"image-selected-disabled"] forState:UIControlStateSelected | UIControlStateDisabled];
[button setImage:[LinphoneUtils getDictEntry:attributes key:@"image-normal"] forState:UIControlStateNormal];
[button setImage:[LinphoneUtils getDictEntry:attributes key:@"image-highlighted"]
forState:UIControlStateHighlighted];
[button setImage:[LinphoneUtils getDictEntry:attributes key:@"image-disabled"] forState:UIControlStateDisabled];
[button setImage:[LinphoneUtils getDictEntry:attributes key:@"image-selected"] forState:UIControlStateSelected];
[button setImage:[LinphoneUtils getDictEntry:attributes key:@"image-disabled-highlighted"]
forState:UIControlStateDisabled | UIControlStateHighlighted];
[button setImage:[LinphoneUtils getDictEntry:attributes key:@"image-selected-highlighted"]
forState:UIControlStateSelected | UIControlStateHighlighted];
[button setImage:[LinphoneUtils getDictEntry:attributes key:@"image-selected-disabled"]
forState:UIControlStateSelected | UIControlStateDisabled];
[button setBackgroundImage:[LinphoneUtils getDictEntry:attributes key:@"background-normal"] forState:UIControlStateNormal];
[button setBackgroundImage:[LinphoneUtils getDictEntry:attributes key:@"background-highlighted"] forState:UIControlStateHighlighted];
[button setBackgroundImage:[LinphoneUtils getDictEntry:attributes key:@"background-disabled"] forState:UIControlStateDisabled];
[button setBackgroundImage:[LinphoneUtils getDictEntry:attributes key:@"background-selected"] forState:UIControlStateSelected];
[button setBackgroundImage:[LinphoneUtils getDictEntry:attributes key:@"background-disabled-highlighted"] forState:UIControlStateDisabled | UIControlStateHighlighted];
[button setBackgroundImage:[LinphoneUtils getDictEntry:attributes key:@"background-selected-highlighted"] forState:UIControlStateSelected | UIControlStateHighlighted];
[button setBackgroundImage:[LinphoneUtils getDictEntry:attributes key:@"background-selected-disabled"] forState:UIControlStateSelected | UIControlStateDisabled];
[button setBackgroundImage:[LinphoneUtils getDictEntry:attributes key:@"background-normal"]
forState:UIControlStateNormal];
[button setBackgroundImage:[LinphoneUtils getDictEntry:attributes key:@"background-highlighted"]
forState:UIControlStateHighlighted];
[button setBackgroundImage:[LinphoneUtils getDictEntry:attributes key:@"background-disabled"]
forState:UIControlStateDisabled];
[button setBackgroundImage:[LinphoneUtils getDictEntry:attributes key:@"background-selected"]
forState:UIControlStateSelected];
[button setBackgroundImage:[LinphoneUtils getDictEntry:attributes key:@"background-disabled-highlighted"]
forState:UIControlStateDisabled | UIControlStateHighlighted];
[button setBackgroundImage:[LinphoneUtils getDictEntry:attributes key:@"background-selected-highlighted"]
forState:UIControlStateSelected | UIControlStateHighlighted];
[button setBackgroundImage:[LinphoneUtils getDictEntry:attributes key:@"background-selected-disabled"]
forState:UIControlStateSelected | UIControlStateDisabled];
}
+ (void)addDictEntry:(NSMutableDictionary*)dict item:(id)item key:(id)key {
if(item != nil && key != nil) {
[dict setObject:item forKey:key];
}
+ (void)addDictEntry:(NSMutableDictionary *)dict item:(id)item key:(id)key {
if (item != nil && key != nil) {
[dict setObject:item forKey:key];
}
}
+ (id)getDictEntry:(NSDictionary*)dict key:(id)key {
if(key != nil) {
return [dict objectForKey:key];
}
return nil;
+ (id)getDictEntry:(NSDictionary *)dict key:(id)key {
if (key != nil) {
return [dict objectForKey:key];
}
return nil;
}
@end
@implementation NSNumber (HumanReadableSize)
- (NSString*)toHumanReadableSize {
float floatSize = [self floatValue];
- (NSString *)toHumanReadableSize {
float floatSize = [self floatValue];
if (floatSize < 1023)
return([NSString stringWithFormat:@"%1.0f bytes",floatSize]);
return ([NSString stringWithFormat:@"%1.0f bytes", floatSize]);
floatSize = floatSize / 1024;
if (floatSize < 1023)
return([NSString stringWithFormat:@"%1.1f KB",floatSize]);
return ([NSString stringWithFormat:@"%1.1f KB", floatSize]);
floatSize = floatSize / 1024;
if (floatSize < 1023)
return([NSString stringWithFormat:@"%1.1f MB",floatSize]);
return ([NSString stringWithFormat:@"%1.1f MB", floatSize]);
floatSize = floatSize / 1024;
return([NSString stringWithFormat:@"%1.1f GB",floatSize]);
return ([NSString stringWithFormat:@"%1.1f GB", floatSize]);
}
@end
@implementation NSString(md5)
@implementation NSString (md5)
- (NSString *)md5 {
const char *ptr = [self UTF8String];
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
CC_MD5(ptr, (unsigned int)strlen(ptr), md5Buffer);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
[output appendFormat:@"%02x",md5Buffer[i]];
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
[output appendFormat:@"%02x", md5Buffer[i]];
}
return output;

File diff suppressed because it is too large Load diff

View file

@ -21,49 +21,55 @@
#pragma mark - Utils
- (void)setText:(NSString*)text forContactHeaderIndex:(NSInteger)idx {
[tester tapRowAtIndexPath:[NSIndexPath indexPathForRow:idx inSection:0] inTableViewWithAccessibilityIdentifier:@"Contact Name Table"];
[tester enterTextIntoCurrentFirstResponder:text];
- (void)setText:(NSString *)text forContactHeaderIndex:(NSInteger)idx {
[tester tapRowAtIndexPath:[NSIndexPath indexPathForRow:idx inSection:0]
inTableViewWithAccessibilityIdentifier:@"Contact Name Table"];
[tester enterTextIntoCurrentFirstResponder:text];
}
- (void)setText:(NSString*)text forContactNumbersIndex:(NSInteger)idx inSection:(NSInteger)section {
[tester tapRowAtIndexPath:[NSIndexPath indexPathForRow:idx inSection:section] inTableViewWithAccessibilityIdentifier:@"Contact numbers table"];
[tester enterTextIntoCurrentFirstResponder:text];
- (void)setText:(NSString *)text forContactNumbersIndex:(NSInteger)idx inSection:(NSInteger)section {
[tester tapRowAtIndexPath:[NSIndexPath indexPathForRow:idx inSection:section]
inTableViewWithAccessibilityIdentifier:@"Contact numbers table"];
[tester enterTextIntoCurrentFirstResponder:text];
}
- (void)createContact:(NSString*)firstName lastName:(NSString*)lastName phoneNumber:(NSString*)phone SIPAddress:(NSString*)sip {
XCTAssert(firstName != nil);
[tester tapViewWithAccessibilityLabel:@"Add contact"];
// check that the OK button is disabled
[tester waitForViewWithAccessibilityLabel:@"Edit" traits:UIAccessibilityTraitButton|UIAccessibilityTraitNotEnabled|UIAccessibilityTraitSelected];
[self setText:firstName forContactHeaderIndex:0];
// entering text should enable the "edit" button
[tester waitForViewWithAccessibilityLabel:@"Edit" traits:UIAccessibilityTraitButton|UIAccessibilityTraitSelected];
if( lastName )
[self setText:lastName forContactHeaderIndex:1];
if ( phone ){
[self setText:phone forContactNumbersIndex:0 inSection:ContactSections_Number];
}
if ( sip ){
[self setText:sip forContactNumbersIndex:0 inSection:ContactSections_Sip];
}
[tester tapViewWithAccessibilityLabel:@"Edit"];
[tester tapViewWithAccessibilityLabel:@"Back"];
- (void)createContact:(NSString *)firstName
lastName:(NSString *)lastName
phoneNumber:(NSString *)phone
SIPAddress:(NSString *)sip {
XCTAssert(firstName != nil);
[tester tapViewWithAccessibilityLabel:@"Add contact"];
// check that the OK button is disabled
[tester waitForViewWithAccessibilityLabel:@"Edit"
traits:UIAccessibilityTraitButton | UIAccessibilityTraitNotEnabled |
UIAccessibilityTraitSelected];
[self setText:firstName forContactHeaderIndex:0];
// entering text should enable the "edit" button
[tester waitForViewWithAccessibilityLabel:@"Edit" traits:UIAccessibilityTraitButton | UIAccessibilityTraitSelected];
if (lastName)
[self setText:lastName forContactHeaderIndex:1];
if (phone) {
[self setText:phone forContactNumbersIndex:0 inSection:ContactSections_Number];
}
if (sip) {
[self setText:sip forContactNumbersIndex:0 inSection:ContactSections_Sip];
}
[tester tapViewWithAccessibilityLabel:@"Edit"];
[tester tapViewWithAccessibilityLabel:@"Back"];
}
#pragma mark - Tests
- (void)testDeleteContact {
NSString* contactName = [self getUUID];
NSString *contactName = [self getUUID];
[self createContact:contactName lastName:@"dummy" phoneNumber:@"0102030405" SIPAddress:[self me]];
NSString *fullName = [contactName stringByAppendingString:@" dummy"];
@ -128,14 +134,14 @@
}
- (void)testEditContact {
NSString* contactName = [self getUUID];
NSString* fullName = [contactName stringByAppendingString:@" dummy"];
[self createContact:contactName lastName:@"dummy" phoneNumber:nil SIPAddress:nil];
[tester tapViewWithAccessibilityLabel:fullName traits:UIAccessibilityTraitStaticText];
/* Phone number */
NSArray* phones = @[@"01234", @"56789"];
NSString *contactName = [self getUUID];
NSString *fullName = [contactName stringByAppendingString:@" dummy"];
[self createContact:contactName lastName:@"dummy" phoneNumber:nil SIPAddress:nil];
[tester tapViewWithAccessibilityLabel:fullName traits:UIAccessibilityTraitStaticText];
/* Phone number */
NSArray *phones = @[ @"01234", @"56789" ];
[self addEntries:phones inSection:ContactSections_Number];
NSArray *SIPs = @[ @"sip1", @"sip2" ];
[self addEntries:SIPs inSection:ContactSections_Sip];
@ -158,10 +164,9 @@
[tester scrollViewWithAccessibilityIdentifier:@"Contact numbers table" byFractionOfSizeHorizontal:0 vertical:-0.9];
[tester tapViewWithAccessibilityLabel:@"Remove"];
[tester waitForAbsenceOfViewWithAccessibilityLabel:fullName traits:UIAccessibilityTraitStaticText];
[tester tapViewWithAccessibilityLabel:@"Remove"];
[tester waitForAbsenceOfViewWithAccessibilityLabel:fullName traits:UIAccessibilityTraitStaticText];
}
@end

View file

@ -45,41 +45,41 @@
}
- (NSString *)accountDomain {
return @"sip.linphone.org";
return @"sip.linphone.org";
}
- (NSString*)getUUID {
return [[[NSUUID UUID] UUIDString] substringToIndex:8];
- (NSString *)getUUID {
return [[[NSUUID UUID] UUIDString] substringToIndex:8];
}
- (NSArray *)getUUIDArrayOfSize:(size_t)size {
NSMutableArray* array = [NSMutableArray arrayWithCapacity:size];
for (NSInteger i=0; i<size; i++) {
[array setObject:[self getUUID] atIndexedSubscript:i];
}
return array;
NSMutableArray *array = [NSMutableArray arrayWithCapacity:size];
for (NSInteger i = 0; i < size; i++) {
[array setObject:[self getUUID] atIndexedSubscript:i];
}
return array;
}
static bool invalidAccount = true;
- (void)setInvalidAccountSet:(BOOL)invalidAccountSet {
invalidAccount = invalidAccountSet;
invalidAccount = invalidAccountSet;
}
- (BOOL)invalidAccountSet {
return invalidAccount;
return invalidAccount;
}
- (BOOL)hasValidProxyConfig {
LinphoneCore* lc = [LinphoneManager getLc];
const MSList* proxies = linphone_core_get_proxy_config_list(lc);
BOOL isOK = false;
while(proxies){
LinphoneProxyConfig* cfg = (LinphoneProxyConfig*)proxies->data;
const char* domain = linphone_proxy_config_get_domain(cfg);
const char* identity = linphone_proxy_config_get_identity(cfg);
LinphoneAddress* addr = linphone_core_interpret_url(lc, identity);
const char* username = linphone_address_get_username(addr);
LinphoneCore *lc = [LinphoneManager getLc];
const MSList *proxies = linphone_core_get_proxy_config_list(lc);
BOOL isOK = false;
while (proxies) {
LinphoneProxyConfig *cfg = (LinphoneProxyConfig *)proxies->data;
const char *domain = linphone_proxy_config_get_domain(cfg);
const char *identity = linphone_proxy_config_get_identity(cfg);
LinphoneAddress *addr = linphone_core_interpret_url(lc, identity);
const char *username = linphone_address_get_username(addr);
if (addr && (username && strcmp(username, [[self me] UTF8String]) == 0) &&
(domain && strcmp(domain, [[self accountDomain] UTF8String]) == 0) &&
@ -97,13 +97,13 @@ static bool invalidAccount = true;
}
- (void)switchToValidAccountIfNeeded {
[UIView setAnimationsEnabled:false];
[UIView setAnimationsEnabled:false];
if (invalidAccount && ![self hasValidProxyConfig]) {
[tester tapViewWithAccessibilityLabel:@"Settings"];
[tester tapViewWithAccessibilityLabel:@"Run assistant"];
[tester waitForTimeInterval:0.5];
[tester waitForTimeInterval:0.5];
if ([tester tryFindingViewWithAccessibilityLabel:@"Launch Wizard" error:nil]) {
[tester tapViewWithAccessibilityLabel:@"Launch Wizard"];
[tester waitForTimeInterval:0.5];

View file

@ -6,7 +6,6 @@
//
//
#import "WizardTester.h"
#import <KIF/KIF.h>
@ -25,35 +24,33 @@
}
}
- (void)afterEach{
- (void)afterEach {
[super afterEach];
[tester tapViewWithAccessibilityLabel:@"Dialer"];
}
#pragma mark - State
#pragma mark - State
+ (void)switchToValidAccountWithTester:(KIFTestCase*)testCase {
+ (void)switchToValidAccountWithTester:(KIFTestCase *)testCase {
}
#pragma mark - Utilities
- (void)_linphoneLogin:(NSString*)username withPW:(NSString*)pw {
[tester tapViewWithAccessibilityLabel:@"Start"];
[tester tapViewWithAccessibilityLabel:@"Sign in linphone.org account"];
[tester enterText:username intoViewWithAccessibilityLabel:@"Username"];
[tester enterText:pw intoViewWithAccessibilityLabel:@"Password"];
[tester tapViewWithAccessibilityLabel:@"Sign in"];
- (void)_linphoneLogin:(NSString *)username withPW:(NSString *)pw {
[tester tapViewWithAccessibilityLabel:@"Start"];
[tester tapViewWithAccessibilityLabel:@"Sign in linphone.org account"];
[tester enterText:username intoViewWithAccessibilityLabel:@"Username"];
[tester enterText:pw intoViewWithAccessibilityLabel:@"Password"];
[tester tapViewWithAccessibilityLabel:@"Sign in"];
}
- (void)_externalLoginWithProtocol:(NSString *)protocol {
- (void)_externalLoginWithProtocol:(NSString*)protocol {
[self setInvalidAccountSet:true];
[tester tapViewWithAccessibilityLabel:@"Start"];
[tester tapViewWithAccessibilityLabel:@"Sign in SIP account"];
[self setInvalidAccountSet:true];
[tester tapViewWithAccessibilityLabel:@"Start"];
[tester tapViewWithAccessibilityLabel:@"Sign in SIP account"];
[tester enterText:[self me] intoViewWithAccessibilityLabel:@"Username"];
[tester enterText:@"testtest" intoViewWithAccessibilityLabel:@"Password"];

View file

@ -8,23 +8,19 @@
#import "DTObjectBlockExecutor.h"
@implementation DTObjectBlockExecutor
+ (id)blockExecutorWithDeallocBlock:(void(^)())block
{
DTObjectBlockExecutor *executor = [[DTObjectBlockExecutor alloc] init];
executor.deallocBlock = block; // copy
return executor;
+ (id)blockExecutorWithDeallocBlock:(void (^)())block {
DTObjectBlockExecutor *executor = [[DTObjectBlockExecutor alloc] init];
executor.deallocBlock = block; // copy
return executor;
}
- (void)dealloc
{
if (_deallocBlock)
{
_deallocBlock();
_deallocBlock = nil;
}
- (void)dealloc {
if (_deallocBlock) {
_deallocBlock();
_deallocBlock = nil;
}
}
@end

View file

@ -13,40 +13,37 @@
#import "Utils.h"
@interface LinphoneTester_Tests : XCTestCase
@property (retain, nonatomic) NSString* bundlePath;
@property (retain, nonatomic) NSString* documentPath;
@property(retain, nonatomic) NSString *bundlePath;
@property(retain, nonatomic) NSString *documentPath;
@end
@implementation LinphoneTester_Tests
+ (NSArray*)skippedSuites {
NSArray* skipped_suites = @[@"Flexisip"];
+ (NSArray *)skippedSuites {
NSArray *skipped_suites = @[ @"Flexisip" ];
return skipped_suites;
}
+ (NSString*)safetyTestString:(NSString*)testString{
NSCharacterSet *charactersToRemove = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
return [[testString componentsSeparatedByCharactersInSet:charactersToRemove] componentsJoinedByString:@"_"];
+ (NSString *)safetyTestString:(NSString *)testString {
NSCharacterSet *charactersToRemove = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
return [[testString componentsSeparatedByCharactersInSet:charactersToRemove] componentsJoinedByString:@"_"];
}
+ (void)initialize {
static char * bundle = NULL;
static char * documents = NULL;
bc_tester_init((void (*)(int, const char *fm, va_list))linphone_iphone_log_handler, ORTP_MESSAGE, ORTP_ERROR);
static char *bundle = NULL;
static char *documents = NULL;
bc_tester_init((void (*)(int, const char *fm, va_list))linphone_iphone_log_handler, ORTP_MESSAGE, ORTP_ERROR);
liblinphone_tester_add_suites();
NSString* bundlePath = [[NSBundle mainBundle] bundlePath];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentPath = [paths objectAtIndex:0];
bundle = ms_strdup([bundlePath UTF8String]);
documents = ms_strdup([documentPath UTF8String]);
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath = [paths objectAtIndex:0];
bundle = ms_strdup([bundlePath UTF8String]);
documents = ms_strdup([documentPath UTF8String]);
LOGI(@"Bundle path: %@", bundlePath);
LOGI(@"Document path: %@", documentPath);
LOGI(@"Bundle path: %@", bundlePath);
LOGI(@"Document path: %@", documentPath);
bc_tester_set_resource_dir_prefix(bundle);
bc_tester_set_writable_dir_prefix(documents);
@ -54,42 +51,42 @@
liblinphone_tester_keep_accounts(TRUE);
int count = bc_tester_nb_suites();
for (int i=0; i<count; i++) {
const char* suite = bc_tester_suite_name(i);
for (int i = 0; i < count; i++) {
const char *suite = bc_tester_suite_name(i);
int test_count = bc_tester_nb_tests(suite);
for( int k = 0; k<test_count; k++){
const char* test =bc_tester_test_name(suite, k);
NSString* sSuite = [NSString stringWithUTF8String:suite];
NSString* sTest = [NSString stringWithUTF8String:test];
for (int k = 0; k < test_count; k++) {
const char *test = bc_tester_test_name(suite, k);
NSString *sSuite = [NSString stringWithUTF8String:suite];
NSString *sTest = [NSString stringWithUTF8String:test];
if( [[LinphoneTester_Tests skippedSuites] containsObject:sSuite] ) continue;
// prepend "test_" so that it gets found by introspection
NSString* safesTest = [self safetyTestString:sTest];
NSString* safesSuite = [self safetyTestString:sSuite];
NSString *selectorName = [NSString stringWithFormat:@"test_%@__%@", safesSuite, safesTest];
if ([[LinphoneTester_Tests skippedSuites] containsObject:sSuite])
continue;
// prepend "test_" so that it gets found by introspection
NSString *safesTest = [self safetyTestString:sTest];
NSString *safesSuite = [self safetyTestString:sSuite];
NSString *selectorName = [NSString stringWithFormat:@"test_%@__%@", safesSuite, safesTest];
[LinphoneTester_Tests addInstanceMethodWithSelectorName:selectorName block:^(LinphoneTester_Tests* myself) {
[myself testForSuite:sSuite andTest:sTest];
}];
[LinphoneTester_Tests addInstanceMethodWithSelectorName:selectorName
block:^(LinphoneTester_Tests *myself) {
[myself testForSuite:sSuite andTest:sTest];
}];
}
}
}
}
- (void)setUp
{
[super setUp];
- (void)setUp {
[super setUp];
}
- (void)tearDown
{
[super tearDown];
- (void)tearDown {
[super tearDown];
}
- (void)testForSuite:(NSString*)suite andTest:(NSString*)test
{
- (void)testForSuite:(NSString *)suite andTest:(NSString *)test {
LOGI(@"Launching test %@ from suite %@", test, suite);
XCTAssertFalse(bc_tester_run_tests([suite UTF8String], [test UTF8String]), @"Suite '%@' / Test '%@' failed", suite, test);
XCTAssertFalse(bc_tester_run_tests([suite UTF8String], [test UTF8String]), @"Suite '%@' / Test '%@' failed", suite,
test);
}
- (void)dealloc {

View file

@ -15,87 +15,80 @@ static char DTRuntimeDeallocBlocks;
#pragma mark - Blocks
- (void)addDeallocBlock:(void(^)())block
{
// don't accept NULL block
NSParameterAssert(block);
NSMutableArray *deallocBlocks = objc_getAssociatedObject(self, &DTRuntimeDeallocBlocks);
- (void)addDeallocBlock:(void (^)())block {
// don't accept NULL block
NSParameterAssert(block);
// add array of dealloc blocks if not existing yet
if (!deallocBlocks)
{
deallocBlocks = [[NSMutableArray alloc] init];
objc_setAssociatedObject(self, &DTRuntimeDeallocBlocks, deallocBlocks, OBJC_ASSOCIATION_RETAIN);
}
DTObjectBlockExecutor *executor = [DTObjectBlockExecutor blockExecutorWithDeallocBlock:block];
[deallocBlocks addObject:executor];
NSMutableArray *deallocBlocks = objc_getAssociatedObject(self, &DTRuntimeDeallocBlocks);
// add array of dealloc blocks if not existing yet
if (!deallocBlocks) {
deallocBlocks = [[NSMutableArray alloc] init];
objc_setAssociatedObject(self, &DTRuntimeDeallocBlocks, deallocBlocks, OBJC_ASSOCIATION_RETAIN);
}
DTObjectBlockExecutor *executor = [DTObjectBlockExecutor blockExecutorWithDeallocBlock:block];
[deallocBlocks addObject:executor];
}
+ (BOOL)addInstanceMethodWithSelectorName:(NSString *)selectorName block:(void(^)(id))block
{
// don't accept nil name
NSParameterAssert(selectorName);
// don't accept NULL block
NSParameterAssert(block);
// See http://stackoverflow.com/questions/6357663/casting-a-block-to-a-void-for-dynamic-class-method-resolution
+ (BOOL)addInstanceMethodWithSelectorName:(NSString *)selectorName block:(void (^)(id))block {
// don't accept nil name
NSParameterAssert(selectorName);
// don't accept NULL block
NSParameterAssert(block);
// See http://stackoverflow.com/questions/6357663/casting-a-block-to-a-void-for-dynamic-class-method-resolution
#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_7
void *impBlockForIMP = (void *)objc_unretainedPointer(block);
void *impBlockForIMP = (void *)objc_unretainedPointer(block);
#else
id impBlockForIMP = (__bridge id)objc_unretainedPointer(block);
id impBlockForIMP = (__bridge id)objc_unretainedPointer(block);
#endif
IMP myIMP = imp_implementationWithBlock(impBlockForIMP);
SEL selector = NSSelectorFromString(selectorName);
return class_addMethod(self, selector, myIMP, "v@:");
IMP myIMP = imp_implementationWithBlock(impBlockForIMP);
SEL selector = NSSelectorFromString(selectorName);
return class_addMethod(self, selector, myIMP, "v@:");
}
#pragma mark - Method Swizzling
+ (void)swizzleMethod:(SEL)selector withMethod:(SEL)otherSelector
{
+ (void)swizzleMethod:(SEL)selector withMethod:(SEL)otherSelector {
// my own class is being targetted
Class c = [self class];
// get the methods from the selectors
Method originalMethod = class_getInstanceMethod(c, selector);
Method otherMethod = class_getInstanceMethod(c, otherSelector);
if (class_addMethod(c, selector, method_getImplementation(otherMethod), method_getTypeEncoding(otherMethod)))
{
class_replaceMethod(c, otherSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}
else
{
Method otherMethod = class_getInstanceMethod(c, otherSelector);
if (class_addMethod(c, selector, method_getImplementation(otherMethod), method_getTypeEncoding(otherMethod))) {
class_replaceMethod(c, otherSelector, method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, otherMethod);
}
}
+ (void)swizzleClassMethod:(SEL)selector withMethod:(SEL)otherSelector
{
+ (void)swizzleClassMethod:(SEL)selector withMethod:(SEL)otherSelector {
// my own class is being targetted
Class c = [self class];
// get the methods from the selectors
Method originalMethod = class_getClassMethod(c, selector);
Method otherMethod = class_getClassMethod(c, otherSelector);
// if (class_addMethod(c, selector, method_getImplementation(otherMethod), method_getTypeEncoding(otherMethod)))
// {
// class_replaceMethod(c, otherSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
// }
// else
// {
method_exchangeImplementations(originalMethod, otherMethod);
// }
Method otherMethod = class_getClassMethod(c, otherSelector);
// if (class_addMethod(c, selector, method_getImplementation(otherMethod), method_getTypeEncoding(otherMethod)))
// {
// class_replaceMethod(c, otherSelector, method_getImplementation(originalMethod),
//method_getTypeEncoding(originalMethod));
// }
// else
// {
method_exchangeImplementations(originalMethod, otherMethod);
// }
}
@end

View file

@ -10,42 +10,44 @@
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
splitViewController.delegate = (id)navigationController.topViewController;
}
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
splitViewController.delegate = (id)navigationController.topViewController;
}
return YES;
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of
// temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application
// and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use
// this method to pause the game.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application
// state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate:
// when the user quits.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes
// made on entering the background.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application
// was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also
// applicationDidEnterBackground:.
}
@end

View file

@ -12,35 +12,35 @@
#include "linphone/liblinphone_tester.h"
#import "Utils.h"
static NSString* const kAllTestsName = @"Run All tests";
static NSString *const kAllTestsName = @"Run All tests";
@implementation TestItem
-(id)initWithName:(NSString *)name fromSuite:(NSString *)suite {
self = [super init];
if( self ){
self.name = name;
self.suite = suite;
self.state = TestStateIdle;
}
return self;
- (id)initWithName:(NSString *)name fromSuite:(NSString *)suite {
self = [super init];
if (self) {
self.name = name;
self.suite = suite;
self.state = TestStateIdle;
}
return self;
}
+(TestItem *)testWithName:(NSString *)name fromSuite:(NSString *)suite{
return [[TestItem alloc] initWithName:name fromSuite:suite];
+ (TestItem *)testWithName:(NSString *)name fromSuite:(NSString *)suite {
return [[TestItem alloc] initWithName:name fromSuite:suite];
}
-(NSString*)description {
return [NSString stringWithFormat:@"{suite:'%@', test:'%@', state:%d}", _suite, _name, _state];
- (NSString *)description {
return [NSString stringWithFormat:@"{suite:'%@', test:'%@', state:%d}", _suite, _name, _state];
}
@end
@interface DetailViewController () {
NSMutableArray* _tests;
BOOL in_progress;
NSMutableArray *_tests;
BOOL in_progress;
}
@property (strong, nonatomic) UIPopoverController *masterPopoverController;
@property(strong, nonatomic) UIPopoverController *masterPopoverController;
- (void)configureView;
@end
@ -48,19 +48,18 @@ static NSString* const kAllTestsName = @"Run All tests";
#pragma mark - Managing the detail item
- (void)setDetailItem:(id)newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
[self.tableView reloadData];
}
- (void)setDetailItem:(id)newDetailItem {
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
if (self.masterPopoverController != nil) {
[self.masterPopoverController dismissPopoverAnimated:YES];
}
// Update the view.
[self configureView];
[self.tableView reloadData];
}
if (self.masterPopoverController != nil) {
[self.masterPopoverController dismissPopoverAnimated:YES];
}
}
- (void)addTestsFromSuite:(NSString *)suite {
@ -74,8 +73,7 @@ static NSString* const kAllTestsName = @"Run All tests";
}
}
- (void)configureView
{
- (void)configureView {
_tests = [[NSMutableArray alloc] initWithCapacity:0];
if (self.detailItem == nil) {
return;
@ -93,35 +91,31 @@ static NSString* const kAllTestsName = @"Run All tests";
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
[self configureView];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Tableview
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _tests.count;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _tests.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"testCellIdentifier" forIndexPath:indexPath];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"testCellIdentifier" forIndexPath:indexPath];
TestItem *test = _tests[indexPath.row];
TestItem *test = _tests[indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:@"%@/%@", test.suite, test.name];
NSString *image = nil;
switch (test.state) {
@ -144,16 +138,14 @@ static NSString* const kAllTestsName = @"Run All tests";
} else {
[cell.imageView setImage:nil];
}
return cell;
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:FALSE];
if (indexPath.row == 0) {
// we should run all tests
@ -167,10 +159,9 @@ static NSString* const kAllTestsName = @"Run All tests";
}
}
-(void)updateItem:(NSArray*)paths withAnimation:(BOOL)animate {
[self.tableView reloadRowsAtIndexPaths:paths
withRowAnimation:animate?UITableViewRowAnimationFade:UITableViewRowAnimationNone];
- (void)updateItem:(NSArray *)paths withAnimation:(BOOL)animate {
[self.tableView reloadRowsAtIndexPaths:paths
withRowAnimation:animate ? UITableViewRowAnimationFade : UITableViewRowAnimationNone];
}
- (void)launchTest:(NSArray *)paths {
@ -215,21 +206,23 @@ static NSString* const kAllTestsName = @"Run All tests";
});
}
#pragma mark - Split view
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
barButtonItem.title = NSLocalizedString(@"Master", @"Master");
[self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
self.masterPopoverController = popoverController;
- (void)splitViewController:(UISplitViewController *)splitController
willHideViewController:(UIViewController *)viewController
withBarButtonItem:(UIBarButtonItem *)barButtonItem
forPopoverController:(UIPopoverController *)popoverController {
barButtonItem.title = NSLocalizedString(@"Master", @"Master");
[self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
self.masterPopoverController = popoverController;
}
- (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
// Called when the view is shown again in the split view, invalidating the button and popover controller.
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
self.masterPopoverController = nil;
- (void)splitViewController:(UISplitViewController *)splitController
willShowViewController:(UIViewController *)viewController
invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
// Called when the view is shown again in the split view, invalidating the button and popover controller.
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
self.masterPopoverController = nil;
}
@end

View file

@ -10,43 +10,40 @@
#import "MasterViewController.h"
@interface LogsViewController () {
NSString* txt;
NSString *txt;
}
@end
@implementation LogsViewController
- (void)viewDidLoad
{
[super viewDidLoad];
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated {
self.tview.textContainer.lineBreakMode = NSLineBreakByClipping;
self.tview.text = [lastLogs componentsJoinedByString:@"\n"];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateLogs:)
name:kLogsUpdateNotification
object:nil];
self.tview.textContainer.lineBreakMode = NSLineBreakByClipping;
self.tview.text = [lastLogs componentsJoinedByString:@"\n"];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateLogs:)
name:kLogsUpdateNotification
object:nil];
}
- (void)viewDidDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (IBAction)clearLogs:(id)sender {
self.tview.text = nil;
self.tview.text = nil;
}
- (void)updateLogs:(NSNotification*)notif {
NSArray* newLogs = [notif.userInfo objectForKey:@"newlogs"];
dispatch_async(dispatch_get_main_queue(), ^{
self.tview.text = [self.tview.text stringByAppendingString:[newLogs componentsJoinedByString:@"\n"] ];
});
- (void)updateLogs:(NSNotification *)notif {
NSArray *newLogs = [notif.userInfo objectForKey:@"newlogs"];
dispatch_async(dispatch_get_main_queue(), ^{
self.tview.text = [self.tview.text stringByAppendingString:[newLogs componentsJoinedByString:@"\n"]];
});
}
@end

View file

@ -15,49 +15,47 @@
#import "Utils.h"
@interface MasterViewController () {
NSMutableArray *_objects;
NSString* bundlePath;
NSString* documentPath;
NSMutableArray *_objects;
NSString *bundlePath;
NSString *documentPath;
}
@end
@implementation MasterViewController
- (void)awakeFromNib
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
self.clearsSelectionOnViewWillAppear = NO;
self.preferredContentSize = CGSizeMake(320.0, 600.0);
}
[super awakeFromNib];
- (void)awakeFromNib {
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
self.clearsSelectionOnViewWillAppear = NO;
self.preferredContentSize = CGSizeMake(320.0, 600.0);
}
[super awakeFromNib];
}
NSMutableArray* lastLogs = nil;
NSMutableArray* logsBuffer = nil;
NSMutableArray *lastLogs = nil;
NSMutableArray *logsBuffer = nil;
static int const kLastLogsCapacity = 5000;
static int const kLogsBufferCapacity = 10;
NSString* const kLogsUpdateNotification = @"kLogsUpdateNotification";
NSString *const kLogsUpdateNotification = @"kLogsUpdateNotification";
- (void)setupLogging {
lastLogs = [[NSMutableArray alloc] initWithCapacity:kLastLogsCapacity];
logsBuffer = [NSMutableArray arrayWithCapacity:kLogsBufferCapacity];
lastLogs = [[NSMutableArray alloc] initWithCapacity:kLastLogsCapacity];
logsBuffer = [NSMutableArray arrayWithCapacity:kLogsBufferCapacity];
linphone_core_set_log_level(ORTP_WARNING);
linphone_core_set_log_handler((OrtpLogFunc)linphone_iphone_log_handler);
}
- (void)viewDidLoad
{
[super viewDidLoad];
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
[self setupLogging];
bundlePath = [[NSBundle mainBundle] bundlePath];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentPath = [paths objectAtIndex:0];
self.detailViewController =
(DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
[self setupLogging];
bundlePath = [[NSBundle mainBundle] bundlePath];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentPath = [paths objectAtIndex:0];
bc_tester_init((void (*)(int, const char *fm, va_list))linphone_iphone_log_handler, ORTP_MESSAGE, ORTP_ERROR);
liblinphone_tester_add_suites();
@ -82,52 +80,50 @@ NSString* const kLogsUpdateNotification = @"kLogsUpdateNotification";
[self.navigationController performSegueWithIdentifier:@"viewLogs" sender:self];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _objects.count;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _objects.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
NSString *suite = _objects[indexPath.row];
cell.textLabel.text = suite;
return cell;
NSString *suite = _objects[indexPath.row];
cell.textLabel.text = suite;
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return NO;
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the specified item to be editable.
return NO;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[_objects removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[_objects removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:@[ indexPath ] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table
// view.
}
}
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath
*)toIndexPath
{
}
*/
@ -136,27 +132,24 @@ NSString* const kLogsUpdateNotification = @"kLogsUpdateNotification";
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
NSString *object = _objects[indexPath.row];
self.detailViewController.detailItem = object;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
NSString *object = _objects[indexPath.row];
self.detailViewController.detailItem = object;
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:@"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSString *object = _objects[indexPath.row];
[[segue destinationViewController] setDetailItem:object];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:@"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSString *object = _objects[indexPath.row];
[[segue destinationViewController] setDetailItem:object];
}
}
@end

View file

@ -12,25 +12,26 @@
#include <execinfo.h>
#include <signal.h>
static NSString * const kKEY_CRASH_REPORT = @"CRASH_REPORT";
static NSString * const kKEY_ExceptionName = @"UnhandledExceptionName";
static NSString * const kKEY_ExceptionReason = @"UnhandledExceptionReason";
static NSString * const kKEY_ExceptionUserInfo = @"UnhandledExceptionUserInfo";
static NSString * const kKEY_ExceptionCallStack = @"UnhandledExceptionCallStack";
static NSString * const kKEY_ExceptionScreenshot = @"UnhandledExceptionScreenshot";
static NSString * const kKEY_ExceptionTimestamp = @"UnhandledExceptionTimestamp";
static NSString *const kKEY_CRASH_REPORT = @"CRASH_REPORT";
static NSString *const kKEY_ExceptionName = @"UnhandledExceptionName";
static NSString *const kKEY_ExceptionReason = @"UnhandledExceptionReason";
static NSString *const kKEY_ExceptionUserInfo = @"UnhandledExceptionUserInfo";
static NSString *const kKEY_ExceptionCallStack = @"UnhandledExceptionCallStack";
static NSString *const kKEY_ExceptionScreenshot = @"UnhandledExceptionScreenshot";
static NSString *const kKEY_ExceptionTimestamp = @"UnhandledExceptionTimestamp";
static void unhandledExceptionHandler(NSException *exception) {
NSMutableDictionary *crashReport = [NSMutableDictionary dictionary];
crashReport[kKEY_ExceptionName] = exception.name;
crashReport[kKEY_ExceptionReason] = exception.reason;
crashReport[kKEY_ExceptionUserInfo] = exception.userInfo ?: [NSNull null].debugDescription;
crashReport[kKEY_ExceptionCallStack] = exception.callStackSymbols.debugDescription;
NSMutableDictionary *crashReport = [NSMutableDictionary dictionary];
crashReport[kKEY_ExceptionName] = exception.name;
crashReport[kKEY_ExceptionReason] = exception.reason;
crashReport[kKEY_ExceptionUserInfo] = exception.userInfo ?: [NSNull null].debugDescription;
crashReport[kKEY_ExceptionCallStack] = exception.callStackSymbols.debugDescription;
NSLog(@"CRASH: %@ - %@", exception.name, exception.callStackSymbols.debugDescription);
[[NSUserDefaults standardUserDefaults] setObject:[NSDictionary dictionaryWithDictionary:crashReport] forKey:kKEY_CRASH_REPORT];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSUserDefaults standardUserDefaults] setObject:[NSDictionary dictionaryWithDictionary:crashReport]
forKey:kKEY_CRASH_REPORT];
[[NSUserDefaults standardUserDefaults] synchronize];
exit(1);
}
@ -39,11 +40,10 @@ static void unhandledExceptionHandler(NSException *exception) {
* Handle uncaught signals
*/
void SignalHandler(int sig, siginfo_t *info, void *context)
{
void SignalHandler(int sig, siginfo_t *info, void *context) {
void *frames[128];
int i,len = backtrace(frames, 128);
char **symbols = backtrace_symbols(frames,len);
int i, len = backtrace(frames, 128);
char **symbols = backtrace_symbols(frames, len);
/*
* Now format into a message for sending to the user
@ -52,35 +52,31 @@ void SignalHandler(int sig, siginfo_t *info, void *context)
NSMutableString *buffer = [[NSMutableString alloc] initWithCapacity:4096];
NSBundle *bundle = [NSBundle mainBundle];
[buffer appendFormat:@"PComp version %@ build %@\n\n",
[bundle objectForInfoDictionaryKey:@"CFBundleVersion"],
[bundle objectForInfoDictionaryKey:@"CIMBuildNumber"]];
[buffer appendFormat:@"PComp version %@ build %@\n\n", [bundle objectForInfoDictionaryKey:@"CFBundleVersion"],
[bundle objectForInfoDictionaryKey:@"CIMBuildNumber"]];
[buffer appendString:@"Uncaught Signal\n"];
[buffer appendFormat:@"si_signo %d\n",info->si_signo];
[buffer appendFormat:@"si_code %d\n",info->si_code];
[buffer appendFormat:@"si_value %d\n",info->si_value.sival_int];
[buffer appendFormat:@"si_errno %d\n",info->si_errno];
[buffer appendFormat:@"si_addr %p\n",info->si_addr];
[buffer appendFormat:@"si_status %d\n",info->si_status];
[buffer appendFormat:@"si_signo %d\n", info->si_signo];
[buffer appendFormat:@"si_code %d\n", info->si_code];
[buffer appendFormat:@"si_value %d\n", info->si_value.sival_int];
[buffer appendFormat:@"si_errno %d\n", info->si_errno];
[buffer appendFormat:@"si_addr %p\n", info->si_addr];
[buffer appendFormat:@"si_status %d\n", info->si_status];
[buffer appendString:@"Stack trace:\n\n"];
for (i = 0; i < len; ++i) {
[buffer appendFormat:@"%4d - %s\n",i,symbols[i]];
[buffer appendFormat:@"%4d - %s\n", i, symbols[i]];
}
/*
* Get the error file to write this to
*/
NSLog(@"Error %@",buffer);
NSLog(@"Error %@", buffer);
exit(1);
}
void InstallUncaughtExceptionHandler()
{
NSSetUncaughtExceptionHandler(&unhandledExceptionHandler);
struct sigaction mySigAction;
void InstallUncaughtExceptionHandler() {
NSSetUncaughtExceptionHandler(&unhandledExceptionHandler);
struct sigaction mySigAction;
mySigAction.sa_sigaction = SignalHandler;
mySigAction.sa_flags = SA_SIGINFO;
@ -96,10 +92,9 @@ void InstallUncaughtExceptionHandler()
sigaction(SIGSYS, &mySigAction, NULL);
}
int main(int argc, char * argv[])
{
int main(int argc, char *argv[]) {
InstallUncaughtExceptionHandler();
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

32
main.m
View file

@ -4,18 +4,18 @@
*
* 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 2 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, write to the Free Software
* the Free Software Foundation; either version 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import <UIKit/UIKit.h>
#import "LinphoneAppDelegate.h"
@ -24,18 +24,18 @@
// Dump exception
void uncaughtExceptionHandler(NSException *exception) {
NSLog(@"Crash: %@", exception);
NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
// Internal error reporting
NSLog(@"Crash: %@", exception);
NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
// Internal error reporting
}
#endif
int main(int argc, char *argv[]) {
#ifdef DEBUG
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
#endif
@autoreleasepool {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([LinphoneAppDelegate class]));
}
}

View file

@ -9,8 +9,8 @@
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
int main(int argc, char *argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}