diff --git a/.clang-format b/.clang-format
new file mode 100644
index 000000000..769b266b1
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,64 @@
+---
+# BasedOnStyle: LLVM
+AccessModifierOffset: -2
+AlignAfterOpenBracket: true
+AlignEscapedNewlinesLeft: false
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: false
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: false
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: false
+BinPackArguments: true
+BinPackParameters: true
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Attach
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+ColumnLimit: 120
+CommentPragmas: '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IndentCaseLabels: false
+IndentFunctionDeclarationAfterType: false
+IndentWidth: 4
+IndentWrappedFunctionNames: false
+KeepEmptyLinesAtTheStartOfBlocks: true
+Language: Cpp
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerAlignment: Right
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp11
+TabWidth: 4
+UseTab: Always
+...
diff --git a/.git-pre-commit b/.git-pre-commit
new file mode 100755
index 000000000..69a71bea9
--- /dev/null
+++ b/.git-pre-commit
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+# This hook purpose is to keep coding style consistent between all developers
+# It is automatically installed in .git/hooks folder by cmake on first run.
+
+# From https://github.com/tatsuhiro-t/nghttp2/blob/master/pre-commit
+
+function invalid-format-detected {
+ cat git-clang-format.diff
+ echo "*****************"
+ echo "$0: Invalid coding style detected (see git-clang-format.diff for issues). Please correct it using one of the following:"
+ echo "1) Apply patch located at git-clang-format.diff using:"
+ echo " cd $(git rev-parse --show-toplevel) && $1"
+ echo "2) Use clang-format to correctly format source code using:"
+ echo " $2"
+ echo "3) Reformat these lines manually."
+ echo "*** Aborting commit.***"
+ exit 1
+}
+function git-clang-format-diffing {
+ format_diff=$(which git-clang-format)
+ format_diff_options="--style=file"
+
+ #only diffing commited files, ignored staged one
+ $format_diff $format_diff_options --diff $(git --no-pager diff --cached --name-status | grep -v '^D' | cut -f2) > git-clang-format.diff
+
+ if ! grep -q -E '(no modified files to format|clang-format did not modify any files)' git-clang-format.diff; then
+ invalid-format-detected "git apply git-clang-format.diff" "clang-format $format_diff_options -i "
+ fi
+}
+
+function clang-format-diff-diffing {
+ format_diff=$(find /usr/bin/ -name 'clang-format-diff*' -type f | tail -n1)
+ format_diff_options="-style file"
+
+ git diff-index --cached --diff-filter=ACMR -p HEAD -- | $format_diff $format_diff_options -p1 > git-clang-format.diff
+ if [ -s git-clang-format.diff ]; then
+ invalid-format-detected "patch -p0 < git-clang-format.diff" "${format_diff/-diff/} $format_diff_options -i "
+ fi
+}
+
+set -e
+if which git-clang-format &>/dev/null; then
+ git-clang-format-diffing $@
+elif [ ! -z "$(find /usr/bin/ /usr/local/bin/ /opt/bin/ -name 'clang-format-diff*' -type f 2>/dev/null)" ]; then
+ # Warning! We need at least version 1.6...
+ clang-format-diff-diffing $@
+else
+ echo "$0: Please install clang-format (coding style checker) - could not find git-clang-format nor clang-format-diff in PATH. Skipping code verification..."
+ exit 0
+fi
diff --git a/.gitignore b/.gitignore
index 57e16863b..fc80e3d8f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,5 @@ build
test-reports
WORK
Makefile
+OUTPUT
+git-clang-format.diff
diff --git a/.gitmodules b/.gitmodules
index 8cfc3ac8c..e75d7c5ab 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -32,7 +32,7 @@
url = git://git.linphone.org/msx264.git
[submodule "submodules/externals/libvpx"]
path = submodules/externals/libvpx
- url = http://git.chromium.org/webm/libvpx.git
+ url = https://github.com/webmproject/libvpx
ignore = dirty
[submodule "submodules/bzrtp"]
path = submodules/bzrtp
diff --git a/.travis.yml b/.travis.yml
index a038e41b8..e5a5386ed 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,13 +6,11 @@ xcode_sdk: iphonesimulator8.1
branches:
only:
- master
- - travis_cmake
env:
global:
- VERSION="8.1"
- BYPASS_TOOLCHECK=1
- - KIF_SCREENSHOTS=Screens
- secure: "JPPcWdmNIJiR3YcIwe0LRYce6qDdsiagO+eKKAp7eVk/wD9UHbz96Ms2FFkXxPhRJB1PA6Pf8FpAzIL2YRiJL9jRtKHSvtdF1cSto+57XyBkCsw7PkMVUIxp7fg6Wiwn3H3tucF8jisIkv/Pn7R+9EqePkZSqqu3+ig5AX9ApQ4="
before_install:
@@ -29,11 +27,11 @@ before_install:
- sudo ln -s /usr/bin/strings /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/strings
- git submodule update --init --recursive
-install:
+install:
- ./prepare.py all
- - make
+ - make -s 1>/dev/null
- mkdir -p Screens
- export KIF_SCREENSHOTS=`pwd`/Screens
after_script:
- - ./Tools/imgur_upload.sh
+ - ./Tools/imgur_upload.sh
diff --git a/Classes/Base.lproj/ChatRoomViewController.xib b/Classes/Base.lproj/ChatRoomViewController.xib
index 92c0c0cac..58c8256f6 100644
--- a/Classes/Base.lproj/ChatRoomViewController.xib
+++ b/Classes/Base.lproj/ChatRoomViewController.xib
@@ -1,31 +1,26 @@
-
+
-
+
-
-
-
-
-
@@ -90,46 +85,11 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -235,17 +195,6 @@
-
-
-
-
-
-
-
-
-
-
-
@@ -264,16 +213,12 @@
-
-
-
-
diff --git a/Classes/ChatRoomTableViewController.h b/Classes/ChatRoomTableViewController.h
index 192ac77d6..f8e317dca 100644
--- a/Classes/ChatRoomTableViewController.h
+++ b/Classes/ChatRoomTableViewController.h
@@ -23,7 +23,6 @@
@protocol ChatRoomDelegate
-- (BOOL)chatRoomStartImageDownload:(NSURL*)url userInfo:(id)userInfo;
- (BOOL)chatRoomStartImageUpload:(UIImage*)image url:(NSURL*)url;
- (void)resendChat:(NSString*)message withExternalUrl:(NSString*)url;
diff --git a/Classes/ChatRoomTableViewController.m b/Classes/ChatRoomTableViewController.m
index 88b4d24f9..425b06662 100644
--- a/Classes/ChatRoomTableViewController.m
+++ b/Classes/ChatRoomTableViewController.m
@@ -63,6 +63,16 @@
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]) {
+ if (linphone_chat_room_get_peer_address(linphone_chat_message_get_chat_room(ftd.message)) ==
+ linphone_chat_room_get_peer_address(chatRoom) &&
+ linphone_chat_message_is_outgoing(ftd.message)) {
+ LOGI(@"Appending transient upload message %p", ftd.message);
+ self->messageList = ms_list_append(self->messageList, ftd.message);
+ }
+ }
}
- (void)reloadData {
@@ -76,9 +86,10 @@
messageList = ms_list_append(messageList, linphone_chat_message_ref(chat));
int pos = ms_list_size(messageList) - 1;
- [self.tableView beginUpdates];
- [self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:pos inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
- [self.tableView endUpdates];
+ NSIndexPath *indexPath = [NSIndexPath indexPathForRow:pos inSection:0];
+ [self.tableView beginUpdates];
+ [self.tableView insertRowsAtIndexPaths:@[ indexPath ] withRowAnimation:UITableViewRowAnimationFade];
+ [self.tableView endUpdates];
}
- (void)updateChatEntry:(LinphoneChatMessage*)chat {
@@ -183,7 +194,6 @@
[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);
diff --git a/Classes/ChatRoomViewController.h b/Classes/ChatRoomViewController.h
index f543f1868..763018847 100644
--- a/Classes/ChatRoomViewController.h
+++ b/Classes/ChatRoomViewController.h
@@ -24,14 +24,12 @@
#import "ChatRoomTableViewController.h"
#import "HPGrowingTextView.h"
#import "ImagePickerViewController.h"
-#import "ImageSharing.h"
#import "OrderedDictionary.h"
#include "linphone/linphonecore.h"
-@interface ChatRoomViewController : UIViewController {
+@interface ChatRoomViewController : UIViewController {
LinphoneChatRoom *chatRoom;
- ImageSharing *imageSharing;
OrderedDictionary *imageQualities;
BOOL scrollOnGrowingEnabled;
BOOL composingVisible;
@@ -54,17 +52,12 @@
@property (strong, nonatomic) IBOutlet UIView *composeIndicatorView;
@property (nonatomic, strong) IBOutlet UIButton* pictureButton;
-@property (nonatomic, strong) IBOutlet UIButton* cancelTransferButton;
-@property (nonatomic, strong) IBOutlet UIProgressView* imageTransferProgressBar;
-@property (nonatomic, strong) IBOutlet UIView* transferView;
-@property (nonatomic, strong) IBOutlet UIView* waitView;
- (IBAction)onBackClick:(id)event;
- (IBAction)onEditClick:(id)event;
- (IBAction)onMessageChange:(id)sender;
- (IBAction)onSendClick:(id)event;
- (IBAction)onPictureClick:(id)event;
-- (IBAction)onTransferCancelClick:(id)event;
- (IBAction)onListTap:(id)sender;
- (void)setChatRoom:(LinphoneChatRoom*)room;
diff --git a/Classes/ChatRoomViewController.m b/Classes/ChatRoomViewController.m
index 53caf7475..fbcbc6ac9 100644
--- a/Classes/ChatRoomViewController.m
+++ b/Classes/ChatRoomViewController.m
@@ -21,10 +21,12 @@
#import "PhoneMainView.h"
#import "DTActionSheet.h"
#import "UILinphone.h"
-
+#import "DTAlertView.h"
+#import "Utils/FileTransferDelegate.h"
#import
#import
#import "Utils.h"
+#import "UIChatRoomCell.h"
@implementation ChatRoomViewController
@@ -44,28 +46,23 @@
@synthesize listTapGestureRecognizer;
@synthesize listSwipeGestureRecognizer;
@synthesize pictureButton;
-@synthesize imageTransferProgressBar;
-@synthesize cancelTransferButton;
-@synthesize transferView;
-@synthesize waitView;
#pragma mark - Lifecycle Functions
- (id)init {
- self = [super initWithNibName:@"ChatRoomViewController" bundle:[NSBundle mainBundle]];
- if (self != nil) {
- self->scrollOnGrowingEnabled = TRUE;
- self->chatRoom = NULL;
- self->imageSharing = NULL;
- self->listTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onListTap:)];
- self.listSwipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(onListSwipe:)];
- self->imageQualities = [[OrderedDictionary alloc] initWithObjectsAndKeys:
- [NSNumber numberWithFloat:0.9], NSLocalizedString(@"Maximum", nil),
- [NSNumber numberWithFloat:0.5], NSLocalizedString(@"Average", nil),
- [NSNumber numberWithFloat:0.0], NSLocalizedString(@"Minimum", nil), nil];
- self->composingVisible = TRUE;
- }
- return self;
+ self = [super initWithNibName:@"ChatRoomViewController" bundle:[NSBundle mainBundle]];
+ if (self != nil) {
+ self->scrollOnGrowingEnabled = TRUE;
+ self->chatRoom = NULL;
+ self->listTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onListTap:)];
+ self.listSwipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(onListSwipe:)];
+ self->imageQualities = [[OrderedDictionary alloc] initWithObjectsAndKeys:
+ [NSNumber numberWithFloat:0.9], NSLocalizedString(@"Maximum", nil),
+ [NSNumber numberWithFloat:0.5], NSLocalizedString(@"Average", nil),
+ [NSNumber numberWithFloat:0.0], NSLocalizedString(@"Minimum", nil), nil];
+ self->composingVisible = TRUE;
+ }
+ return self;
}
- (void)dealloc {
@@ -156,6 +153,7 @@ static UICompositeViewDescription *compositeDescription = nil;
selector:@selector(textComposeEvent:)
name:kLinphoneTextComposeEvent
object:nil];
+
if([tableController isEditing])
[tableController setEditing:FALSE animated:FALSE];
[editButton setOff];
@@ -167,39 +165,16 @@ static UICompositeViewDescription *compositeDescription = nil;
BOOL fileSharingEnabled = [[LinphoneManager instance] lpConfigStringForKey:@"sharing_server_preference"] != NULL
&& [[[LinphoneManager instance] lpConfigStringForKey:@"sharing_server_preference"] length]>0;
[pictureButton setEnabled:fileSharingEnabled];
- [waitView setHidden:TRUE];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
- if(imageSharing) {
- [imageSharing cancel];
- }
-
[messageField resignFirstResponder];
[self setComposingVisible:FALSE withDelay:0]; // will hide the "user is composing.." message
- [[NSNotificationCenter defaultCenter] removeObserver:self
- name:UIApplicationDidBecomeActiveNotification
- object:nil];
-
- [[NSNotificationCenter defaultCenter] removeObserver:self
- name:UIKeyboardWillShowNotification
- object:nil];
- [[NSNotificationCenter defaultCenter] removeObserver:self
- name:UIKeyboardWillHideNotification
- object:nil];
- [[NSNotificationCenter defaultCenter] removeObserver:self
- name:kLinphoneTextReceived
- object:nil];
- [[NSNotificationCenter defaultCenter] removeObserver:self
- name:UITextViewTextDidChangeNotification
- object:nil];
- [[NSNotificationCenter defaultCenter] removeObserver:self
- name:kLinphoneTextComposeEvent
- object:nil];
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
@@ -211,7 +186,6 @@ static UICompositeViewDescription *compositeDescription = nil;
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
-
}
-(void)didReceiveMemoryWarning {
@@ -287,9 +261,9 @@ static UICompositeViewDescription *compositeDescription = nil;
}
static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState state,void* ud) {
- ChatRoomViewController* thiz = (__bridge ChatRoomViewController*)ud;
- const char*text = linphone_chat_message_get_text(msg);
+ const char *text = (linphone_chat_message_get_file_transfer_information(msg) != NULL) ? "photo transfer" : linphone_chat_message_get_text(msg);
LOGI(@"Delivery status for [%s] is [%s]",text,linphone_chat_message_state_to_string(state));
+ ChatRoomViewController* thiz = (__bridge ChatRoomViewController*)ud;
[thiz.tableController updateChatEntry:msg];
}
@@ -317,39 +291,34 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
}
- (void)saveAndSend:(UIImage*)image url:(NSURL*)url {
- if(url == nil) {
- [waitView setHidden:FALSE];
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- [[LinphoneManager instance].photoLibrary
- writeImageToSavedPhotosAlbum:image.CGImage
- orientation:(ALAssetOrientation)[image imageOrientation]
- completionBlock:^(NSURL *assetURL, NSError *error){
- dispatch_async(dispatch_get_main_queue(), ^{
- [waitView setHidden:TRUE];
- if (error) {
- LOGE(@"Cannot save image data downloaded [%@]", [error localizedDescription]);
+ // photo from Camera, must be saved first
+ if (url == nil) {
+ [[LinphoneManager instance]
+ .photoLibrary
+ writeImageToSavedPhotosAlbum:image.CGImage
+ orientation:(ALAssetOrientation)[image imageOrientation]
+ completionBlock:^(NSURL *assetURL, NSError *error) {
+ if (error) {
+ LOGE(@"Cannot save image data downloaded [%@]", [error localizedDescription]);
- UIAlertView* errorAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Transfer error", nil)
- message:NSLocalizedString(@"Cannot write image to photo library", nil)
- delegate:nil
- cancelButtonTitle:NSLocalizedString(@"Ok",nil)
- otherButtonTitles:nil ,nil];
- [errorAlert show];
- return;
- }
- LOGI(@"Image saved to [%@]", [assetURL absoluteString]);
- [self chatRoomStartImageUpload:image url:assetURL];
- });
- }];
- });
- } else {
- [self chatRoomStartImageUpload:image url:url];
- }
+ UIAlertView *errorAlert = [[UIAlertView alloc]
+ initWithTitle:NSLocalizedString(@"Transfer error", nil)
+ message:NSLocalizedString(@"Cannot write image to photo library", nil)
+ delegate:nil
+ cancelButtonTitle:NSLocalizedString(@"Ok", nil)
+ otherButtonTitles:nil, nil];
+ [errorAlert show];
+ } else {
+ LOGI(@"Image saved to [%@]", [assetURL absoluteString]);
+ [self chatRoomStartImageUpload:image url:assetURL];
+ }
+ }];
+ } else {
+ [self chatRoomStartImageUpload:image url:url];
+ }
}
- (void)chooseImageQuality:(UIImage*)image url:(NSURL*)url {
- [waitView setHidden:FALSE];
-
DTActionSheet *sheet = [[DTActionSheet alloc] initWithTitle:NSLocalizedString(@"Choose the image size", nil)];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//UIImage *image = [original_image normalizedImage];
@@ -365,7 +334,6 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
}
[sheet addCancelButtonWithTitle:NSLocalizedString(@"Cancel", nil) block:nil];
dispatch_async(dispatch_get_main_queue(), ^{
- [waitView setHidden:TRUE];
[sheet showInView:[PhoneMainView instance].view];
});
});
@@ -498,8 +466,8 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
#pragma mark - Action Functions
- (IBAction)onBackClick:(id)event {
- [self.tableController setChatRoom:NULL];
- [[PhoneMainView instance] popCurrentView];
+ [self.tableController setChatRoom:NULL];
+ [[PhoneMainView instance] popCurrentView];
}
- (IBAction)onEditClick:(id)event {
@@ -577,111 +545,21 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
[sheet showInView:[PhoneMainView instance].view];
}
-- (IBAction)onTransferCancelClick:(id)event {
- if(imageSharing) {
- [imageSharing cancel];
- }
-}
-
-
#pragma mark ChatRoomDelegate
-- (BOOL)chatRoomStartImageDownload:(NSURL*)url userInfo:(id)userInfo {
- if(imageSharing == nil) {
- imageSharing = [ImageSharing newImageSharingDownload:url delegate:self userInfo:userInfo];
- [messageView setHidden:TRUE];
- [transferView setHidden:FALSE];
- return TRUE;
- }
- return FALSE;
-}
-
- (BOOL)chatRoomStartImageUpload:(UIImage*)image url:(NSURL*)url{
- if(imageSharing == nil) {
- NSString *urlString = [[LinphoneManager instance] lpConfigStringForKey:@"sharing_server_preference"];
- imageSharing = [ImageSharing newImageSharingUpload:[NSURL URLWithString:urlString] image:image delegate:self userInfo:url];
- [messageView setHidden:TRUE];
- [transferView setHidden:FALSE];
- return TRUE;
- }
- return FALSE;
+ FileTransferDelegate * fileTransfer = [[FileTransferDelegate alloc] init];
+ [[[LinphoneManager instance] fileTransferDelegates] addObject:fileTransfer];
+ [fileTransfer upload:image withURL:url forChatRoom:chatRoom];
+ [tableController addChatEntry:linphone_chat_message_ref(fileTransfer.message)];
+ [tableController scrollToBottom:true];
+ return TRUE;
}
- (void)resendChat:(NSString *)message withExternalUrl:(NSString *)url {
[self sendMessage:message withExterlBodyUrl:[NSURL URLWithString:url] withInternalURL:nil];
}
-#pragma mark ImageSharingDelegate
-
-- (void)imageSharingProgress:(ImageSharing*)aimageSharing progress:(float)progress {
- [imageTransferProgressBar setProgress:progress];
-}
-
-- (void)imageSharingAborted:(ImageSharing*)aimageSharing {
- [messageView setHidden:FALSE];
- [transferView setHidden:TRUE];
- imageSharing = nil;
-}
-
-- (void)imageSharingError:(ImageSharing*)aimageSharing error:(NSError *)error {
- [messageView setHidden:FALSE];
- [transferView setHidden:TRUE];
- NSString *url = [aimageSharing.connection.currentRequest.URL absoluteString];
- if (aimageSharing.upload) {
- LOGE(@"Cannot upload file to server [%@] because [%@]", url, [error localizedDescription]);
- UIAlertView* errorAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Transfer error", nil)
- message:NSLocalizedString(@"Cannot transfer file to remote contact", nil)
- delegate:nil
- cancelButtonTitle:NSLocalizedString(@"Ok",nil)
- otherButtonTitles:nil ,nil];
- [errorAlert show];
- } else {
- LOGE(@"Cannot download file from [%@] because [%@]", url, [error localizedDescription]);
- UIAlertView* errorAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Transfer error", nil)
- message:NSLocalizedString(@"Cannot transfer file from remote contact", nil)
- delegate:nil
- cancelButtonTitle:NSLocalizedString(@"Continue", nil)
- otherButtonTitles:nil, nil];
- [errorAlert show];
- }
- imageSharing = nil;
-}
-
-- (void)imageSharingUploadDone:(ImageSharing*)aimageSharing url:(NSURL*)url{
- [self sendMessage:nil withExterlBodyUrl:url withInternalURL:[aimageSharing userInfo] ];
-
- [messageView setHidden:FALSE];
- [transferView setHidden:TRUE];
- imageSharing = nil;
-}
-
-- (void)imageSharingDownloadDone:(ImageSharing*)aimageSharing image:(UIImage *)image {
- [messageView setHidden:FALSE];
- [transferView setHidden:TRUE];
-
- __block LinphoneChatMessage *chat = (LinphoneChatMessage *)[(NSValue*)[imageSharing userInfo] pointerValue];
- [[LinphoneManager instance].photoLibrary writeImageToSavedPhotosAlbum:image.CGImage
- orientation:(ALAssetOrientation)[image imageOrientation]
- completionBlock:^(NSURL *assetURL, NSError *error){
- if (error) {
- LOGE(@"Cannot save image data downloaded [%@]", [error localizedDescription]);
-
- UIAlertView* errorAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Transfer error", nil)
- message:NSLocalizedString(@"Cannot write image to photo library", nil)
- delegate:nil
- cancelButtonTitle:NSLocalizedString(@"Ok",nil)
- otherButtonTitles:nil ,nil];
- [errorAlert show];
- return;
- }
- LOGI(@"Image saved to [%@]", [assetURL absoluteString]);
- [LinphoneManager setValueInMessageAppData:[assetURL absoluteString] forKey:@"localimage" inMessage:chat];
- [tableController updateChatEntry:chat];
- }];
- imageSharing = nil;
-}
-
-
#pragma mark ImagePickerDelegate
- (void)imagePickerDelegateImage:(UIImage*)image info:(NSDictionary *)info {
@@ -698,7 +576,6 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
[self chooseImageQuality:image url:url];
}
-
#pragma mark - Keyboard Event Functions
- (void)keyboardWillHide:(NSNotification *)notif {
diff --git a/Classes/ChatTableViewController.m b/Classes/ChatTableViewController.m
index 23097283e..e6ce9be78 100644
--- a/Classes/ChatTableViewController.m
+++ b/Classes/ChatTableViewController.m
@@ -20,6 +20,8 @@
#import "ChatTableViewController.h"
#import "UIChatCell.h"
+#import "FileTransferDelegate.h"
+
#import "linphone/linphonecore.h"
#import "PhoneMainView.h"
#import "UACellBackgroundView.h"
@@ -64,43 +66,44 @@ static int sorted_history_comparison(LinphoneChatRoom *to_insert, LinphoneChatRo
LinphoneChatMessage* last_elem_message = linphone_chat_room_get_user_data(elem);
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 ) return 1;
- else if ( new > old) return -1;
- }
- return 0;
+ 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)
+ return 1;
+ else if (new > old)
+ return -1;
+ }
+ return 0;
}
- (MSList*)sortChatRooms {
- MSList* sorted = nil;
- MSList* unsorted = linphone_core_get_chat_rooms([LinphoneManager getLc]);
- MSList* iter = unsorted;
+ MSList *sorted = nil;
+ MSList *unsorted = linphone_core_get_chat_rooms([LinphoneManager getLc]);
+ MSList *iter = unsorted;
- while (iter) {
- // store last message in user data
- MSList* history = linphone_chat_room_get_history(iter->data, 1);
- LinphoneChatMessage* last_msg = history? history->data : NULL;
- if( last_msg ){
- linphone_chat_room_set_user_data(iter->data, linphone_chat_message_ref(last_msg));
- }
- ms_list_free_with_data(history, (void (*)(void *))linphone_chat_message_unref);
+ while (iter) {
+ // store last message in user data
+ LinphoneChatRoom *chat_room = iter->data;
+ MSList *history = linphone_chat_room_get_history(iter->data, 1);
+ assert(ms_list_size(history) <= 1);
+ LinphoneChatMessage *last_msg = history ? history->data : NULL;
+ if (last_msg) {
+ linphone_chat_message_ref(last_msg);
+ linphone_chat_room_set_user_data(chat_room, last_msg);
+ }
+ sorted = ms_list_insert_sorted(sorted, chat_room, (MSCompareFunc)sorted_history_comparison);
- sorted = ms_list_insert_sorted(sorted,
- iter->data,
- (MSCompareFunc)sorted_history_comparison);
-
- iter = iter->next;
- }
- return sorted;
+ iter = iter->next;
+ }
+ return sorted;
}
static void chatTable_free_chatrooms(void *data){
- LinphoneChatMessage* lastMsg = linphone_chat_room_get_user_data(data);
- if( lastMsg ){
- linphone_chat_message_unref(lastMsg);
- linphone_chat_room_set_user_data(data, NULL);
- }
+ LinphoneChatMessage *lastMsg = linphone_chat_room_get_user_data(data);
+ if (lastMsg) {
+ linphone_chat_message_unref(lastMsg);
+ linphone_chat_room_set_user_data(data, NULL);
+ }
}
- (void)loadData {
@@ -170,8 +173,14 @@ static void chatTable_free_chatrooms(void *data){
linphone_chat_message_unref(last_msg);
linphone_chat_room_set_user_data(chatRoom, NULL);
}
- linphone_chat_room_delete_history(chatRoom);
- linphone_chat_room_unref(chatRoom);
+
+ for (FileTransferDelegate *ftd in [[LinphoneManager instance] fileTransferDelegates]) {
+ if (linphone_chat_message_get_chat_room(ftd.message) == chatRoom) {
+ [ftd cancel];
+ }
+ }
+ linphone_chat_room_delete_history(chatRoom);
+ linphone_chat_room_unref(chatRoom);
data = ms_list_remove(data, chatRoom);
// will force a call to [self loadData]
diff --git a/Classes/HistoryDetailsViewController.m b/Classes/HistoryDetailsViewController.m
index fd0d0c187..0872ae64f 100644
--- a/Classes/HistoryDetailsViewController.m
+++ b/Classes/HistoryDetailsViewController.m
@@ -369,7 +369,6 @@ static UICompositeViewDescription *compositeDescription = nil;
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);
diff --git a/Classes/ImageSharing.h b/Classes/ImageSharing.h
deleted file mode 100644
index e222e747d..000000000
--- a/Classes/ImageSharing.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* ImageSharing.h
- *
- * Copyright (C) 2012 Belledonne Comunications, Grenoble, France
- *
- * 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
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#import
-
-@class ImageSharing;
-
-@protocol ImageSharingDelegate
-
-- (void)imageSharingProgress:(ImageSharing*)imageSharing progress:(float)progress;
-- (void)imageSharingAborted:(ImageSharing*)imageSharing;
-- (void)imageSharingError:(ImageSharing*)imageSharing error:(NSError *)error;
-- (void)imageSharingUploadDone:(ImageSharing*)imageSharing url:(NSURL*)url;
-- (void)imageSharingDownloadDone:(ImageSharing*)imageSharing image:(UIImage *)image;
-
-@end
-
-@interface ImageSharing : NSObject {
-@private
- NSInteger totalBytesExpectedToRead;
- id delegate;
- NSInteger statusCode;
-}
-
-+ (id)newImageSharingUpload:(NSURL*)url image:(UIImage*)image delegate:(id)delegate userInfo:(id)userInfo;
-+ (id)newImageSharingDownload:(NSURL*)url delegate:(id)delegate userInfo:(id)userInfo;
-
-- (void)cancel;
-
-@property (nonatomic, strong) id userInfo;
-
-@property (nonatomic, readonly) BOOL upload;
-@property (nonatomic, readonly) NSMutableData* data;
-@property (nonatomic, readonly) NSURLConnection* connection;
-
-@end
diff --git a/Classes/ImageSharing.m b/Classes/ImageSharing.m
deleted file mode 100644
index 6fb88bfd0..000000000
--- a/Classes/ImageSharing.m
+++ /dev/null
@@ -1,177 +0,0 @@
-/* ImageSharing.m
- *
- * Copyright (C) 2012 Belledonne Comunications, Grenoble, France
- *
- * 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
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#import "ImageSharing.h"
-#import "Utils.h"
-#import "LinphoneManager.h"
-
-@implementation ImageSharing
-
-@synthesize connection;
-@synthesize data;
-@synthesize upload;
-@synthesize userInfo;
-
-#pragma mark - Lifecycle Functions
-
-+ (id)newImageSharingUpload:(NSURL*)url image:(UIImage*)image delegate:(id)delegate userInfo:(id)auserInfo{
- ImageSharing *imgs = [[ImageSharing alloc] init];
- if(imgs != nil) {
- imgs.userInfo = auserInfo;
- imgs->upload = TRUE;
- imgs->delegate = delegate;
- imgs->data = [[NSMutableData alloc] init];
- if(delegate) {
- [delegate imageSharingProgress:imgs progress:0];
- }
- [imgs uploadImageTo:url image:image];
- }
- return imgs;
-}
-
-+ (id)newImageSharingDownload:(NSURL*)url delegate:(id)delegate userInfo:(id)auserInfo{
- ImageSharing *imgs = [[ImageSharing alloc] init];
- if(imgs != nil) {
- imgs.userInfo = auserInfo;
- imgs->upload = FALSE;
- imgs->delegate = delegate;
- imgs->data = [[NSMutableData alloc] init];
- if(delegate) {
- [delegate imageSharingProgress:imgs progress:0];
- }
- [imgs downloadImageFrom:url];
- }
- return imgs;
-}
-
-
-
-#pragma mark -
-
-- (void)cancel {
- [connection cancel];
- LOGI(@"File transfer interrupted by user");
- if(delegate) {
- [delegate imageSharingAborted:self];
- }
-}
-
-
-- (void)downloadImageFrom:(NSURL*)url {
- LOGI(@"downloading [%@]", [url absoluteString]);
-
- NSURLRequest* request = [NSURLRequest requestWithURL:url
- cachePolicy:NSURLRequestUseProtocolCachePolicy
- timeoutInterval:60.0];
-
- connection = [[NSURLConnection alloc] initWithRequest:request delegate: self];
-}
-
-
-- (void)uploadImageTo:(NSURL*)url image:(UIImage*)image {
- LOGI(@"downloading [%@]", [url absoluteString]);
-
- // setting up the request object now
- NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
- [request setURL:url];
- [request setHTTPMethod:@"POST"];
-
- /*
- add some header info now
- we always need a boundary when we post a file
- also we need to set the content type
-
- You might want to generate a random boundary.. this is just the same
- as my output from wireshark on a valid html post
- */
- NSString *boundary = @"---------------------------14737809831466499882746641449";
- NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
- [request addValue:contentType forHTTPHeaderField: @"Content-Type"];
-
- /*
- now lets create the body of the post
- */
- NSMutableData *body = [NSMutableData data];
- NSString *imageName = [NSString stringWithFormat:@"%lu-%f.jpg", (unsigned long)[image hash],[NSDate timeIntervalSinceReferenceDate]];
- [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
- [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\"; filename=\"%@\"\r\n",imageName] dataUsingEncoding:NSUTF8StringEncoding]];
- [body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
- [body appendData:[NSData dataWithData:UIImageJPEGRepresentation(image, 1.0)]];
- [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
- [request setHTTPBody:body];
-
- connection = [[NSURLConnection alloc] initWithRequest:(NSURLRequest *)request delegate:self];
-}
-
-
-#pragma mark - NSURLConnectionDelegate
-
-- (void)connection:(NSURLConnection *)aconnection didFailWithError:(NSError *)error {
- if(delegate) {
- [delegate imageSharingError:self error:error];
- }
-}
-
-- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite {
- if(upload && delegate) {
- [delegate imageSharingProgress:self progress:(float)totalBytesWritten/(float)totalBytesExpectedToWrite];
- }
-}
-
-- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)adata {
- [data appendData:adata];
- if(!upload && delegate) {
- [delegate imageSharingProgress:self progress:(float)data.length/(float)totalBytesExpectedToRead];
- }
-}
-
-- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
- NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *) response;
- statusCode = httpResponse.statusCode;
- LOGI(@"File transfer status code [%i]", statusCode);
-
- if (statusCode == 200 && !upload) {
- totalBytesExpectedToRead = (int)[response expectedContentLength];
- }
-}
-
-- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
- if(statusCode >= 400) {
- NSError *error = [NSError errorWithDomain:@"ImageSharing" code:statusCode userInfo:nil];
- if(delegate) {
- [delegate imageSharingError:self error:error];
- }
- return;
- }
- if (upload) {
- NSString* imageRemoteUrl = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
- LOGI(@"File can be downloaded from [%@]", imageRemoteUrl);
- if(delegate) {
- [delegate imageSharingUploadDone:self url:[NSURL URLWithString:imageRemoteUrl]];
- }
- } else {
- UIImage* image = [UIImage imageWithData:data];
- LOGI(@"File downloaded");
- if(delegate) {
- [delegate imageSharingDownloadDone:self image:image];
- }
- }
-}
-
-@end
diff --git a/Classes/InAppProductsCell.h b/Classes/InAppProductsCell.h
deleted file mode 100644
index 4efa640ee..000000000
--- a/Classes/InAppProductsCell.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//
-// InAppProductsCell.h
-// linphone
-//
-// Created by Gautier Pelloux-Prayer on 15/04/15.
-//
-//
-
-#import
-#import
-
-@interface InAppProductsCell : UITableViewCell {
-}
-@property (strong, nonatomic) IBOutlet UILabel *ptitle;
-@property (strong, nonatomic) IBOutlet UILabel *pdescription;
-@property (strong, nonatomic) IBOutlet UILabel *pprice;
-@property (strong, nonatomic) IBOutlet UISwitch *ppurchased;
-@property (nonatomic) BOOL isMaximized;
-@property (strong, nonatomic) NSString *productID;
-
-- (id)initWithIdentifier:(NSString*)identifier maximized:(bool)maximized;
-
-+ (CGFloat)getHeight:(BOOL)maximized;
-
-- (void)fillFromProduct:(SKProduct*)prod;
-
-@end
diff --git a/Classes/InAppProductsCell.m b/Classes/InAppProductsCell.m
deleted file mode 100644
index e0e8ea763..000000000
--- a/Classes/InAppProductsCell.m
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// InAppProductsCell.m
-// linphone
-//
-// Created by Gautier Pelloux-Prayer on 15/04/15.
-//
-//
-
-#import "InAppProductsCell.h"
-#import "LinphoneManager.h"
-
-@implementation InAppProductsCell
-
-- (void)setIsMaximized:(BOOL)isMaximized {
- _isMaximized = isMaximized;
-
- //show the BUY button only when not maximized
-// _buyButton.hidden = !isMaximized;
-
- self.frame = CGRectMake(self.frame.origin.x,
- self.frame.origin.y,
- self.frame.size.width,
- [InAppProductsCell getHeight:isMaximized]);
-}
-
-- (void)fillFromProduct:(SKProduct *)prod {
- NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
- [formatter setLocale:prod.priceLocale];
- [formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
- NSString * formattedPrice = [formatter stringFromNumber:prod.price];
-
- [_ptitle setText: [prod localizedTitle]];
- [_pdescription setText: [prod localizedDescription]];
- [_pprice setText: formattedPrice];
- [_ppurchased setOn: [[[LinphoneManager instance] iapManager] isPurchasedWithID:prod.productIdentifier]];
- _productID = prod.productIdentifier;
-}
-- (id)initWithIdentifier:(NSString*)identifier maximized:(bool)maximized {
- if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
- NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"InAppProductsCell"
- owner:self
- options:nil];
- if ([arrayOfViews count] >= 1) {
- [self.contentView addSubview:[arrayOfViews objectAtIndex:0]];
- }
- _isMaximized = maximized;
- }
- return self;
-}
-
-
-- (NSString *)description {
- return [NSString stringWithFormat:@"%@ (%@): %@ (%@)", _ptitle.text, _pprice.text, _pdescription.text, _isMaximized ? @"maximized":@"minimized"];
-}
-
-+ (CGFloat)getHeight:(BOOL)maximized {
- return maximized ? 40 : 40;
-}
-
-@end
diff --git a/Classes/InAppProductsCell.xib b/Classes/InAppProductsCell.xib
deleted file mode 100644
index 73791c7a4..000000000
--- a/Classes/InAppProductsCell.xib
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Classes/InAppProductsManager.m b/Classes/InAppProductsManager.m
index 847697868..f4e77fac9 100644
--- a/Classes/InAppProductsManager.m
+++ b/Classes/InAppProductsManager.m
@@ -29,7 +29,6 @@
#import "LinphoneManager.h"
#import "PhoneMainView.h"
-#import "InAppProductsViewController.h"
@interface InAppProductsManager()
@property (strong, nonatomic) NSDate *expirationDate;
diff --git a/Classes/InAppProductsTableViewController.h b/Classes/InAppProductsTableViewController.h
deleted file mode 100644
index a98352c37..000000000
--- a/Classes/InAppProductsTableViewController.h
+++ /dev/null
@@ -1,13 +0,0 @@
-//
-// InAppProductsTableViewController.h
-// linphone
-//
-// Created by Gautier Pelloux-Prayer on 16/04/15.
-//
-//
-
-#import
-
-@interface InAppProductsTableViewController : UITableViewController
-
-@end
diff --git a/Classes/InAppProductsTableViewController.m b/Classes/InAppProductsTableViewController.m
deleted file mode 100644
index 6c5232283..000000000
--- a/Classes/InAppProductsTableViewController.m
+++ /dev/null
@@ -1,78 +0,0 @@
-//
-// InAppProductsTableViewController.m
-// linphone
-//
-// Created by Gautier Pelloux-Prayer on 16/04/15.
-//
-//
-
-#import "InAppProductsTableViewController.h"
-#import "InAppProductsCell.h"
-#import "InAppProductsManager.h"
-#import "LinphoneManager.h"
-#import "DTAlertView.h"
-
-@implementation InAppProductsTableViewController {
- NSInteger currentExpanded;
- InAppProductsManager *iapm;
-}
-
-- (void)viewWillAppear:(BOOL)animated {
- currentExpanded = -1;
- iapm = [[LinphoneManager instance] iapManager];
-}
-
-#pragma mark - Table view data source
-
-- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
- return 1;
-}
-
-- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
- return [iapm productsAvailable].count;
-}
-
-- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- static NSString *kCellId = @"InAppProductsCell";
- InAppProductsCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId];
- if (cell == nil) {
- cell = [[InAppProductsCell alloc] initWithIdentifier:kCellId maximized:(currentExpanded == indexPath.row)];
- }
- SKProduct *prod = [[[[LinphoneManager instance] iapManager] productsAvailable] objectAtIndex:indexPath.row];
- [cell fillFromProduct:prod];
- cell.isMaximized = (currentExpanded == indexPath.row);
- return cell;
-}
-
-//- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
-// if(currentExpanded == indexPath.row) {
-// currentExpanded = -1;
-// [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
-// return;
-// } else if(currentExpanded >= 0) {
-// NSIndexPath *previousPath = [NSIndexPath indexPathForRow:currentExpanded inSection:0];
-// currentExpanded = indexPath.row;
-// [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:previousPath] withRowAnimation:UITableViewRowAnimationFade];
-// }
-// currentExpanded = indexPath.row;
-// [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
-//}
-
-- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
- InAppProductsCell *cell = (InAppProductsCell*)[tableView cellForRowAtIndexPath:indexPath];
- if (cell.ppurchased.isOn) {
- DTAlertView* alert = [[DTAlertView alloc] initWithTitle:NSLocalizedString(@"Already purchased", nil) message: [NSString stringWithFormat:NSLocalizedString(@"You already bought %@.",nil), cell.ptitle.text]];
-
- [alert addCancelButtonWithTitle:NSLocalizedString(@"OK", nil) block:nil];
- [alert show];
- } else {
- //try to purchase item, and if successfull change the switch
- [[[LinphoneManager instance] iapManager] purchaseWitID: cell.productID];
- }
-}
-
--(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
- return [InAppProductsCell getHeight:(currentExpanded == indexPath.row)];
-}
-
-@end
diff --git a/Classes/InAppProductsViewController.h b/Classes/InAppProductsViewController.h
deleted file mode 100644
index 84ad3469d..000000000
--- a/Classes/InAppProductsViewController.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// InAppProductsViewController.h
-// linphone
-//
-// Created by Gautier Pelloux-Prayer on 15/04/15.
-//
-//
-
-#import
-#import "UICompositeViewController.h"
-#import "InAppProductsTableViewController.h"
-
-@interface InAppProductsViewController : UIViewController {
-}
-
-@property (nonatomic, strong) IBOutlet InAppProductsTableViewController* tableController;
-@property (strong, nonatomic) IBOutlet UIView *waitView;
-- (IBAction)onRestoreClicked:(UIButton *)sender;
-
-@end
diff --git a/Classes/InAppProductsViewController.m b/Classes/InAppProductsViewController.m
deleted file mode 100644
index 2154a82b0..000000000
--- a/Classes/InAppProductsViewController.m
+++ /dev/null
@@ -1,80 +0,0 @@
-//
-// InAppProductsViewController.m
-// linphone
-//
-// Created by Gautier Pelloux-Prayer on 15/04/15.
-//
-//
-
-#import "InAppProductsViewController.h"
-#import "InAppProductsCell.h"
-
-@implementation InAppProductsViewController
-
-#pragma mark - Lifecycle Functions
-
-- (id)init {
- return [super initWithNibName:@"InAppProductsViewController" bundle:[NSBundle mainBundle]];
-}
-
-
-- (void)dealloc {
- [[NSNotificationCenter defaultCenter] removeObserver:self];
-
-
-}
-
-#pragma mark - ViewController Functions
-
-- (void)viewDidLoad {
- [super viewDidLoad];
-}
-
-- (void)viewWillAppear:(BOOL)animated {
- [super viewWillAppear:animated];
- for (NSString* notification in [NSArray arrayWithObjects:kIAPReady, kIAPRestoreSucceeded, kIAPPurchaseSucceeded, kIAPReceiptSucceeded, kIAPPurchaseTrying, nil]) {
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(onIAPPurchaseNotification:)
- name:notification
- object:nil];
- }
-}
-
-- (void)viewWillDisappear:(BOOL)animated {
- [super viewWillDisappear:animated];
- for (NSString* notification in [NSArray arrayWithObjects:kIAPReady, kIAPRestoreSucceeded, kIAPPurchaseSucceeded, kIAPReceiptSucceeded, kIAPPurchaseTrying, nil]) {
- [[NSNotificationCenter defaultCenter] removeObserver:self
- name:notification
- object:nil];
- }
-}
-
-- (void)onIAPPurchaseNotification:(NSNotification*)notif {
- InAppProductsManager *iapm = [[LinphoneManager instance] iapManager];
- [[_tableController tableView] reloadData];
- [_waitView setHidden:([[iapm productsAvailable] count] != 0 && ![notif.name isEqualToString:kIAPPurchaseTrying])];
-}
-
-#pragma mark - UICompositeViewDelegate Functions
-
-static UICompositeViewDescription *compositeDescription = nil;
-
-+ (UICompositeViewDescription *)compositeViewDescription {
- if(compositeDescription == nil) {
- compositeDescription = [[UICompositeViewDescription alloc] init:@"InAppProducts"
- content:@"InAppProductsViewController"
- stateBar:nil
- stateBarEnabled:false
- tabBar: @"UIMainBar"
- tabBarEnabled:true
- fullscreen:false
- landscapeMode:[LinphoneManager runningOnIpad]
- portraitMode:true];
- }
- return compositeDescription;
-}
-
-- (IBAction)onRestoreClicked:(UIButton *)sender {
- [[[LinphoneManager instance] iapManager] restore];
-}
-@end
\ No newline at end of file
diff --git a/Classes/InAppProductsViewController.xib b/Classes/InAppProductsViewController.xib
deleted file mode 100644
index 4864c1eb0..000000000
--- a/Classes/InAppProductsViewController.xib
+++ /dev/null
@@ -1,70 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Classes/LinphoneCoreSettingsStore.h b/Classes/LinphoneCoreSettingsStore.h
index ee73e33ea..224b8f679 100644
--- a/Classes/LinphoneCoreSettingsStore.h
+++ b/Classes/LinphoneCoreSettingsStore.h
@@ -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
#import "IASKSettingsStore.h"
@@ -28,7 +28,6 @@
NSDictionary *changedDict;
}
-- (void)synchronizeAccount;
- (void)transformLinphoneCoreToKeys;
@end
diff --git a/Classes/LinphoneCoreSettingsStore.m b/Classes/LinphoneCoreSettingsStore.m
index 191972865..e392f1b9b 100644
--- a/Classes/LinphoneCoreSettingsStore.m
+++ b/Classes/LinphoneCoreSettingsStore.m
@@ -18,6 +18,7 @@
*/
#import "LinphoneCoreSettingsStore.h"
+#import "DTAlertView.h"
#include "linphone/lpconfig.h"
@@ -27,7 +28,7 @@ extern void linphone_iphone_log_handler(int lev, const char *fmt, va_list args);
- (id)init {
self = [super init];
- if (self){
+ if (self) {
dict = [[NSMutableDictionary alloc] init];
changedDict = [[NSMutableDictionary alloc] init];
[self transformLinphoneCoreToKeys];
@@ -35,193 +36,191 @@ extern void linphone_iphone_log_handler(int lev, const char *fmt, va_list args);
return self;
}
-
-- (void)transformKeysToLinphoneCore {
- //LinphoneCore *lc=[LinphoneManager getLc];
-
-}
-
-- (void)setString:(const char*)value forKey:(NSString*)key {
- id obj=Nil;
- if (value) obj=[[NSString alloc] initWithCString:value encoding:[NSString defaultCStringEncoding] ];
+- (void)setCString:(const char *)value forKey:(NSString *)key {
+ id obj = Nil;
+ if (value)
+ obj = [[NSString alloc] initWithCString:value encoding:[NSString defaultCStringEncoding]];
[self setObject:obj forKey:key];
}
-- (NSString*)stringForKey:(NSString*) key {
- return [self objectForKey: key];
+- (NSString *)stringForKey:(NSString *)key {
+ return [self objectForKey:key];
}
-- (void)transformCodecsToKeys: (const MSList *)codecs {
- LinphoneCore *lc=[LinphoneManager getLc];
- const MSList *elem=codecs;
- for(;elem!=NULL;elem=elem->next){
- PayloadType *pt=(PayloadType*)elem->data;
- NSString *pref=[LinphoneManager getPreferenceForCodec:pt->mime_type withRate:pt->clock_rate];
- if (pref){
- bool_t value = linphone_core_payload_type_enabled(lc,pt);
- [self setBool:value forKey: pref];
- }else{
- LOGW(@"Codec %s/%i supported by core is not shown in iOS app config view.",
- pt->mime_type,pt->clock_rate);
+- (void)setObject:(id)value forKey:(NSString *)key {
+ [dict setValue:value forKey:key];
+ [changedDict setValue:[NSNumber numberWithBool:TRUE] forKey:key];
+}
+
+- (id)objectForKey:(NSString *)key {
+ return [dict valueForKey:key];
+}
+
+- (BOOL)valueChangedForKey:(NSString *)key {
+ return [[changedDict valueForKey:key] boolValue];
+}
+
++ (int)validPort:(int)port {
+ if (port < 0) {
+ return 0;
+ }
+ if (port > 65535) {
+ return 65535;
+ }
+ return port;
+}
+
++ (BOOL)parsePortRange:(NSString *)text minPort:(int *)minPort maxPort:(int *)maxPort {
+ NSError *error = nil;
+ *minPort = -1;
+ *maxPort = -1;
+ NSRegularExpression *regex =
+ [NSRegularExpression regularExpressionWithPattern:@"([0-9]+)(([^0-9]+)([0-9]+))?" options:0 error:&error];
+ if (error != NULL)
+ return FALSE;
+ NSArray *matches = [regex matchesInString:text options:0 range:NSMakeRange(0, [text length])];
+ if ([matches count] == 1) {
+ NSTextCheckingResult *match = [matches objectAtIndex:0];
+ bool range = [match rangeAtIndex:2].length > 0;
+ if (!range) {
+ NSRange rangeMinPort = [match rangeAtIndex:1];
+ *minPort = [LinphoneCoreSettingsStore validPort:[[text substringWithRange:rangeMinPort] intValue]];
+ *maxPort = *minPort;
+ return TRUE;
+ } else {
+ NSRange rangeMinPort = [match rangeAtIndex:1];
+ *minPort = [LinphoneCoreSettingsStore validPort:[[text substringWithRange:rangeMinPort] intValue]];
+ NSRange rangeMaxPort = [match rangeAtIndex:4];
+ *maxPort = [LinphoneCoreSettingsStore validPort:[[text substringWithRange:rangeMaxPort] intValue]];
+ if (*minPort > *maxPort) {
+ *minPort = *maxPort;
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+- (void)transformCodecsToKeys:(const MSList *)codecs {
+ LinphoneCore *lc = [LinphoneManager getLc];
+
+ const MSList *elem = codecs;
+ for (; elem != NULL; elem = elem->next) {
+ PayloadType *pt = (PayloadType *)elem->data;
+ NSString *pref = [LinphoneManager getPreferenceForCodec:pt->mime_type withRate:pt->clock_rate];
+ if (pref) {
+ bool_t value = linphone_core_payload_type_enabled(lc, pt);
+ [self setBool:value forKey:pref];
+ } else {
+ LOGW(@"Codec %s/%i supported by core is not shown in iOS app config view.", pt->mime_type, pt->clock_rate);
}
}
}
- (void)transformLinphoneCoreToKeys {
- LinphoneCore *lc=[LinphoneManager getLc];
- LinphoneProxyConfig *cfg=NULL;
- LpConfig* conf = linphone_core_get_config(lc);
- linphone_core_get_default_proxy(lc,&cfg);
- if (cfg){
- const char *identity=linphone_proxy_config_get_identity(cfg);
- LinphoneAddress *addr=linphone_address_new(identity);
- if (addr){
- const char *proxy=linphone_proxy_config_get_addr(cfg);
- LinphoneAddress *proxy_addr=linphone_address_new(proxy);
- int port=linphone_address_get_port(proxy_addr);
+ LinphoneManager *lm = [LinphoneManager instance];
+ LinphoneCore *lc = [LinphoneManager getLc];
- [self setString: linphone_address_get_username(addr) forKey:@"username_preference"];
- [self setString: linphone_address_get_domain(addr) forKey:@"domain_preference"];
- [self setInteger: linphone_proxy_config_get_expires(cfg) forKey:@"expire_preference"];
- [self setString: linphone_proxy_config_get_dial_prefix(cfg) forKey:@"prefix_preference"];
- if (strcmp(linphone_address_get_domain(addr),linphone_address_get_domain(proxy_addr))!=0 || port>0){
- char tmp[256]={0};
- if (port>0) {
- snprintf(tmp,sizeof(tmp)-1,"%s:%i",linphone_address_get_domain(proxy_addr),port);
- }else snprintf(tmp,sizeof(tmp)-1,"%s",linphone_address_get_domain(proxy_addr));
- [self setString:tmp forKey:@"proxy_preference"];
+ // root section
+ {
+ LinphoneProxyConfig *cfg = NULL;
+ linphone_core_get_default_proxy(lc, &cfg);
+ if (cfg) {
+ const char *identity = linphone_proxy_config_get_identity(cfg);
+ LinphoneAddress *addr = linphone_address_new(identity);
+ if (addr) {
+ const char *proxy = linphone_proxy_config_get_addr(cfg);
+ LinphoneAddress *proxy_addr = linphone_address_new(proxy);
+ int port = linphone_address_get_port(proxy_addr);
+
+ [self setCString:linphone_address_get_username(addr) forKey:@"username_preference"];
+ [self setCString:linphone_address_get_domain(addr) forKey:@"domain_preference"];
+ if (strcmp(linphone_address_get_domain(addr), linphone_address_get_domain(proxy_addr)) != 0 ||
+ port > 0) {
+ char tmp[256] = {0};
+ if (port > 0) {
+ snprintf(tmp, sizeof(tmp) - 1, "%s:%i", linphone_address_get_domain(proxy_addr), port);
+ } else
+ snprintf(tmp, sizeof(tmp) - 1, "%s", linphone_address_get_domain(proxy_addr));
+ [self setCString:tmp forKey:@"proxy_preference"];
+ }
+ const char *tname = "udp";
+ switch (linphone_address_get_transport(proxy_addr)) {
+ case LinphoneTransportTcp:
+ tname = "tcp";
+ break;
+ case LinphoneTransportTls:
+ tname = "tls";
+ break;
+ default:
+ break;
+ }
+ linphone_address_destroy(addr);
+ linphone_address_destroy(proxy_addr);
+
+ [self setCString:tname forKey:@"transport_preference"];
+ [self setBool:(linphone_proxy_config_get_route(cfg) != NULL)forKey:@"outbound_proxy_preference"];
+ [self setBool:linphone_proxy_config_avpf_enabled(cfg) forKey:@"avpf_preference"];
+ [self setBool:linphone_core_video_enabled(lc) forKey:@"enable_video_preference"];
+
+ // actually in Advanced section but proxy config dependent
+ [self setInteger:linphone_proxy_config_get_expires(cfg) forKey:@"expire_preference"];
+ // actually in Call section but proxy config dependent
+ [self setCString:linphone_proxy_config_get_dial_prefix(cfg) forKey:@"prefix_preference"];
+ // actually in Call section but proxy config dependent
+ [self setBool:linphone_proxy_config_get_dial_escape_plus(cfg) forKey:@"substitute_+_by_00_preference"];
}
-
- const char* tname = "udp";
- switch (linphone_address_get_transport(proxy_addr)) {
- case LinphoneTransportTcp: tname = "tcp"; break;
- case LinphoneTransportTls: tname = "tls"; break;
- default: break;
- }
- [self setString:tname forKey:@"transport_preference"];
-
- linphone_address_destroy(addr);
- linphone_address_destroy(proxy_addr);
-
- [self setBool:(linphone_proxy_config_get_route(cfg)!=NULL) forKey:@"outbound_proxy_preference"];
- [self setBool:linphone_proxy_config_get_dial_escape_plus(cfg) forKey:@"substitute_+_by_00_preference"];
- [self setBool:linphone_proxy_config_avpf_enabled(cfg) forKey:@"avpf_preference"];
-
+ } else {
+ [self setObject:@"" forKey:@"username_preference"];
+ [self setObject:@"" forKey:@"password_preference"];
+ [self setObject:@"" forKey:@"domain_preference"];
+ [self setObject:@"" forKey:@"proxy_preference"];
+ [self setCString:"udp" forKey:@"transport_preference"];
+ [self setBool:FALSE forKey:@"outbound_proxy_preference"];
+ [self setBool:FALSE forKey:@"avpf_preference"];
+ // actually in Advanced section but proxy config dependent
+ [self setInteger:[lm lpConfigIntForKey:@"reg_expires" forSection:@"default_values" withDefault:600]
+ forKey:@"expire_preference"];
}
- } else {
- [self setInteger: lp_config_get_int(conf,"default_values","reg_expires", 600) forKey:@"expire_preference"];
- [self setObject:@"" forKey:@"username_preference"];
- [self setObject:@"" forKey:@"domain_preference"];
- [self setObject:@"" forKey:@"proxy_preference"];
- [self setObject:@"" forKey:@"password_preference"];
- [self setBool:FALSE forKey:@"outbound_proxy_preference"];
- [self setString:"udp" forKey:@"transport_preference"];
- [self setBool:FALSE forKey:@"avpf_preference"];
- }
-
- [self setBool:lp_config_get_int(conf, LINPHONERC_APPLICATION_KEY, "pushnotification_preference", 0) forKey:@"pushnotification_preference"];
- {
- LinphoneAddress *parsed = linphone_core_get_primary_contact_parsed(lc);
- if(parsed != NULL) {
- [self setString: linphone_address_get_display_name(parsed) forKey:@"primary_displayname_preference"];
- [self setString: linphone_address_get_username(parsed) forKey:@"primary_username_preference"];
- }
- linphone_address_destroy(parsed);
- }
- {
- {
- int minPort, maxPort;
- linphone_core_get_audio_port_range(lc, &minPort, &maxPort);
- if(minPort != maxPort)
- [self setObject:[NSString stringWithFormat:@"%d-%d", minPort, maxPort] forKey:@"audio_port_preference"];
- else
- [self setObject:[NSString stringWithFormat:@"%d", minPort] forKey:@"audio_port_preference"];
- }
- {
- int minPort, maxPort;
- linphone_core_get_video_port_range(lc, &minPort, &maxPort);
- if(minPort != maxPort)
- [self setObject:[NSString stringWithFormat:@"%d-%d", minPort, maxPort] forKey:@"video_port_preference"];
- else
- [self setObject:[NSString stringWithFormat:@"%d", minPort] forKey:@"video_port_preference"];
- }
- }
- {
- [self setInteger: linphone_core_get_upload_bandwidth(lc) forKey:@"upload_bandwidth_preference"];
- [self setInteger: linphone_core_get_download_bandwidth(lc) forKey:@"download_bandwidth_preference"];
- }
- {
- [self setFloat:linphone_core_get_playback_gain_db(lc) forKey:@"playback_gain_preference"];
- [self setFloat:linphone_core_get_mic_gain_db(lc) forKey:@"microphone_gain_preference"];
- }
- {
- int port = lp_config_get_int(conf, LINPHONERC_APPLICATION_KEY, "port_preference", 5060);
- [self setInteger:port forKey:@"port_preference"];
- int random_port_preference = lp_config_get_int(conf,LINPHONERC_APPLICATION_KEY,"random_port_preference", 1);
- [self setInteger:random_port_preference forKey:@"random_port_preference"];
- }
- {
LinphoneAuthInfo *ai;
- const MSList *elem=linphone_core_get_auth_info_list(lc);
- if (elem && (ai=(LinphoneAuthInfo*)elem->data)){
- [self setString: linphone_auth_info_get_passwd(ai) forKey:@"password_preference"];
- [self setString: linphone_auth_info_get_ha1(ai) forKey:@"ha1_preference"]; // hidden but useful if provisioned
- [self setString:linphone_auth_info_get_userid(ai) forKey:@"userid_preference"];
+ const MSList *elem = linphone_core_get_auth_info_list(lc);
+ if (elem && (ai = (LinphoneAuthInfo *)elem->data)) {
+ [self setCString:linphone_auth_info_get_userid(ai) forKey:@"userid_preference"];
+ [self setCString:linphone_auth_info_get_passwd(ai) forKey:@"password_preference"];
+ // hidden but useful if provisioned
+ [self setCString:linphone_auth_info_get_ha1(ai) forKey:@"ha1_preference"];
}
- }
- {
- [self setString: linphone_core_get_stun_server(lc) forKey:@"stun_preference"];
- [self setBool:linphone_core_get_firewall_policy(lc)==LinphonePolicyUseIce forKey:@"ice_preference"];
+ [self setBool:[lm lpConfigBoolForKey:@"advanced_account_preference"] forKey:@"advanced_account_preference"];
}
+ // audio section
{
- [self transformCodecsToKeys: linphone_core_get_audio_codecs(lc)];
- [self transformCodecsToKeys: linphone_core_get_video_codecs(lc)];
- [self setBool:linphone_core_adaptive_rate_control_enabled(lc) forKey:@"adaptive_rate_control_preference"];
- [self setString:linphone_core_get_adaptive_rate_algorithm(lc) forKey:@"adaptive_rate_algorithm_preference"];
-
- [self setInteger:lp_config_get_int(conf, "audio", "codec_bitrate_limit", kLinphoneAudioVbrCodecDefaultBitrate) forKey:@"audio_codec_bitrate_limit_preference"];
- [self setInteger:lp_config_get_int(conf, LINPHONERC_APPLICATION_KEY, "voiceproc_preference", 1) forKey:@"voiceproc_preference"];
- [self setInteger:lp_config_get_int(conf, "sound", "eq_active", 0) forKey:@"eq_active"];
+ [self transformCodecsToKeys:linphone_core_get_audio_codecs(lc)];
+ [self setFloat:linphone_core_get_playback_gain_db(lc) forKey:@"playback_gain_preference"];
+ [self setFloat:linphone_core_get_mic_gain_db(lc) forKey:@"microphone_gain_preference"];
+ [self setInteger:[lm lpConfigIntForKey:@"codec_bitrate_limit"
+ forSection:@"audio"
+ withDefault:kLinphoneAudioVbrCodecDefaultBitrate]
+ forKey:@"audio_codec_bitrate_limit_preference"];
+ [self setInteger:[lm lpConfigIntForKey:@"voiceproc_preference" withDefault:1] forKey:@"voiceproc_preference"];
+ [self setInteger:[lm lpConfigIntForKey:@"eq_active" forSection:@"sound" withDefault:0] forKey:@"eq_active"];
}
- [self setBool:lp_config_get_int(conf, LINPHONERC_APPLICATION_KEY, "advanced_account_preference", 0) forKey:@"advanced_account_preference"];
-
+ // video section
{
- LinphoneMediaEncryption menc=linphone_core_get_media_encryption(lc);
- const char *val;
- switch(menc){
- case LinphoneMediaEncryptionSRTP: val="SRTP"; break;
- case LinphoneMediaEncryptionZRTP: val="ZRTP"; break;
- case LinphoneMediaEncryptionDTLS: val="DTLS"; break;
- case LinphoneMediaEncryptionNone: val="None"; break;
- }
- [self setString:val forKey:@"media_encryption_preference"];
- }
- [self setBool: lp_config_get_int(conf, LINPHONERC_APPLICATION_KEY, "edge_opt_preference", 0) forKey:@"edge_opt_preference"];
- [self setBool: lp_config_get_int(conf, LINPHONERC_APPLICATION_KEY, "enable_first_login_view_preference", 0) forKey:@"enable_first_login_view_preference"];
- [self setBool: lp_config_get_int(conf, LINPHONERC_APPLICATION_KEY, "debugenable_preference", 0) forKey:@"debugenable_preference"];
- [self setBool: lp_config_get_int(conf, LINPHONERC_APPLICATION_KEY, "animations_preference", 1) forKey:@"animations_preference"];
- [self setBool: lp_config_get_int(conf, LINPHONERC_APPLICATION_KEY, "wifi_only_preference", 0) forKey:@"wifi_only_preference"];
- [self setString: lp_config_get_string(conf, LINPHONERC_APPLICATION_KEY, "sharing_server_preference", NULL) forKey:@"sharing_server_preference"];
- [self setBool:lp_config_get_int(conf, "sip", "use_ipv6", 0) forKey:@"use_ipv6"];
+ [self transformCodecsToKeys:linphone_core_get_video_codecs(lc)];
-
- [self setBool: lp_config_get_int(conf,LINPHONERC_APPLICATION_KEY,"start_at_boot_preference",1) forKey:@"start_at_boot_preference"];
- [self setBool: lp_config_get_int(conf,LINPHONERC_APPLICATION_KEY,"backgroundmode_preference",1) forKey:@"backgroundmode_preference"];
- [self setBool: lp_config_get_int(conf,LINPHONERC_APPLICATION_KEY,"autoanswer_notif_preference",1) forKey:@"autoanswer_notif_preference"];
-
-
- {
const LinphoneVideoPolicy *pol;
- [self setBool: linphone_core_video_enabled(lc) forKey:@"enable_video_preference"];
- pol=linphone_core_get_video_policy(lc);
- [self setBool:(pol->automatically_initiate) forKey:@"start_video_preference"];
- [self setBool:(pol->automatically_accept) forKey:@"accept_video_preference"];
+ pol = linphone_core_get_video_policy(lc);
+ [self setBool:(pol->automatically_initiate)forKey:@"start_video_preference"];
+ [self setBool:(pol->automatically_accept)forKey:@"accept_video_preference"];
[self setBool:linphone_core_self_view_enabled(lc) forKey:@"self_video_preference"];
- BOOL previewEnabled=lp_config_get_int(conf,LINPHONERC_APPLICATION_KEY,"preview_preference",1);
+ BOOL previewEnabled = [lm lpConfigBoolForKey:@"preview_preference" withDefault:YES];
[self setBool:previewEnabled forKey:@"preview_preference"];
+
+ const char *preset = linphone_core_get_video_preset(lc);
+ [self setCString:preset ? preset : "default" forKey:@"video_preset_preference"];
MSVideoSize vsize = linphone_core_get_preferred_video_size(lc);
int index;
if ((vsize.width == MS_VIDEO_SIZE_720P_W) && (vsize.height == MS_VIDEO_SIZE_720P_H)) {
@@ -232,30 +231,112 @@ extern void linphone_iphone_log_handler(int lev, const char *fmt, va_list args);
index = 2;
}
[self setInteger:index forKey:@"video_preferred_size_preference"];
+ [self setInteger:linphone_core_get_preferred_framerate(lc) forKey:@"video_preferred_fps_preference"];
+ [self setInteger:linphone_core_get_download_bandwidth(lc) forKey:@"download_bandwidth_preference"];
}
+
+ // call section
{
[self setBool:linphone_core_get_use_info_for_dtmf(lc) forKey:@"sipinfo_dtmf_preference"];
[self setBool:linphone_core_get_use_rfc2833_for_dtmf(lc) forKey:@"rfc_dtmf_preference"];
[self setInteger:linphone_core_get_inc_timeout(lc) forKey:@"incoming_call_timeout_preference"];
[self setInteger:linphone_core_get_in_call_timeout(lc) forKey:@"in_call_timeout_preference"];
+
+ [self setBool:[lm lpConfigBoolForKey:@"repeat_call_notification"]
+ forKey:@"repeat_call_notification_preference"];
}
- // Tunnel
- if (linphone_core_tunnel_available()){
+ // network section
+ {
+ [self setBool:[lm lpConfigBoolForKey:@"edge_opt_preference" withDefault:NO] forKey:@"edge_opt_preference"];
+ [self setBool:[lm lpConfigBoolForKey:@"wifi_only_preference" withDefault:NO] forKey:@"wifi_only_preference"];
+ [self setCString:linphone_core_get_stun_server(lc) forKey:@"stun_preference"];
+ [self setBool:linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce forKey:@"ice_preference"];
+ int random_port_preference = [lm lpConfigIntForKey:@"random_port_preference" withDefault:1];
+ [self setInteger:random_port_preference forKey:@"random_port_preference"];
+ int port = [lm lpConfigIntForKey:@"port_preference" withDefault:5060];
+ [self setInteger:port forKey:@"port_preference"];
+ {
+ int minPort, maxPort;
+ linphone_core_get_audio_port_range(lc, &minPort, &maxPort);
+ if (minPort != maxPort)
+ [self setObject:[NSString stringWithFormat:@"%d-%d", minPort, maxPort] forKey:@"audio_port_preference"];
+ else
+ [self setObject:[NSString stringWithFormat:@"%d", minPort] forKey:@"audio_port_preference"];
+ }
+ {
+ int minPort, maxPort;
+ linphone_core_get_video_port_range(lc, &minPort, &maxPort);
+ if (minPort != maxPort)
+ [self setObject:[NSString stringWithFormat:@"%d-%d", minPort, maxPort] forKey:@"video_port_preference"];
+ else
+ [self setObject:[NSString stringWithFormat:@"%d", minPort] forKey:@"video_port_preference"];
+ }
+ [self setBool:[lm lpConfigBoolForKey:@"use_ipv6" withDefault:NO] forKey:@"use_ipv6"];
+ LinphoneMediaEncryption menc = linphone_core_get_media_encryption(lc);
+ const char *val;
+ switch (menc) {
+ case LinphoneMediaEncryptionSRTP:
+ val = "SRTP";
+ break;
+ case LinphoneMediaEncryptionZRTP:
+ val = "ZRTP";
+ break;
+ case LinphoneMediaEncryptionDTLS:
+ val = "DTLS";
+ break;
+ case LinphoneMediaEncryptionNone:
+ val = "None";
+ break;
+ }
+ [self setCString:val forKey:@"media_encryption_preference"];
+ [self setBool:[lm lpConfigBoolForKey:@"pushnotification_preference" withDefault:NO]
+ forKey:@"pushnotification_preference"];
+ [self setInteger:linphone_core_get_upload_bandwidth(lc) forKey:@"upload_bandwidth_preference"];
+ [self setInteger:linphone_core_get_download_bandwidth(lc) forKey:@"download_bandwidth_preference"];
+ [self setBool:linphone_core_adaptive_rate_control_enabled(lc) forKey:@"adaptive_rate_control_preference"];
+ [self setCString:linphone_core_get_adaptive_rate_algorithm(lc) forKey:@"adaptive_rate_algorithm_preference"];
+ }
+
+ // tunnel section
+ if (linphone_core_tunnel_available()) {
LinphoneTunnel *tunnel = linphone_core_get_tunnel([LinphoneManager getLc]);
- [self setString:lp_config_get_string(linphone_core_get_config(lc), LINPHONERC_APPLICATION_KEY, "tunnel_mode_preference", "off") forKey:@"tunnel_mode_preference"];
- const MSList* configs = linphone_tunnel_get_servers(tunnel);
- if(configs != NULL) {
+ [self setObject:[lm lpConfigStringForKey:@"tunnel_mode_preference" withDefault:@"off"]
+ forKey:@"tunnel_mode_preference"];
+ const MSList *configs = linphone_tunnel_get_servers(tunnel);
+ if (configs != NULL) {
LinphoneTunnelConfig *ltc = (LinphoneTunnelConfig *)configs->data;
- [self setString:linphone_tunnel_config_get_host(ltc) forKey:@"tunnel_address_preference"];
+ [self setCString:linphone_tunnel_config_get_host(ltc) forKey:@"tunnel_address_preference"];
[self setInteger:linphone_tunnel_config_get_port(ltc) forKey:@"tunnel_port_preference"];
} else {
- [self setString:"" forKey:@"tunnel_address_preference"];
+ [self setCString:"" forKey:@"tunnel_address_preference"];
[self setInteger:443 forKey:@"tunnel_port_preference"];
}
}
+ // advanced section
+ {
+ [self setBool:[lm lpConfigBoolForKey:@"debugenable_preference" withDefault:NO]
+ forKey:@"debugenable_preference"];
+ [self setBool:[lm lpConfigBoolForKey:@"animations_preference" withDefault:NO] forKey:@"animations_preference"];
+ [self setBool:[lm lpConfigBoolForKey:@"backgroundmode_preference" withDefault:NO]
+ forKey:@"backgroundmode_preference"];
+ [self setBool:[lm lpConfigBoolForKey:@"start_at_boot_preference" withDefault:NO]
+ forKey:@"start_at_boot_preference"];
+ [self setBool:[lm lpConfigBoolForKey:@"autoanswer_notif_preference" withDefault:NO]
+ forKey:@"autoanswer_notif_preference"];
+ [self setBool:[lm lpConfigBoolForKey:@"enable_first_login_view_preference" withDefault:NO]
+ forKey:@"enable_first_login_view_preference"];
+ LinphoneAddress *parsed = linphone_core_get_primary_contact_parsed(lc);
+ if (parsed != NULL) {
+ [self setCString:linphone_address_get_display_name(parsed) forKey:@"primary_displayname_preference"];
+ [self setCString:linphone_address_get_username(parsed) forKey:@"primary_username_preference"];
+ }
+ linphone_address_destroy(parsed);
+ [self setObject:[lm lpConfigStringForKey:@"sharing_server_preference"] forKey:@"sharing_server_preference"];
+ }
+
changedDict = [[NSMutableDictionary alloc] init];
// Post event
@@ -263,48 +344,31 @@ extern void linphone_iphone_log_handler(int lev, const char *fmt, va_list args);
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneLogsUpdate object:self userInfo:eventDic];
}
-- (void)setObject:(id)value forKey:(NSString *)key {
- [dict setValue:value forKey:key];
- [changedDict setValue:[NSNumber numberWithBool:TRUE] forKey:key];
-}
-
-- (id)objectForKey:(NSString*)key {
- return [dict valueForKey:key];
-}
-
-- (BOOL)valueChangedForKey:(NSString*)key {
- return [[changedDict valueForKey:key] boolValue];
-}
-
-- (void)alertAccountError:(NSString*)error {
- UIAlertView* alertview = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil)
+- (void)alertAccountError:(NSString *)error {
+ UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil)
message:error
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK", nil)
- otherButtonTitles: nil];
+ otherButtonTitles:nil];
[alertview show];
}
-+ (BOOL)hasSipPrefix:(NSString*)str {
- return [str hasPrefix:@"sip:"] || [str hasPrefix:@"sips:"];
-}
-
- (void)synchronizeAccount {
+ LinphoneManager *lm = [LinphoneManager instance];
LinphoneCore *lc = [LinphoneManager getLc];
- LpConfig* conf = linphone_core_get_config(lc);
- LinphoneProxyConfig* proxyCfg = NULL;
+ LinphoneProxyConfig *proxyCfg = NULL;
BOOL isEditing = FALSE;
- NSString* error = nil;
+ NSString *error = nil;
int port_preference = [self integerForKey:@"port_preference"];
BOOL random_port_preference = [self boolForKey:@"random_port_preference"];
- lp_config_set_int(conf, LINPHONERC_APPLICATION_KEY, "random_port_preference", random_port_preference);
- if(random_port_preference) {
+ [lm lpConfigSetInt:random_port_preference forKey:@"random_port_preference"];
+ if (random_port_preference) {
port_preference = -1;
}
- LCSipTransports transportValue={ port_preference, port_preference, -1, -1 };
+ LCSipTransports transportValue = {port_preference, port_preference, -1, -1};
// will also update the sip_*_port section of the config
if (linphone_core_set_sip_transports(lc, &transportValue)) {
@@ -314,54 +378,55 @@ extern void linphone_iphone_log_handler(int lev, const char *fmt, va_list args);
port_preference = linphone_core_get_sip_port(lc);
[self setInteger:port_preference forKey:@"port_preference"]; // Update back preference
-
BOOL enable_ipv6 = [self boolForKey:@"use_ipv6"];
- lp_config_set_int(conf, "sip", "use_ipv6", enable_ipv6);
- if( linphone_core_ipv6_enabled(lc) != enable_ipv6){
- LOGD(@"%@ IPV6", enable_ipv6?@"ENABLING":@"DISABLING");
+ [lm lpConfigSetBool:enable_ipv6 forKey:@"use_ipv6" forSection:@"sip"];
+ if (linphone_core_ipv6_enabled(lc) != enable_ipv6) {
+ LOGD(@"%@ IPV6", enable_ipv6 ? @"ENABLING" : @"DISABLING");
linphone_core_enable_ipv6(lc, enable_ipv6);
}
+ // configure sip account
- //configure sip account
+ // mandatory parameters
+ NSString *username = [self stringForKey:@"username_preference"];
+ NSString *userID = [self stringForKey:@"userid_preference"];
+ NSString *domain = [self stringForKey:@"domain_preference"];
+ NSString *transport = [self stringForKey:@"transport_preference"];
+ NSString *accountHa1 = [self stringForKey:@"ha1_preference"];
+ NSString *accountPassword = [self stringForKey:@"password_preference"];
+ bool isOutboundProxy = [self boolForKey:@"outbound_proxy_preference"];
+ BOOL use_avpf = [self boolForKey:@"avpf_preference"];
- //mandatory parameters
- NSString* username = [self stringForKey:@"username_preference"];
- NSString* userID = [self stringForKey:@"userid_preference"];
- NSString* domain = [self stringForKey:@"domain_preference"];
- NSString* transport = [self stringForKey:@"transport_preference"];
- NSString* accountHa1 = [self stringForKey:@"ha1_preference"];
- NSString* accountPassword = [self stringForKey:@"password_preference"];
- bool isOutboundProxy = [self boolForKey:@"outbound_proxy_preference"];
- BOOL use_avpf = [self boolForKey:@"avpf_preference"];
+ if (username && [username length] > 0 && domain && [domain length] > 0) {
+ int expire = [self integerForKey:@"expire_preference"];
+ BOOL isWifiOnly = [self boolForKey:@"wifi_only_preference"];
+ BOOL pushnotification = [self boolForKey:@"pushnotification_preference"];
+ NSString *prefix = [self stringForKey:@"prefix_preference"];
+ NSString *proxyAddress = [self stringForKey:@"proxy_preference"];
- if (username && [username length] >0 && domain && [domain length]>0) {
- int expire = [self integerForKey:@"expire_preference"];
- BOOL isWifiOnly = [self boolForKey:@"wifi_only_preference"];
- BOOL pushnotification = [self boolForKey:@"pushnotification_preference"];
- NSString* prefix = [self stringForKey:@"prefix_preference"];
- NSString* proxyAddress = [self stringForKey:@"proxy_preference"];
+ LinphoneAuthInfo *info = NULL;
+ const char *route = NULL;
- LinphoneAuthInfo *info = NULL;
- const char* route = NULL;
+ if (isWifiOnly && [LinphoneManager instance].connectivity == wwan)
+ expire = 0;
- if( isWifiOnly && [LinphoneManager instance].connectivity == wwan ) expire = 0;
-
- if ((!proxyAddress || [proxyAddress length] <1 ) && domain) {
+ if ((!proxyAddress || [proxyAddress length] < 1) && domain) {
proxyAddress = domain;
- }
-
- if( ![LinphoneCoreSettingsStore hasSipPrefix:proxyAddress] ) {
- proxyAddress = [NSString stringWithFormat:@"sip:%@",proxyAddress];
}
- char* proxy = ms_strdup([proxyAddress cStringUsingEncoding:[NSString defaultCStringEncoding]]);
- LinphoneAddress* proxy_addr = linphone_address_new(proxy);
+ if (![proxyAddress hasPrefix:@"sip:"] && ![proxyAddress hasPrefix:@"sips:"]) {
+ proxyAddress = [NSString stringWithFormat:@"sip:%@", proxyAddress];
+ }
- if( proxy_addr ){
+ char *proxy = ms_strdup([proxyAddress cStringUsingEncoding:[NSString defaultCStringEncoding]]);
+ LinphoneAddress *proxy_addr = linphone_address_new(proxy);
+
+ if (proxy_addr) {
LinphoneTransportType type = LinphoneTransportUdp;
- if ( [transport isEqualToString:@"tcp"] ) type = LinphoneTransportTcp;
- else if ( [transport isEqualToString:@"tls"] ) type = LinphoneTransportTls;
+ if ([transport isEqualToString:@"tcp"])
+ type = LinphoneTransportTcp;
+ else if ([transport isEqualToString:@"tls"])
+ type = LinphoneTransportTls;
linphone_address_set_transport(proxy_addr, type);
ms_free(proxy);
@@ -369,11 +434,11 @@ extern void linphone_iphone_log_handler(int lev, const char *fmt, va_list args);
}
// use proxy as route if outbound_proxy is enabled
- route = isOutboundProxy? proxy : NULL;
+ route = isOutboundProxy ? proxy : NULL;
- //possible valid config detected, try to modify current proxy or create new one if none existing
+ // possible valid config detected, try to modify current proxy or create new one if none existing
linphone_core_get_default_proxy(lc, &proxyCfg);
- if( proxyCfg == NULL ){
+ if (proxyCfg == NULL) {
proxyCfg = linphone_core_create_proxy_config(lc);
} else {
isEditing = TRUE;
@@ -381,30 +446,41 @@ extern void linphone_iphone_log_handler(int lev, const char *fmt, va_list args);
}
char normalizedUserName[256];
- LinphoneAddress* linphoneAddress = linphone_address_new("sip:user@domain.com");
- linphone_proxy_config_normalize_number(proxyCfg, [username cStringUsingEncoding:[NSString defaultCStringEncoding]], normalizedUserName, sizeof(normalizedUserName));
+ LinphoneAddress *linphoneAddress = linphone_address_new("sip:user@domain.com");
+ linphone_proxy_config_normalize_number(proxyCfg,
+ [username cStringUsingEncoding:[NSString defaultCStringEncoding]],
+ normalizedUserName, sizeof(normalizedUserName));
linphone_address_set_username(linphoneAddress, normalizedUserName);
linphone_address_set_domain(linphoneAddress, [domain cStringUsingEncoding:[NSString defaultCStringEncoding]]);
- const char* identity = linphone_address_as_string_uri_only(linphoneAddress);
- const char* password = [accountPassword cStringUsingEncoding:[NSString defaultCStringEncoding]];
- const char* ha1 = [accountHa1 cStringUsingEncoding:[NSString defaultCStringEncoding]];
+ const char *identity = linphone_address_as_string_uri_only(linphoneAddress);
+ const char *password = [accountPassword cStringUsingEncoding:[NSString defaultCStringEncoding]];
+ const char *ha1 = [accountHa1 cStringUsingEncoding:[NSString defaultCStringEncoding]];
+ if (linphone_proxy_config_set_identity(proxyCfg, identity) == -1) {
+ error = NSLocalizedString(@"Invalid username or domain", nil);
+ goto bad_proxy;
+ }
+ if (linphone_proxy_config_set_server_addr(proxyCfg, proxy) == -1) {
+ error = NSLocalizedString(@"Invalid proxy address", nil);
+ goto bad_proxy;
+ }
+ if (linphone_proxy_config_set_route(proxyCfg, route) == -1) {
+ error = NSLocalizedString(@"Invalid route", nil);
+ goto bad_proxy;
+ }
- if( linphone_proxy_config_set_identity(proxyCfg, identity) == -1 ) { error = NSLocalizedString(@"Invalid username or domain",nil); goto bad_proxy;}
- if( linphone_proxy_config_set_server_addr(proxyCfg, proxy) == -1 ) { error = NSLocalizedString(@"Invalid proxy address", nil); goto bad_proxy; }
- if( linphone_proxy_config_set_route(proxyCfg, route) == -1 ) { error = NSLocalizedString(@"Invalid route", nil); goto bad_proxy; }
-
- if ([prefix length]>0) {
- linphone_proxy_config_set_dial_prefix(proxyCfg, [prefix cStringUsingEncoding:[NSString defaultCStringEncoding]]);
+ if ([prefix length] > 0) {
+ linphone_proxy_config_set_dial_prefix(proxyCfg,
+ [prefix cStringUsingEncoding:[NSString defaultCStringEncoding]]);
}
if ([self objectForKey:@"substitute_+_by_00_preference"]) {
bool substitute_plus_by_00 = [self boolForKey:@"substitute_+_by_00_preference"];
- linphone_proxy_config_set_dial_escape_plus(proxyCfg,substitute_plus_by_00);
+ linphone_proxy_config_set_dial_escape_plus(proxyCfg, substitute_plus_by_00);
}
- lp_config_set_int(conf, LINPHONERC_APPLICATION_KEY, "pushnotification_preference", pushnotification);
+ [lm lpConfigSetInt:pushnotification forKey:@"pushnotification_preference"];
[[LinphoneManager instance] configurePushTokenForProxyConfig:proxyCfg];
linphone_proxy_config_enable_register(proxyCfg, true);
@@ -413,9 +489,10 @@ extern void linphone_iphone_log_handler(int lev, const char *fmt, va_list args);
// setup auth info
LinphoneAddress *from = linphone_address_new(identity);
- if (from != 0){
- const char* userid_str = (userID != nil)? [userID UTF8String] : NULL;
- info=linphone_auth_info_new(linphone_address_get_username(from),userid_str,password,ha1,NULL,linphone_proxy_config_get_domain(proxyCfg));
+ if (from != 0) {
+ const char *userid_str = (userID != nil) ? [userID UTF8String] : NULL;
+ info = linphone_auth_info_new(linphone_address_get_username(from), userid_str, password, ha1, NULL,
+ linphone_proxy_config_get_domain(proxyCfg));
linphone_address_destroy(from);
}
@@ -423,178 +500,123 @@ extern void linphone_iphone_log_handler(int lev, const char *fmt, va_list args);
// add auth info
linphone_core_clear_all_auth_info(lc);
- if( info ) { linphone_core_add_auth_info(lc,info); }
+ if (info) {
+ linphone_core_add_auth_info(lc, info);
+ }
// setup new proxycfg
- if( isEditing ){
+ if (isEditing) {
linphone_proxy_config_done(proxyCfg);
} else {
// was a new proxy config, add it
linphone_core_add_proxy_config(lc, proxyCfg);
- linphone_core_set_default_proxy_config(lc,proxyCfg);
+ linphone_core_set_default_proxy_config(lc, proxyCfg);
}
bad_proxy:
- if( linphoneAddress)
+ if (linphoneAddress)
linphone_address_destroy(linphoneAddress);
- if( proxy)
+ if (proxy)
ms_free(proxy);
- if( info )
+ if (info)
linphone_auth_info_destroy(info);
// in case of error, show an alert to the user
- if( error != nil ){
- if( isEditing ) linphone_proxy_config_done(proxyCfg);
- else linphone_proxy_config_destroy(proxyCfg);
+ if (error != nil) {
+ if (isEditing)
+ linphone_proxy_config_done(proxyCfg);
+ else
+ linphone_proxy_config_destroy(proxyCfg);
- [self alertAccountError:error];
+ [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil)
+ message:error
+ delegate:nil
+ cancelButtonTitle:NSLocalizedString(@"OK", nil)
+ otherButtonTitles:nil] show];
}
}
[[[LinphoneManager instance] fastAddressBook] reload];
}
-+ (int)validPort:(int)port {
- if(port < 0) {
- return 0;
- }
- if(port > 65535) {
- return 65535;
- }
- return port;
-}
-
-+ (BOOL)parsePortRange:(NSString*)text minPort:(int*)minPort maxPort:(int*)maxPort {
- NSError* error = nil;
- *minPort = -1;
- *maxPort = -1;
- NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:@"([0-9]+)(([^0-9]+)([0-9]+))?" options:0 error:&error];
- if(error != NULL)
- return FALSE;
- NSArray* matches = [regex matchesInString:text options:0 range:NSMakeRange(0, [text length])];
- if([matches count] == 1) {
- NSTextCheckingResult *match = [matches objectAtIndex:0];
- bool range = [match rangeAtIndex:2].length > 0;
- if(!range) {
- NSRange rangeMinPort = [match rangeAtIndex:1];
- *minPort = [LinphoneCoreSettingsStore validPort:[[text substringWithRange:rangeMinPort] intValue]];
- *maxPort = *minPort;
- return TRUE;
- } else {
- NSRange rangeMinPort = [match rangeAtIndex:1];
- *minPort = [LinphoneCoreSettingsStore validPort:[[text substringWithRange:rangeMinPort] intValue]];
- NSRange rangeMaxPort = [match rangeAtIndex:4];
- *maxPort = [LinphoneCoreSettingsStore validPort:[[text substringWithRange:rangeMaxPort] intValue]];
- if(*minPort > *maxPort) {
- *minPort = *maxPort;
- }
- return TRUE;
- }
- }
- return FALSE;
-}
-
-- (BOOL)synchronize {
- LinphoneCore *lc=[LinphoneManager getLc];
-
- BOOL account_changed;
-
- account_changed=[self valueChangedForKey:@"username_preference"]
- || [self valueChangedForKey:@"password_preference"]
- || [self valueChangedForKey:@"domain_preference"]
- || [self valueChangedForKey:@"expire_preference"]
- || [self valueChangedForKey:@"proxy_preference"]
- || [self valueChangedForKey:@"outbound_proxy_preference"]
- || [self valueChangedForKey:@"transport_preference"]
- || [self valueChangedForKey:@"port_preference"]
- || [self valueChangedForKey:@"random_port_preference"]
- || [self valueChangedForKey:@"prefix_preference"]
- || [self valueChangedForKey:@"substitute_+_by_00_preference"]
- || [self valueChangedForKey:@"use_ipv6"]
- || [self valueChangedForKey:@"avpf_preference"]
- || [self valueChangedForKey:@"pushnotification_preference"];
-
- if (account_changed)
- [self synchronizeAccount];
-
- //Configure Codecs
-
+- (void)synchronizeCodecs:(const MSList *)codecs {
+ LinphoneCore *lc = [LinphoneManager getLc];
PayloadType *pt;
const MSList *elem;
- for (elem=linphone_core_get_audio_codecs(lc);elem!=NULL;elem=elem->next){
- pt=(PayloadType*)elem->data;
- NSString *pref=[LinphoneManager getPreferenceForCodec:pt->mime_type withRate:pt->clock_rate];
- linphone_core_enable_payload_type(lc,pt,[self boolForKey: pref]);
+ for (elem = codecs; elem != NULL; elem = elem->next) {
+ pt = (PayloadType *)elem->data;
+ NSString *pref = [LinphoneManager getPreferenceForCodec:pt->mime_type withRate:pt->clock_rate];
+ linphone_core_enable_payload_type(lc, pt, [self boolForKey:pref]);
+ }
+}
+
+- (BOOL)synchronize {
+ LinphoneManager *lm = [LinphoneManager instance];
+ LinphoneCore *lc = [LinphoneManager getLc];
+ // root section
+ {
+ BOOL account_changed =
+ [self valueChangedForKey:@"username_preference"] || [self valueChangedForKey:@"password_preference"] ||
+ [self valueChangedForKey:@"domain_preference"] || [self valueChangedForKey:@"expire_preference"] ||
+ [self valueChangedForKey:@"proxy_preference"] || [self valueChangedForKey:@"outbound_proxy_preference"] ||
+ [self valueChangedForKey:@"transport_preference"] || [self valueChangedForKey:@"port_preference"] ||
+ [self valueChangedForKey:@"random_port_preference"] || [self valueChangedForKey:@"prefix_preference"] ||
+ [self valueChangedForKey:@"substitute_+_by_00_preference"] || [self valueChangedForKey:@"use_ipv6"] ||
+ [self valueChangedForKey:@"avpf_preference"] || [self valueChangedForKey:@"pushnotification_preference"];
+ if (account_changed)
+ [self synchronizeAccount];
+
+ bool enableVideo = [self boolForKey:@"enable_video_preference"];
+ linphone_core_enable_video(lc, enableVideo, enableVideo);
}
- for (elem=linphone_core_get_video_codecs(lc);elem!=NULL;elem=elem->next){
- pt=(PayloadType*)elem->data;
- NSString *pref=[LinphoneManager getPreferenceForCodec:pt->mime_type withRate:pt->clock_rate];
- linphone_core_enable_payload_type(lc,pt,[self boolForKey: pref]);
- }
+ // audio section
+ {
+ [self synchronizeCodecs:linphone_core_get_audio_codecs(lc)];
- LpConfig *config = linphone_core_get_config(lc);
- lp_config_set_int(config, "audio", "codec_bitrate_limit", [self integerForKey:@"audio_codec_bitrate_limit_preference"]);
- [[LinphoneManager instance] configureVbrCodecs];
- linphone_core_enable_adaptive_rate_control(lc, [self boolForKey:@"adaptive_rate_control_preference"]);
- linphone_core_set_adaptive_rate_algorithm(lc, [
- [self stringForKey:@"adaptive_rate_algorithm_preference"] cStringUsingEncoding:[NSString defaultCStringEncoding]
- ]);
+ float playback_gain = [self floatForKey:@"playback_gain_preference"];
+ linphone_core_set_playback_gain_db(lc, playback_gain);
- // Voice processing
- BOOL voice_processing = [self boolForKey:@"voiceproc_preference"];
- lp_config_set_int(config, LINPHONERC_APPLICATION_KEY, "voiceproc_preference", voice_processing);
- NSString* au_device = @"AU: Audio Unit Receiver";
- if( !voice_processing ){ au_device = @"AU: Audio Unit NoVoiceProc"; }
- linphone_core_set_capture_device(lc, [au_device UTF8String]);
- linphone_core_set_playback_device(lc, [au_device UTF8String]);
+ float mic_gain = [self floatForKey:@"microphone_gain_preference"];
+ linphone_core_set_mic_gain_db(lc, mic_gain);
- BOOL equalizer = [self boolForKey:@"eq_active"];
- lp_config_set_int(config, "sound", "eq_active", equalizer);
+ [lm lpConfigSetInt:[self integerForKey:@"audio_codec_bitrate_limit_preference"]
+ forKey:@"codec_bitrate_limit"
+ forSection:@"audio"];
- linphone_core_set_use_info_for_dtmf(lc, [self boolForKey:@"sipinfo_dtmf_preference"]);
- linphone_core_set_use_rfc2833_for_dtmf(lc, [self boolForKey:@"rfc_dtmf_preference"]);
- linphone_core_set_inc_timeout(lc, [self integerForKey:@"incoming_call_timeout_preference"]);
- linphone_core_set_in_call_timeout(lc, [self integerForKey:@"in_call_timeout_preference"]);
- lp_config_set_string(config, "app", "voice_mail_uri", [[self stringForKey:@"voice_mail_uri_preference"] UTF8String]);
+ BOOL voice_processing = [self boolForKey:@"voiceproc_preference"];
+ [lm lpConfigSetInt:voice_processing forKey:@"voiceproc_preference"];
- bool enableVideo = [self boolForKey:@"enable_video_preference"];
- linphone_core_enable_video(lc, enableVideo, enableVideo);
+ BOOL equalizer = [self boolForKey:@"eq_active"];
+ [lm lpConfigSetBool:equalizer forKey:@"eq_active" forSection:@"sound"];
- NSString *menc = [self stringForKey:@"media_encryption_preference"];
- if (menc && [menc compare:@"SRTP"] == NSOrderedSame)
- linphone_core_set_media_encryption(lc, LinphoneMediaEncryptionSRTP);
- else if (menc && [menc compare:@"ZRTP"] == NSOrderedSame)
- linphone_core_set_media_encryption(lc, LinphoneMediaEncryptionZRTP);
- else if (menc && [menc compare:@"DTLS"] == NSOrderedSame)
- linphone_core_set_media_encryption(lc, LinphoneMediaEncryptionDTLS);
- else
- linphone_core_set_media_encryption(lc, LinphoneMediaEncryptionNone);
+ [[LinphoneManager instance] configureVbrCodecs];
- NSString* stun_server = [self stringForKey:@"stun_preference"];
- if ([stun_server length] > 0){
- linphone_core_set_stun_server(lc, [stun_server UTF8String]);
- BOOL ice_preference = [self boolForKey:@"ice_preference"];
- if(ice_preference) {
- linphone_core_set_firewall_policy(lc, LinphonePolicyUseIce);
- } else {
- linphone_core_set_firewall_policy(lc, LinphonePolicyUseStun);
+ NSString *au_device = @"AU: Audio Unit Receiver";
+ if (!voice_processing) {
+ au_device = @"AU: Audio Unit NoVoiceProc";
}
- } else {
- linphone_core_set_stun_server(lc, NULL);
- linphone_core_set_firewall_policy(lc, LinphonePolicyNoFirewall);
+ linphone_core_set_capture_device(lc, [au_device UTF8String]);
+ linphone_core_set_playback_device(lc, [au_device UTF8String]);
}
- LinphoneVideoPolicy policy;
- policy.automatically_accept = [self boolForKey:@"accept_video_preference"];
- policy.automatically_initiate = [self boolForKey:@"start_video_preference"];
- linphone_core_set_video_policy(lc, &policy);
- linphone_core_enable_self_view(lc, [self boolForKey:@"self_video_preference"]);
- BOOL preview_preference=[self boolForKey:@"preview_preference"];
- lp_config_set_int(config, LINPHONERC_APPLICATION_KEY, "preview_preference", preview_preference);
- MSVideoSize vsize;
- int bw;
- switch ([self integerForKey:@"video_preferred_size_preference"]) {
+ // video section
+ {
+ [self synchronizeCodecs:linphone_core_get_video_codecs(lc)];
+
+ LinphoneVideoPolicy policy;
+ policy.automatically_initiate = [self boolForKey:@"start_video_preference"];
+ policy.automatically_accept = [self boolForKey:@"accept_video_preference"];
+ linphone_core_set_video_policy(lc, &policy);
+ linphone_core_enable_self_view(lc, [self boolForKey:@"self_video_preference"]);
+ BOOL preview_preference = [self boolForKey:@"preview_preference"];
+ [lm lpConfigSetInt:preview_preference forKey:@"preview_preference"];
+
+ NSString *videoPreset = [self stringForKey:@"video_preset_preference"];
+ linphone_core_set_video_preset(lc, [videoPreset UTF8String]);
+ int bw;
+ MSVideoSize vsize;
+ switch ([self integerForKey:@"video_preferred_size_preference"]) {
case 0:
MS_VIDEO_SIZE_ASSIGN(vsize, 720P);
// 128 = margin for audio, the BW includes both video and audio
@@ -604,131 +626,164 @@ extern void linphone_iphone_log_handler(int lev, const char *fmt, va_list args);
MS_VIDEO_SIZE_ASSIGN(vsize, VGA);
// no margin for VGA or QVGA, because video encoders can encode the
// target resulution in less than the asked bandwidth
- bw = 512;
+ bw = 660;
break;
case 2:
default:
MS_VIDEO_SIZE_ASSIGN(vsize, QVGA);
bw = 380;
break;
- }
- linphone_core_set_preferred_video_size(lc, vsize);
- [self setInteger: bw forKey:@"upload_bandwidth_preference"];
- [self setInteger: bw forKey:@"download_bandwidth_preference"];
-
- // Primary contact
- NSString* displayname = [self stringForKey:@"primary_displayname_preference"];
- NSString* username = [self stringForKey:@"primary_username_preference"];
- LinphoneAddress *parsed = linphone_core_get_primary_contact_parsed(lc);
- if(parsed != NULL) {
- linphone_address_set_display_name(parsed,[displayname cStringUsingEncoding:[NSString defaultCStringEncoding]]);
- linphone_address_set_username(parsed,[username cStringUsingEncoding:[NSString defaultCStringEncoding]]);
- char *contact = linphone_address_as_string(parsed);
- linphone_core_set_primary_contact(lc, contact);
- ms_free(contact);
- linphone_address_destroy(parsed);
+ }
+ linphone_core_set_preferred_video_size(lc, vsize);
+ if (![videoPreset isEqualToString:@"custom"]) {
+ [self setInteger:0 forKey:@"video_preferred_fps_preference"];
+ [self setInteger:bw forKey:@"download_bandwidth_preference"];
+ }
+ linphone_core_set_preferred_framerate(lc, [self integerForKey:@"video_preferred_fps_preference"]);
+ linphone_core_set_download_bandwidth(lc, [self integerForKey:@"download_bandwidth_preference"]);
}
-
- // Audio & Video Port
+ // call section
{
- NSString *audio_port_preference = [self stringForKey:@"audio_port_preference"];
- int minPort, maxPort;
- [LinphoneCoreSettingsStore parsePortRange:audio_port_preference minPort:&minPort maxPort:&maxPort];
- linphone_core_set_audio_port_range(lc, minPort, maxPort);
+ linphone_core_set_use_rfc2833_for_dtmf(lc, [self boolForKey:@"rfc_dtmf_preference"]);
+ linphone_core_set_use_info_for_dtmf(lc, [self boolForKey:@"sipinfo_dtmf_preference"]);
+ linphone_core_set_inc_timeout(lc, [self integerForKey:@"incoming_call_timeout_preference"]);
+ linphone_core_set_in_call_timeout(lc, [self integerForKey:@"in_call_timeout_preference"]);
+ [lm lpConfigSetString:[self stringForKey:@"voice_mail_uri_preference"] forKey:@"voice_mail_uri"];
+ [lm lpConfigSetBool:[self boolForKey:@"repeat_call_notification_preference"]
+ forKey:@"repeat_call_notification"];
}
+
+ // network section
{
- NSString *video_port_preference = [self stringForKey:@"video_port_preference"];
- int minPort, maxPort;
- [LinphoneCoreSettingsStore parsePortRange:video_port_preference minPort:&minPort maxPort:&maxPort];
- linphone_core_set_video_port_range(lc, minPort, maxPort);
- }
+ BOOL edgeOpt = [self boolForKey:@"edge_opt_preference"];
+ [lm lpConfigSetInt:edgeOpt forKey:@"edge_opt_preference"];
- int upload_bandwidth = [self integerForKey:@"upload_bandwidth_preference"];
- linphone_core_set_upload_bandwidth(lc, upload_bandwidth);
-
- int download_bandwidth = [self integerForKey:@"download_bandwidth_preference"];
- linphone_core_set_download_bandwidth(lc, download_bandwidth);
-
- float playback_gain = [self floatForKey:@"playback_gain_preference"];
- linphone_core_set_playback_gain_db(lc, playback_gain);
-
- float mic_gain = [self floatForKey:@"microphone_gain_preference"];
- linphone_core_set_mic_gain_db(lc, mic_gain);
-
- UIDevice* device = [UIDevice currentDevice];
- bool backgroundSupported = false;
- if ([device respondsToSelector:@selector(isMultitaskingSupported)])
- backgroundSupported = [device isMultitaskingSupported];
- BOOL isbackgroundModeEnabled;
- if (backgroundSupported) {
- isbackgroundModeEnabled = [self boolForKey:@"backgroundmode_preference"];
- } else {
- isbackgroundModeEnabled = false;
- }
-
- lp_config_set_int(config, LINPHONERC_APPLICATION_KEY, "backgroundmode_preference", isbackgroundModeEnabled);
- lp_config_set_int(config, LINPHONERC_APPLICATION_KEY, "start_at_boot_preference", [self boolForKey:@"start_at_boot_preference"]);
- lp_config_set_int(config, LINPHONERC_APPLICATION_KEY, "autoanswer_notif_preference", [self boolForKey:@"autoanswer_notif_preference"]);
- lp_config_set_int(config, LINPHONERC_APPLICATION_KEY, "advanced_account_preference", [self boolForKey:@"advanced_account_preference"]);
-
- BOOL firstloginview = [self boolForKey:@"enable_first_login_view_preference"];
- lp_config_set_int(config, LINPHONERC_APPLICATION_KEY, "enable_first_login_view_preference", firstloginview);
-
- BOOL edgeOpt = [self boolForKey:@"edge_opt_preference"];
- lp_config_set_int(config, LINPHONERC_APPLICATION_KEY, "edge_opt_preference", edgeOpt);
-
- BOOL debugmode = [self boolForKey:@"debugenable_preference"];
- lp_config_set_int(config, LINPHONERC_APPLICATION_KEY, "debugenable_preference", debugmode);
- [[LinphoneManager instance] setLogsEnabled:debugmode];
-
- BOOL animations = [self boolForKey:@"animations_preference"];
- lp_config_set_int(config, LINPHONERC_APPLICATION_KEY, "animations_preference", animations);
-
- BOOL wifiOnly = [self boolForKey:@"wifi_only_preference"];
- lp_config_set_int(config, LINPHONERC_APPLICATION_KEY, "wifi_only_preference", wifiOnly);
- if([self valueChangedForKey:@"wifi_only_preference"]) {
- [[LinphoneManager instance] setupNetworkReachabilityCallback];
- }
-
- NSString* sharing_server = [self stringForKey:@"sharing_server_preference"];
- [[LinphoneManager instance] lpConfigSetString:sharing_server forKey:@"sharing_server_preference"];
-
-
- //Tunnel
- if (linphone_core_tunnel_available()){
- NSString* lTunnelPrefMode = [self stringForKey:@"tunnel_mode_preference"];
- NSString* lTunnelPrefAddress = [self stringForKey:@"tunnel_address_preference"];
- int lTunnelPrefPort = [self integerForKey:@"tunnel_port_preference"];
- LinphoneTunnel *tunnel = linphone_core_get_tunnel([LinphoneManager getLc]);
- TunnelMode mode = tunnel_off;
- int lTunnelPort = 443;
- if (lTunnelPrefPort) {
- lTunnelPort = lTunnelPrefPort;
+ BOOL wifiOnly = [self boolForKey:@"wifi_only_preference"];
+ [lm lpConfigSetInt:wifiOnly forKey:@"wifi_only_preference"];
+ if ([self valueChangedForKey:@"wifi_only_preference"]) {
+ [[LinphoneManager instance] setupNetworkReachabilityCallback];
}
- linphone_tunnel_clean_servers(tunnel);
- if (lTunnelPrefAddress && [lTunnelPrefAddress length]) {
- LinphoneTunnelConfig *ltc = linphone_tunnel_config_new();
- linphone_tunnel_config_set_host(ltc, [lTunnelPrefAddress UTF8String]);
- linphone_tunnel_config_set_port(ltc, lTunnelPort);
- linphone_tunnel_add_server(tunnel, ltc);
-
- if ([lTunnelPrefMode isEqualToString:@"off"]) {
- mode = tunnel_off;
- } else if ([lTunnelPrefMode isEqualToString:@"on"]) {
- mode = tunnel_on;
- } else if ([lTunnelPrefMode isEqualToString:@"wwan"]) {
- mode = tunnel_wwan;
- } else if ([lTunnelPrefMode isEqualToString:@"auto"]) {
- mode = tunnel_auto;
+ NSString *stun_server = [self stringForKey:@"stun_preference"];
+ if ([stun_server length] > 0) {
+ linphone_core_set_stun_server(lc, [stun_server UTF8String]);
+ BOOL ice_preference = [self boolForKey:@"ice_preference"];
+ if (ice_preference) {
+ linphone_core_set_firewall_policy(lc, LinphonePolicyUseIce);
} else {
- LOGE(@"Unexpected tunnel mode [%s]",[lTunnelPrefMode cStringUsingEncoding:[NSString defaultCStringEncoding]]);
+ linphone_core_set_firewall_policy(lc, LinphonePolicyUseStun);
}
+ } else {
+ linphone_core_set_stun_server(lc, NULL);
+ linphone_core_set_firewall_policy(lc, LinphonePolicyNoFirewall);
}
- lp_config_set_string(linphone_core_get_config(lc), LINPHONERC_APPLICATION_KEY, "tunnel_mode_preference", [lTunnelPrefMode UTF8String]);
- [[LinphoneManager instance] setTunnelMode:mode];
+ {
+ NSString *audio_port_preference = [self stringForKey:@"audio_port_preference"];
+ int minPort, maxPort;
+ [LinphoneCoreSettingsStore parsePortRange:audio_port_preference minPort:&minPort maxPort:&maxPort];
+ linphone_core_set_audio_port_range(lc, minPort, maxPort);
+ }
+ {
+ NSString *video_port_preference = [self stringForKey:@"video_port_preference"];
+ int minPort, maxPort;
+ [LinphoneCoreSettingsStore parsePortRange:video_port_preference minPort:&minPort maxPort:&maxPort];
+ linphone_core_set_video_port_range(lc, minPort, maxPort);
+ }
+
+ NSString *menc = [self stringForKey:@"media_encryption_preference"];
+ if (menc && [menc compare:@"SRTP"] == NSOrderedSame)
+ linphone_core_set_media_encryption(lc, LinphoneMediaEncryptionSRTP);
+ else if (menc && [menc compare:@"ZRTP"] == NSOrderedSame)
+ linphone_core_set_media_encryption(lc, LinphoneMediaEncryptionZRTP);
+ else if (menc && [menc compare:@"DTLS"] == NSOrderedSame)
+ linphone_core_set_media_encryption(lc, LinphoneMediaEncryptionDTLS);
+ else
+ linphone_core_set_media_encryption(lc, LinphoneMediaEncryptionNone);
+
+ linphone_core_enable_adaptive_rate_control(lc, [self boolForKey:@"adaptive_rate_control_preference"]);
+ linphone_core_set_adaptive_rate_algorithm(lc, [[self stringForKey:@"adaptive_rate_algorithm_preference"]
+ cStringUsingEncoding:[NSString defaultCStringEncoding]]);
+ }
+
+ // tunnel section
+ {
+ if (linphone_core_tunnel_available()) {
+ NSString *lTunnelPrefMode = [self stringForKey:@"tunnel_mode_preference"];
+ NSString *lTunnelPrefAddress = [self stringForKey:@"tunnel_address_preference"];
+ int lTunnelPrefPort = [self integerForKey:@"tunnel_port_preference"];
+ LinphoneTunnel *tunnel = linphone_core_get_tunnel([LinphoneManager getLc]);
+ TunnelMode mode = tunnel_off;
+ int lTunnelPort = 443;
+ if (lTunnelPrefPort) {
+ lTunnelPort = lTunnelPrefPort;
+ }
+
+ linphone_tunnel_clean_servers(tunnel);
+ if (lTunnelPrefAddress && [lTunnelPrefAddress length]) {
+ LinphoneTunnelConfig *ltc = linphone_tunnel_config_new();
+ linphone_tunnel_config_set_host(ltc, [lTunnelPrefAddress UTF8String]);
+ linphone_tunnel_config_set_port(ltc, lTunnelPort);
+ linphone_tunnel_add_server(tunnel, ltc);
+
+ if ([lTunnelPrefMode isEqualToString:@"off"]) {
+ mode = tunnel_off;
+ } else if ([lTunnelPrefMode isEqualToString:@"on"]) {
+ mode = tunnel_on;
+ } else if ([lTunnelPrefMode isEqualToString:@"wwan"]) {
+ mode = tunnel_wwan;
+ } else if ([lTunnelPrefMode isEqualToString:@"auto"]) {
+ mode = tunnel_auto;
+ } else {
+ LOGE(@"Unexpected tunnel mode [%s]",
+ [lTunnelPrefMode cStringUsingEncoding:[NSString defaultCStringEncoding]]);
+ }
+ }
+
+ [lm lpConfigSetString:lTunnelPrefMode forKey:@"tunnel_mode_preference"];
+ [[LinphoneManager instance] setTunnelMode:mode];
+ }
+ }
+
+ // advanced section
+ {
+ BOOL debugmode = [self boolForKey:@"debugenable_preference"];
+ [lm lpConfigSetInt:debugmode forKey:@"debugenable_preference"];
+ [[LinphoneManager instance] setLogsEnabled:debugmode];
+
+ BOOL animations = [self boolForKey:@"animations_preference"];
+ [lm lpConfigSetInt:animations forKey:@"animations_preference"];
+
+ UIDevice *device = [UIDevice currentDevice];
+ bool backgroundSupported =
+ [device respondsToSelector:@selector(isMultitaskingSupported)] && [device isMultitaskingSupported];
+ BOOL isbackgroundModeEnabled = backgroundSupported && [self boolForKey:@"backgroundmode_preference"];
+ [lm lpConfigSetInt:isbackgroundModeEnabled forKey:@"backgroundmode_preference"];
+
+ [lm lpConfigSetInt:[self integerForKey:@"start_at_boot_preference"] forKey:@"start_at_boot_preference"];
+ [lm lpConfigSetInt:[self integerForKey:@"autoanswer_notif_preference"] forKey:@"autoanswer_notif_preference"];
+
+ BOOL firstloginview = [self boolForKey:@"enable_first_login_view_preference"];
+ [lm lpConfigSetInt:firstloginview forKey:@"enable_first_login_view_preference"];
+
+ NSString *displayname = [self stringForKey:@"primary_displayname_preference"];
+ NSString *username = [self stringForKey:@"primary_username_preference"];
+ LinphoneAddress *parsed = linphone_core_get_primary_contact_parsed(lc);
+ if (parsed != NULL) {
+ linphone_address_set_display_name(parsed,
+ [displayname cStringUsingEncoding:[NSString defaultCStringEncoding]]);
+ linphone_address_set_username(parsed, [username cStringUsingEncoding:[NSString defaultCStringEncoding]]);
+ char *contact = linphone_address_as_string(parsed);
+ linphone_core_set_primary_contact(lc, contact);
+ ms_free(contact);
+ linphone_address_destroy(parsed);
+ }
+
+ [lm lpConfigSetInt:[self integerForKey:@"advanced_account_preference"] forKey:@"advanced_account_preference"];
+
+ NSString *sharing_server = [self stringForKey:@"sharing_server_preference"];
+ [[LinphoneManager instance] lpConfigSetString:sharing_server forKey:@"sharing_server_preference"];
}
changedDict = [[NSMutableDictionary alloc] init];
diff --git a/Classes/LinphoneManager.h b/Classes/LinphoneManager.h
index 7daa5e605..5ad82797f 100644
--- a/Classes/LinphoneManager.h
+++ b/Classes/LinphoneManager.h
@@ -36,7 +36,7 @@
#include "linphone/linphonecore.h"
#include "linphone/linphone_tunnel.h"
-extern const char *const LINPHONERC_APPLICATION_KEY;
+extern NSString *const LINPHONERC_APPLICATION_KEY;
extern NSString *const kLinphoneCoreUpdate;
extern NSString *const kLinphoneDisplayStatusUpdate;
@@ -52,6 +52,8 @@ extern NSString *const kLinphoneBluetoothAvailabilityUpdate;
extern NSString *const kLinphoneConfiguringStateUpdate;
extern NSString *const kLinphoneGlobalStateUpdate;
extern NSString *const kLinphoneNotifyReceived;
+extern NSString *const kLinphoneFileTransferSendUpdate;
+extern NSString *const kLinphoneFileTransferRecvUpdate;
typedef enum _NetworkType {
network_none = 0,
@@ -167,18 +169,26 @@ typedef struct _LinphoneManagerSounds {
+(void)setValueInMessageAppData:(id)value forKey:(NSString*)key inMessage:(LinphoneChatMessage*)msg;
- (void)lpConfigSetString:(NSString*)value forKey:(NSString*)key;
-- (NSString*)lpConfigStringForKey:(NSString*)key;
-- (NSString*)lpConfigStringForKey:(NSString*)key withDefault:(NSString*)value;
- (void)lpConfigSetString:(NSString*)value forKey:(NSString*)key forSection:(NSString*)section;
+- (NSString *)lpConfigStringForKey:(NSString *)key;
- (NSString*)lpConfigStringForKey:(NSString*)key forSection:(NSString*)section;
-- (void)lpConfigSetInt:(NSInteger)value forKey:(NSString*)key;
-- (NSInteger)lpConfigIntForKey:(NSString*)key;
-- (void)lpConfigSetInt:(NSInteger)value forKey:(NSString*)key forSection:(NSString*)section;
-- (NSInteger)lpConfigIntForKey:(NSString*)key forSection:(NSString*)section;
+- (NSString *)lpConfigStringForKey:(NSString *)key withDefault:(NSString *)value;
+- (NSString *)lpConfigStringForKey:(NSString *)key forSection:(NSString *)section withDefault:(NSString *)value;
+
+- (void)lpConfigSetInt:(int)value forKey:(NSString *)key;
+- (void)lpConfigSetInt:(int)value forKey:(NSString *)key forSection:(NSString *)section;
+- (int)lpConfigIntForKey:(NSString *)key;
+- (int)lpConfigIntForKey:(NSString *)key forSection:(NSString *)section;
+- (int)lpConfigIntForKey:(NSString *)key withDefault:(int)value;
+- (int)lpConfigIntForKey:(NSString *)key forSection:(NSString *)section withDefault:(int)value;
+
- (void)lpConfigSetBool:(BOOL)value forKey:(NSString*)key;
-- (BOOL)lpConfigBoolForKey:(NSString*)key;
- (void)lpConfigSetBool:(BOOL)value forKey:(NSString*)key forSection:(NSString*)section;
+- (BOOL)lpConfigBoolForKey:(NSString *)key;
- (BOOL)lpConfigBoolForKey:(NSString*)key forSection:(NSString*)section;
+- (BOOL)lpConfigBoolForKey:(NSString *)key withDefault:(BOOL)value;
+- (BOOL)lpConfigBoolForKey:(NSString *)key forSection:(NSString *)section withDefault:(BOOL)value;
+
- (void)silentPushFailed:(NSTimer*)timer;
@property (readonly) BOOL isTesting;
@@ -203,5 +213,6 @@ typedef struct _LinphoneManagerSounds {
@property (readonly) BOOL wasRemoteProvisioned;
@property (readonly) LpConfig *configDb;
@property (readonly) InAppProductsManager *iapManager;
-@end
+@property(strong, nonatomic) NSMutableArray *fileTransferDelegates;
+@end
\ No newline at end of file
diff --git a/Classes/LinphoneManager.m b/Classes/LinphoneManager.m
index fb440ffb9..949bc6ec8 100644
--- a/Classes/LinphoneManager.m
+++ b/Classes/LinphoneManager.m
@@ -52,7 +52,7 @@ static void audioRouteChangeListenerCallback (
static LinphoneCore* theLinphoneCore = nil;
static LinphoneManager* theLinphoneManager = nil;
-const char *const LINPHONERC_APPLICATION_KEY = "app";
+NSString *const LINPHONERC_APPLICATION_KEY = @"app";
NSString *const kLinphoneCoreUpdate = @"LinphoneCoreUpdate";
NSString *const kLinphoneDisplayStatusUpdate = @"LinphoneDisplayStatusUpdate";
@@ -68,7 +68,8 @@ NSString *const kLinphoneBluetoothAvailabilityUpdate = @"LinphoneBluetoothAvaila
NSString *const kLinphoneConfiguringStateUpdate = @"LinphoneConfiguringStateUpdate";
NSString *const kLinphoneGlobalStateUpdate = @"LinphoneGlobalStateUpdate";
NSString *const kLinphoneNotifyReceived = @"LinphoneNotifyReceived";
-
+NSString *const kLinphoneFileTransferSendUpdate = @"LinphoneFileTransferSendUpdate";
+NSString *const kLinphoneFileTransferRecvUpdate = @"LinphoneFileTransferRecvUpdate";
const int kLinphoneAudioVbrCodecDefaultBitrate=36; /*you can override this from linphonerc or linphonerc-factory*/
@@ -145,10 +146,10 @@ struct codec_name_pref_table codec_pref_table[]={
{ "mp4v-es", 90000, "mp4v-es_preference"},
{ "h264", 90000, "h264_preference"},
{ "vp8", 90000, "vp8_preference"},
- { "mpeg4-generic", 16000, "aaceld_16k_preference"},
- { "mpeg4-generic", 22050, "aaceld_22k_preference"},
- { "mpeg4-generic", 32000, "aaceld_32k_preference"},
- { "mpeg4-generic", 44100, "aaceld_44k_preference"},
+ { "mpeg4-generic", 16000, "aaceld_16k_preference"},
+ { "mpeg4-generic", 22050, "aaceld_22k_preference"},
+ { "mpeg4-generic", 32000, "aaceld_32k_preference"},
+ { "mpeg4-generic", 44100, "aaceld_44k_preference"},
{ "mpeg4-generic", 48000, "aaceld_48k_preference"},
{ "opus", 48000, "opus_preference"},
{ NULL,0,Nil }
@@ -194,9 +195,9 @@ struct codec_name_pref_table codec_pref_table[]={
}
+ (BOOL)isRunningTests {
- NSDictionary *environment = [[NSProcessInfo processInfo] environment];
- NSString *injectBundle = environment[@"XCInjectBundle"];
- return [[injectBundle pathExtension] isEqualToString:@"xctest"];
+ NSDictionary *environment = [[NSProcessInfo processInfo] environment];
+ NSString *injectBundle = environment[@"XCInjectBundle"];
+ return [[injectBundle pathExtension] isEqualToString:@"xctest"];
}
+ (BOOL)isNotIphone3G
@@ -244,12 +245,12 @@ struct codec_name_pref_table codec_pref_table[]={
#endif
+ (BOOL)langageDirectionIsRTL {
- static NSLocaleLanguageDirection dir = NSLocaleLanguageDirectionLeftToRight;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- dir = [NSLocale characterDirectionForLanguage:[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]];
- });
- return dir == NSLocaleLanguageDirectionRightToLeft;
+ static NSLocaleLanguageDirection dir = NSLocaleLanguageDirectionLeftToRight;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ dir = [NSLocale characterDirectionForLanguage:[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]];
+ });
+ return dir == NSLocaleLanguageDirectionRightToLeft;
}
#pragma mark - Lifecycle Functions
@@ -262,17 +263,18 @@ struct codec_name_pref_table codec_pref_table[]={
LOGE(@"cannot register route change handler [%ld]",lStatus);
}
- NSString *path = [[NSBundle mainBundle] pathForResource:@"msg" ofType:@"wav"];
- self.messagePlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:path] error:nil];
+ NSString *path = [[NSBundle mainBundle] pathForResource:@"msg" ofType:@"wav"];
+ self.messagePlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:path] error:nil];
- sounds.vibrate = kSystemSoundID_Vibrate;
+ sounds.vibrate = kSystemSoundID_Vibrate;
- logs = [[NSMutableArray alloc] init];
+ logs = [[NSMutableArray alloc] init];
database = NULL;
speakerEnabled = FALSE;
bluetoothEnabled = FALSE;
tunnelMode = FALSE;
+ _fileTransferDelegates = [[NSMutableArray alloc] init];
pushCallIDs = [[NSMutableArray alloc] init ];
photoLibrary = [[ALAssetsLibrary alloc] init];
@@ -283,7 +285,7 @@ struct codec_name_pref_table codec_pref_table[]={
[self overrideDefaultSettings];
//set default values for first boot
- if (lp_config_get_string(configDb,LINPHONERC_APPLICATION_KEY,"debugenable_preference",NULL)==NULL){
+ if ([self lpConfigStringForKey:@"debugenable_preference"] == nil) {
#ifdef DEBUG
[self lpConfigSetBool:TRUE forKey:@"debugenable_preference"];
#else
@@ -447,11 +449,11 @@ exit_dbmigration:
}
- (void)migrateFromUserPrefs {
- static const char* migration_flag = "userpref_migration_done";
+ static NSString *migration_flag = @"userpref_migration_done";
if( configDb == nil ) return;
- if( lp_config_get_int(configDb, LINPHONERC_APPLICATION_KEY, migration_flag, 0) ){
+ if ([self lpConfigIntForKey:migration_flag withDefault:0]) {
LOGI(@"UserPrefs migration already performed, skip");
return;
}
@@ -468,12 +470,12 @@ exit_dbmigration:
for( NSString* userpref in values ){
if( [defaults_keys containsObject:userpref] ){
LOGI(@"Migrating %@ from user preferences: %d", userpref, [[defaults objectForKey:userpref] boolValue]);
- lp_config_set_int(configDb, LINPHONERC_APPLICATION_KEY, [userpref UTF8String], [[defaults objectForKey:userpref] boolValue]);
+ [self lpConfigSetBool:[[defaults objectForKey:userpref] boolValue] forKey:userpref];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:userpref];
shouldSync = TRUE;
- } else if ( lp_config_get_string(configDb, LINPHONERC_APPLICATION_KEY, [userpref UTF8String], NULL) == NULL ){
+ } else if ([self lpConfigStringForKey:userpref] == nil) {
// no default value found in our linphonerc, we need to add them
- lp_config_set_int(configDb, LINPHONERC_APPLICATION_KEY, [userpref UTF8String], [[values objectForKey:userpref] boolValue]);
+ [self lpConfigSetBool:[[values objectForKey:userpref] boolValue] forKey:userpref];
}
}
@@ -482,7 +484,7 @@ exit_dbmigration:
[[NSUserDefaults standardUserDefaults] synchronize];
}
// don't get back here in the future
- lp_config_set_int(configDb, LINPHONERC_APPLICATION_KEY, migration_flag, 1);
+ [self lpConfigSetBool:YES forKey:migration_flag];
}
@@ -543,9 +545,9 @@ static void linphone_iphone_log(struct _LinphoneCore * lc, const char * message)
- (void)displayStatus:(NSString*) message {
// Post event
- [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneDisplayStatusUpdate
- object:self
- userInfo:@{@"message":message}];
+ [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneDisplayStatusUpdate
+ object:self
+ userInfo:@{@"message":message}];
}
@@ -639,14 +641,15 @@ static void linphone_iphone_display_status(struct _LinphoneCore * lc, const char
data->notification = [[UILocalNotification alloc] init];
if (data->notification) {
- // iOS8 doesn't need the timer trick for the local notification.
- if( [[UIDevice currentDevice].systemVersion floatValue] >= 8){
- data->notification.soundName = @"ring.caf";
- data->notification.category = @"incoming_call";
- } else {
- data->notification.soundName = @"shortring.caf";
- data->timer = [NSTimer scheduledTimerWithTimeInterval:4.0 target:self selector:@selector(localNotifContinue:) userInfo:data->notification repeats:TRUE];
- }
+ // iOS8 doesn't need the timer trick for the local notification.
+ if ([[UIDevice currentDevice].systemVersion floatValue] >= 8 &&
+ [self lpConfigBoolForKey:@"repeat_call_notification"] == NO) {
+ data->notification.soundName = @"ring.caf";
+ data->notification.category = @"incoming_call";
+ } else {
+ data->notification.soundName = @"shortring.caf";
+ data->timer = [NSTimer scheduledTimerWithTimeInterval:4.0 target:self selector:@selector(localNotifContinue:) userInfo:data->notification repeats:TRUE];
+ }
data->notification.repeatInterval = 0;
@@ -664,9 +667,9 @@ static void linphone_iphone_display_status(struct _LinphoneCore * lc, const char
incallBgTask=0;
}];
- if( data->timer ){
- [[NSRunLoop currentRunLoop] addTimer:data->timer forMode:NSRunLoopCommonModes];
- }
+ if( data->timer ){
+ [[NSRunLoop currentRunLoop] addTimer:data->timer forMode:NSRunLoopCommonModes];
+ }
}
}
@@ -740,9 +743,9 @@ static void linphone_iphone_display_status(struct _LinphoneCore * lc, const char
[self setupGSMInteraction];
}
// Post event
- NSDictionary* dict = @{@"call": [NSValue valueWithPointer:call],
- @"state": [NSNumber numberWithInt:state],
- @"message":[NSString stringWithUTF8String:message]};
+ NSDictionary* dict = @{@"call": [NSValue valueWithPointer:call],
+ @"state": [NSNumber numberWithInt:state],
+ @"message":[NSString stringWithUTF8String:message]};
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneCallUpdate object:self userInfo:dict];
}
@@ -845,12 +848,12 @@ static void linphone_iphone_registration_state(LinphoneCore *lc, LinphoneProxyCo
silentPushCompletion(UIBackgroundFetchResultNewData);
silentPushCompletion = nil;
}
- const LinphoneAddress* remoteAddress = linphone_chat_message_get_from_address(msg);
- char* c_address = linphone_address_as_string_uri_only(remoteAddress);
- NSString* address = [NSString stringWithUTF8String:c_address];
- NSString* remote_uri = [NSString stringWithUTF8String:c_address];
- const char* call_id = linphone_chat_message_get_custom_header(msg, "Call-ID");
- NSString* callID = [NSString stringWithUTF8String:call_id];
+ const LinphoneAddress* remoteAddress = linphone_chat_message_get_from_address(msg);
+ char* c_address = linphone_address_as_string_uri_only(remoteAddress);
+ NSString* address = [NSString stringWithUTF8String:c_address];
+ NSString* remote_uri = [NSString stringWithUTF8String:c_address];
+ const char* call_id = linphone_chat_message_get_custom_header(msg, "Call-ID");
+ NSString* callID = [NSString stringWithUTF8String:call_id];
ms_free(c_address);
@@ -874,9 +877,9 @@ static void linphone_iphone_registration_state(LinphoneCore *lc, LinphoneProxyCo
UILocalNotification* notif = [[UILocalNotification alloc] init];
if (notif) {
notif.repeatInterval = 0;
- if( [[UIDevice currentDevice].systemVersion floatValue] >= 8){
- notif.category = @"incoming_msg";
- }
+ if( [[UIDevice currentDevice].systemVersion floatValue] >= 8){
+ notif.category = @"incoming_msg";
+ }
notif.alertBody = [NSString stringWithFormat:NSLocalizedString(@"IM_MSG",nil), address];
notif.alertAction = NSLocalizedString(@"Show", nil);
notif.soundName = @"msg.caf";
@@ -936,58 +939,58 @@ static void linphone_iphone_is_composing_received(LinphoneCore *lc, LinphoneChat
}
+ (void)kickOffNetworkConnection {
- static BOOL in_progress = FALSE;
- if( in_progress ){
- LOGW(@"Connection kickoff already in progress");
- return;
- }
- in_progress = TRUE;
+ static BOOL in_progress = FALSE;
+ if( in_progress ){
+ LOGW(@"Connection kickoff already in progress");
+ return;
+ }
+ in_progress = TRUE;
/* start a new thread to avoid blocking the main ui in case of peer host failure */
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- static int sleep_us = 10000;
- static int timeout_s = 5;
- BOOL timeout_reached = FALSE;
- int loop = 0;
+ static int sleep_us = 10000;
+ static int timeout_s = 5;
+ BOOL timeout_reached = FALSE;
+ int loop = 0;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.0.200"/*"linphone.org"*/, 15000, nil, &writeStream);
BOOL res = CFWriteStreamOpen (writeStream);
const char* buff="hello";
- time_t start = time(NULL);
- time_t loop_time;
+ time_t start = time(NULL);
+ time_t loop_time;
- if( res == FALSE ){
- LOGI(@"Could not open write stream, backing off");
- CFRelease(writeStream);
- in_progress = FALSE;
- return;
- }
+ if( res == FALSE ){
+ LOGI(@"Could not open write stream, backing off");
+ CFRelease(writeStream);
+ in_progress = FALSE;
+ return;
+ }
- // check stream status and handle timeout
- CFStreamStatus status = CFWriteStreamGetStatus(writeStream);
- while (status != kCFStreamStatusOpen && status != kCFStreamStatusError ) {
- usleep(sleep_us);
- status = CFWriteStreamGetStatus(writeStream);
- loop_time = time(NULL);
- if( loop_time - start >= timeout_s){
- timeout_reached = TRUE;
- break;
- }
- loop++;
- }
+ // check stream status and handle timeout
+ CFStreamStatus status = CFWriteStreamGetStatus(writeStream);
+ while (status != kCFStreamStatusOpen && status != kCFStreamStatusError ) {
+ usleep(sleep_us);
+ status = CFWriteStreamGetStatus(writeStream);
+ loop_time = time(NULL);
+ if( loop_time - start >= timeout_s){
+ timeout_reached = TRUE;
+ break;
+ }
+ loop++;
+ }
- if (status == kCFStreamStatusOpen ) {
- CFWriteStreamWrite (writeStream,(const UInt8*)buff,strlen(buff));
- } else if( !timeout_reached ){
- CFErrorRef error = CFWriteStreamCopyError(writeStream);
- LOGD(@"CFStreamError: %@", error);
- CFRelease(error);
- } else if( timeout_reached ){
- LOGI(@"CFStream timeout reached");
- }
+ if (status == kCFStreamStatusOpen ) {
+ CFWriteStreamWrite (writeStream,(const UInt8*)buff,strlen(buff));
+ } else if( !timeout_reached ){
+ CFErrorRef error = CFWriteStreamCopyError(writeStream);
+ LOGD(@"CFStreamError: %@", error);
+ CFRelease(error);
+ } else if( timeout_reached ){
+ LOGI(@"CFStream timeout reached");
+ }
CFWriteStreamClose (writeStream);
CFRelease(writeStream);
- in_progress = FALSE;
+ in_progress = FALSE;
});
}
@@ -1046,7 +1049,7 @@ static void networkReachabilityNotification(CFNotificationCenterRef center, void
void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* nilCtx){
showNetworkFlags(flags);
- LinphoneManager* lLinphoneMgr = [LinphoneManager instance];
+ LinphoneManager *lm = [LinphoneManager instance];
SCNetworkReachabilityFlags networkDownFlags=kSCNetworkReachabilityFlagsConnectionRequired |kSCNetworkReachabilityFlagsConnectionOnTraffic | kSCNetworkReachabilityFlagsConnectionOnDemand;
if (theLinphoneCore != nil) {
@@ -1056,30 +1059,28 @@ void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReach
struct NetworkReachabilityContext* ctx = nilCtx ? ((struct NetworkReachabilityContext*)nilCtx) : 0;
if ((flags == 0) || (flags & networkDownFlags)) {
linphone_core_set_network_reachable(theLinphoneCore, false);
- lLinphoneMgr.connectivity = none;
+ lm.connectivity = none;
[LinphoneManager kickOffNetworkConnection];
} else {
LinphoneTunnel *tunnel = linphone_core_get_tunnel([LinphoneManager getLc]);
Connectivity newConnectivity;
- BOOL isWifiOnly = lp_config_get_int(lLinphoneMgr.configDb, LINPHONERC_APPLICATION_KEY, "wifi_only_preference",FALSE);
+ BOOL isWifiOnly = [lm lpConfigBoolForKey:@"wifi_only_preference" withDefault:FALSE];
if (!ctx || ctx->testWWan)
newConnectivity = flags & kSCNetworkReachabilityFlagsIsWWAN ? wwan:wifi;
else
newConnectivity = wifi;
- if (newConnectivity == wwan
- && proxy
- && isWifiOnly
- && (lLinphoneMgr.connectivity == newConnectivity || lLinphoneMgr.connectivity == none)) {
+ if (newConnectivity == wwan && proxy && isWifiOnly &&
+ (lm.connectivity == newConnectivity || lm.connectivity == none)) {
linphone_proxy_config_expires(proxy, 0);
} else if (proxy){
- NSInteger defaultExpire = [[LinphoneManager instance] lpConfigIntForKey:@"default_expires"];
+ NSInteger defaultExpire = [lm lpConfigIntForKey:@"default_expires"];
if (defaultExpire>=0)
linphone_proxy_config_expires(proxy, (int)defaultExpire);
//else keep default value from linphonecore
}
- if (lLinphoneMgr.connectivity != newConnectivity) {
+ if (lm.connectivity != newConnectivity) {
if (tunnel) linphone_tunnel_reconnect(tunnel);
// connectivity has changed
linphone_core_set_network_reachable(theLinphoneCore,false);
@@ -1090,10 +1091,10 @@ void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReach
linphone_core_iterate(theLinphoneCore);
LOGI(@"Network connectivity changed to type [%s]",(newConnectivity==wifi?"wifi":"wwan"));
}
- lLinphoneMgr.connectivity=newConnectivity;
- switch (lLinphoneMgr.tunnelMode) {
+ lm.connectivity = newConnectivity;
+ switch (lm.tunnelMode) {
case tunnel_wwan:
- linphone_tunnel_enable(tunnel,lLinphoneMgr.connectivity == wwan);
+ linphone_tunnel_enable(tunnel, lm.connectivity == wwan);
break;
case tunnel_auto:
linphone_tunnel_auto_detect(tunnel);
@@ -1104,7 +1105,7 @@ void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReach
}
}
if (ctx && ctx->networkStateChanged) {
- (*ctx->networkStateChanged)(lLinphoneMgr.connectivity);
+ (*ctx->networkStateChanged)(lm.connectivity);
}
}
}
@@ -1185,7 +1186,7 @@ void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReach
}
}
-#pragma mark -
+#pragma mark - VTable
static LinphoneCoreVTable linphonec_vtable = {
.show =NULL,
@@ -1208,6 +1209,8 @@ static LinphoneCoreVTable linphonec_vtable = {
.notify_received = linphone_iphone_notify_received
};
+#pragma mark -
+
//scheduling loop
- (void)iterate {
linphone_core_iterate(theLinphoneCore);
@@ -1300,6 +1303,11 @@ static LinphoneCoreVTable linphonec_vtable = {
linphone_core_set_static_picture(theLinphoneCore, imagePath);
}
+ NSString *urlString = [self lpConfigStringForKey:@"sharing_server_preference"];
+ if( urlString ){
+ linphone_core_set_file_transfer_server(theLinphoneCore, [urlString UTF8String]);
+ }
+
/*DETECT cameras*/
frontCamId= backCamId=nil;
char** camlist = (char**)linphone_core_get_video_devices(theLinphoneCore);
@@ -1394,24 +1402,24 @@ static BOOL libStarted = FALSE;
connectivity=none;
- ms_init(); // Need to initialize mediastreamer2 before loading the plugins
+ ms_init(); // Need to initialize mediastreamer2 before loading the plugins
- libmsilbc_init();
+ libmsilbc_init();
#if defined (HAVE_SILK)
- libmssilk_init();
+ libmssilk_init();
#endif
#ifdef HAVE_AMR
- libmsamr_init(); //load amr plugin if present from the liblinphone sdk
+ libmsamr_init(); //load amr plugin if present from the liblinphone sdk
#endif
#ifdef HAVE_X264
- libmsx264_init(); //load x264 plugin if present from the liblinphone sdk
+ libmsx264_init(); //load x264 plugin if present from the liblinphone sdk
#endif
#ifdef HAVE_OPENH264
- libmsopenh264_init(); //load openh264 plugin if present from the liblinphone sdk
+ libmsopenh264_init(); //load openh264 plugin if present from the liblinphone sdk
#endif
#if HAVE_G729
- libmsbcg729_init(); // load g729 plugin
+ libmsbcg729_init(); // load g729 plugin
#endif
linphone_core_set_log_collection_path([[LinphoneManager cacheDirectory] UTF8String]);
@@ -1490,39 +1498,39 @@ static int comp_call_id(const LinphoneCall* call , const char *callid) {
}
- (void)cancelLocalNotifTimerForCallId:(NSString*)callid {
- //first, make sure this callid is not already involved in a call
- MSList* calls = (MSList*)linphone_core_get_calls(theLinphoneCore);
- MSList* call = ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String]);
- if (call != NULL) {
- LinphoneCallAppData* data = (__bridge LinphoneCallAppData *)(linphone_call_get_user_data((LinphoneCall*)call->data));
- if ( data->timer )
- [data->timer invalidate];
- data->timer = nil;
- return;
- }
+ //first, make sure this callid is not already involved in a call
+ MSList* calls = (MSList*)linphone_core_get_calls(theLinphoneCore);
+ MSList* call = ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String]);
+ if (call != NULL) {
+ LinphoneCallAppData* data = (__bridge LinphoneCallAppData *)(linphone_call_get_user_data((LinphoneCall*)call->data));
+ if ( data->timer )
+ [data->timer invalidate];
+ data->timer = nil;
+ return;
+ }
}
- (void)acceptCallForCallId:(NSString*)callid {
- //first, make sure this callid is not already involved in a call
- MSList* calls = (MSList*)linphone_core_get_calls(theLinphoneCore);
- MSList* call = ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String]);
- if (call != NULL) {
- [self acceptCall:(LinphoneCall*)call->data];
- return;
- };
+ //first, make sure this callid is not already involved in a call
+ MSList* calls = (MSList*)linphone_core_get_calls(theLinphoneCore);
+ MSList* call = ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String]);
+ if (call != NULL) {
+ [self acceptCall:(LinphoneCall*)call->data];
+ return;
+ };
}
- (void)addPushCallId:(NSString*) callid {
//first, make sure this callid is not already involved in a call
- MSList* calls = (MSList*)linphone_core_get_calls(theLinphoneCore);
- if (ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String])) {
- LOGW(@"Call id [%@] already handled",callid);
- return;
- };
- if ([pushCallIDs count] > 10 /*max number of pending notif*/)
- [pushCallIDs removeObjectAtIndex:0];
+ MSList* calls = (MSList*)linphone_core_get_calls(theLinphoneCore);
+ if (ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String])) {
+ LOGW(@"Call id [%@] already handled",callid);
+ return;
+ };
+ if ([pushCallIDs count] > 10 /*max number of pending notif*/)
+ [pushCallIDs removeObjectAtIndex:0];
- [pushCallIDs addObject:callid];
+ [pushCallIDs addObject:callid];
}
- (BOOL)popPushCallID:(NSString*) callId {
@@ -1542,11 +1550,11 @@ static int comp_call_id(const LinphoneCall* call , const char *callid) {
}
- (void)playMessageSound {
- BOOL success = [self.messagePlayer play];
- if( !success ){
- LOGE(@"Could not play the message sound");
- }
- AudioServicesPlaySystemSound([LinphoneManager instance].sounds.vibrate);
+ BOOL success = [self.messagePlayer play];
+ if( !success ){
+ LOGE(@"Could not play the message sound");
+ }
+ AudioServicesPlaySystemSound([LinphoneManager instance].sounds.vibrate);
}
static int comp_call_state_paused (const LinphoneCall* call, const void* param) {
@@ -1559,7 +1567,7 @@ static int comp_call_state_paused (const LinphoneCall* call, const void* param)
[[UIApplication sharedApplication] endBackgroundTask:pausedCallBgTask];
}];
LOGI(@"Long running task started, remaining [%g s] because at least one call is paused"
- ,[[UIApplication sharedApplication] backgroundTimeRemaining]);
+ ,[[UIApplication sharedApplication] backgroundTimeRemaining]);
}
- (BOOL)enterBackgroundMode {
LinphoneProxyConfig* proxyCfg;
@@ -1864,18 +1872,18 @@ static void audioRouteChangeListenerCallback (
}
LinphoneCall* call=NULL;
- BOOL addressIsASCII = [address canBeConvertedToEncoding:[NSString defaultCStringEncoding]];
+ BOOL addressIsASCII = [address canBeConvertedToEncoding:[NSString defaultCStringEncoding]];
if ([address length] == 0) return; //just return
- if( !addressIsASCII ){
- UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Invalid SIP address",nil)
- message:NSLocalizedString(@"The address should only contain ASCII data",nil)
- delegate:nil
- cancelButtonTitle:NSLocalizedString(@"Continue",nil)
- otherButtonTitles:nil];
- [error show];
+ if( !addressIsASCII ){
+ UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Invalid SIP address",nil)
+ message:NSLocalizedString(@"The address should only contain ASCII data",nil)
+ delegate:nil
+ cancelButtonTitle:NSLocalizedString(@"Continue",nil)
+ otherButtonTitles:nil];
+ [error show];
- }
+ }
LinphoneAddress* linphoneAddress = linphone_core_interpret_url(theLinphoneCore, [address cStringUsingEncoding:[NSString defaultCStringEncoding]]);
if (linphoneAddress) {
@@ -1901,7 +1909,7 @@ static void audioRouteChangeListenerCallback (
otherButtonTitles:nil];
[error show];
- }
+ }
if (call) {
@@ -1929,16 +1937,16 @@ static void audioRouteChangeListenerCallback (
pushNotificationToken = nil;
}
- if(apushNotificationToken != nil) {
- pushNotificationToken = apushNotificationToken;
- }
- LinphoneProxyConfig *cfg=nil;
- linphone_core_get_default_proxy(theLinphoneCore, &cfg);
- if (cfg ) {
- linphone_proxy_config_edit(cfg);
- [self configurePushTokenForProxyConfig: cfg];
- linphone_proxy_config_done(cfg);
- }
+ if(apushNotificationToken != nil) {
+ pushNotificationToken = apushNotificationToken;
+ }
+ LinphoneProxyConfig *cfg=nil;
+ linphone_core_get_default_proxy(theLinphoneCore, &cfg);
+ if (cfg ) {
+ linphone_proxy_config_edit(cfg);
+ [self configurePushTokenForProxyConfig: cfg];
+ linphone_proxy_config_done(cfg);
+ }
}
- (void)configurePushTokenForProxyConfig:(LinphoneProxyConfig*)proxyCfg{
@@ -1956,10 +1964,10 @@ static void audioRouteChangeListenerCallback (
#else
#define APPMODE_SUFFIX @"prod"
#endif
- NSString *params = [NSString stringWithFormat:@"app-id=%@.%@;pn-type=apple;pn-tok=%@;pn-msg-str=IM_MSG;pn-call-str=IC_MSG;pn-call-snd=ring.caf;pn-msg-snd=msg.caf", [[NSBundle mainBundle] bundleIdentifier],APPMODE_SUFFIX,tokenString];
+ NSString *params = [NSString stringWithFormat:@"app-id=%@.%@;pn-type=apple;pn-tok=%@;pn-msg-str=IM_MSG;pn-call-str=IC_MSG;pn-call-snd=ring.caf;pn-msg-snd=msg.caf", [[NSBundle mainBundle] bundleIdentifier],APPMODE_SUFFIX,tokenString];
- linphone_proxy_config_set_contact_uri_parameters(proxyCfg, [params UTF8String]);
- linphone_proxy_config_set_contact_parameters(proxyCfg, NULL);
+ linphone_proxy_config_set_contact_uri_parameters(proxyCfg, [params UTF8String]);
+ linphone_proxy_config_set_contact_parameters(proxyCfg, NULL);
} else {
// no push token:
linphone_proxy_config_set_contact_uri_parameters(proxyCfg, NULL);
@@ -1990,22 +1998,22 @@ static void audioRouteChangeListenerCallback (
if (! [[NSFileManager defaultManager] fileExistsAtPath:cachePath isDirectory:&isDir] && isDir == NO) {
[[NSFileManager defaultManager] createDirectoryAtPath:cachePath withIntermediateDirectories:NO attributes:nil error:&error];
}
- return cachePath;
+ return cachePath;
}
+ (int)unreadMessageCount {
- int count = 0;
- MSList* rooms = linphone_core_get_chat_rooms([LinphoneManager getLc]);
- MSList* item = rooms;
- while (item) {
- LinphoneChatRoom* room = (LinphoneChatRoom*)item->data;
- if( room ){
- count += linphone_chat_room_get_unread_messages_count(room);
- }
- item = item->next;
- }
+ int count = 0;
+ MSList* rooms = linphone_core_get_chat_rooms([LinphoneManager getLc]);
+ MSList* item = rooms;
+ while (item) {
+ LinphoneChatRoom* room = (LinphoneChatRoom*)item->data;
+ if( room ){
+ count += linphone_chat_room_get_unread_messages_count(room);
+ }
+ item = item->next;
+ }
- return count;
+ return count;
}
+ (BOOL)copyFile:(NSString*)src destination:(NSString*)dst override:(BOOL)override {
@@ -2038,16 +2046,16 @@ static void audioRouteChangeListenerCallback (
- (void)configureVbrCodecs{
PayloadType *pt;
int bitrate=lp_config_get_int(configDb,"audio","codec_bitrate_limit",kLinphoneAudioVbrCodecDefaultBitrate);/*default value is in linphonerc or linphonerc-factory*/
- const MSList *audio_codecs = linphone_core_get_audio_codecs(theLinphoneCore);
- const MSList* codec = audio_codecs;
- while (codec) {
- pt = codec->data;
- if( linphone_core_payload_type_is_vbr(theLinphoneCore, pt) ) {
- linphone_core_set_payload_type_bitrate(theLinphoneCore, pt, bitrate);
- }
+ const MSList *audio_codecs = linphone_core_get_audio_codecs(theLinphoneCore);
+ const MSList* codec = audio_codecs;
+ while (codec) {
+ pt = codec->data;
+ if( linphone_core_payload_type_is_vbr(theLinphoneCore, pt) ) {
+ linphone_core_set_payload_type_bitrate(theLinphoneCore, pt, bitrate);
+ }
- codec = codec->next;
- }
+ codec = codec->next;
+ }
}
-(void)setLogsEnabled:(BOOL)enabled {
@@ -2094,63 +2102,70 @@ static void audioRouteChangeListenerCallback (
#pragma mark - LPConfig Functions
- (void)lpConfigSetString:(NSString*)value forKey:(NSString*)key {
- [self lpConfigSetString:value forKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]];
+ [self lpConfigSetString:value forKey:key forSection:LINPHONERC_APPLICATION_KEY];
}
-
- (void)lpConfigSetString:(NSString*)value forKey:(NSString*)key forSection:(NSString *)section {
if (!key) return;
lp_config_set_string(configDb, [section UTF8String], [key UTF8String], value?[value UTF8String]:NULL);
}
-
- (NSString*)lpConfigStringForKey:(NSString*)key {
- return [self lpConfigStringForKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]];
+ return [self lpConfigStringForKey:key withDefault:nil];
}
- (NSString*)lpConfigStringForKey:(NSString*)key withDefault:(NSString*)defaultValue {
- NSString* value = [self lpConfigStringForKey:key];
- return value?value:defaultValue;
+ return [self lpConfigStringForKey:key forSection:LINPHONERC_APPLICATION_KEY withDefault:defaultValue];
}
-
- (NSString*)lpConfigStringForKey:(NSString*)key forSection:(NSString *)section {
- if (!key) return nil;
+ return [self lpConfigStringForKey:key forSection:section withDefault:nil];
+}
+- (NSString *)lpConfigStringForKey:(NSString *)key forSection:(NSString *)section withDefault:(NSString *)defaultValue {
+ if (!key)
+ return defaultValue;
const char* value = lp_config_get_string(configDb, [section UTF8String], [key UTF8String], NULL);
- if (value)
- return [NSString stringWithUTF8String:value];
- else
- return nil;
+ return value ? [NSString stringWithUTF8String:value] : defaultValue;
}
-- (void)lpConfigSetInt:(NSInteger)value forKey:(NSString*)key {
- [self lpConfigSetInt:value forKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]];
+- (void)lpConfigSetInt:(int)value forKey:(NSString *)key {
+ [self lpConfigSetInt:value forKey:key forSection:LINPHONERC_APPLICATION_KEY];
}
-
-- (void)lpConfigSetInt:(NSInteger)value forKey:(NSString*)key forSection:(NSString *)section {
+- (void)lpConfigSetInt:(int)value forKey:(NSString *)key forSection:(NSString *)section {
if (!key) return;
- lp_config_set_int(configDb, [section UTF8String], [key UTF8String], (int)value );
+ lp_config_set_int(configDb, [section UTF8String], [key UTF8String], (int)value);
}
-
-- (NSInteger)lpConfigIntForKey:(NSString*)key {
- return [self lpConfigIntForKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]];
+- (int)lpConfigIntForKey:(NSString *)key {
+ return [self lpConfigIntForKey:key withDefault:-1];
}
-
-- (NSInteger)lpConfigIntForKey:(NSString*)key forSection:(NSString *)section {
- if (!key) return -1;
- return lp_config_get_int(configDb, [section UTF8String], [key UTF8String], -1);
+- (int)lpConfigIntForKey:(NSString *)key withDefault:(int)defaultValue {
+ return [self lpConfigIntForKey:key forSection:LINPHONERC_APPLICATION_KEY withDefault:defaultValue];
+}
+- (int)lpConfigIntForKey:(NSString *)key forSection:(NSString *)section {
+ return [self lpConfigIntForKey:key forSection:section withDefault:-1];
+}
+- (int)lpConfigIntForKey:(NSString *)key forSection:(NSString *)section withDefault:(int)defaultValue {
+ if (!key)
+ return defaultValue;
+ return lp_config_get_int(configDb, [section UTF8String], [key UTF8String], (int)defaultValue);
}
- (void)lpConfigSetBool:(BOOL)value forKey:(NSString*)key {
- [self lpConfigSetBool:value forKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]];
+ [self lpConfigSetBool:value forKey:key forSection:LINPHONERC_APPLICATION_KEY];
}
-
- (void)lpConfigSetBool:(BOOL)value forKey:(NSString*)key forSection:(NSString *)section {
- return [self lpConfigSetInt:(NSInteger)(value == TRUE) forKey:key forSection:section];
+ [self lpConfigSetInt:(int)(value == TRUE)forKey:key forSection:section];
}
-
- (BOOL)lpConfigBoolForKey:(NSString*)key {
- return [self lpConfigBoolForKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]];
+ return [self lpConfigBoolForKey:key withDefault:FALSE];
+}
+- (BOOL)lpConfigBoolForKey:(NSString *)key withDefault:(BOOL)defaultValue {
+ return [self lpConfigBoolForKey:key forSection:LINPHONERC_APPLICATION_KEY withDefault:defaultValue];
}
-
- (BOOL)lpConfigBoolForKey:(NSString*)key forSection:(NSString *)section {
- return [self lpConfigIntForKey:key forSection:section] == 1;
+ return [self lpConfigBoolForKey:key forSection:section withDefault:FALSE];
+}
+- (BOOL)lpConfigBoolForKey:(NSString *)key forSection:(NSString *)section withDefault:(BOOL)defaultValue {
+ if (!key)
+ return defaultValue;
+ int val = [self lpConfigIntForKey:key forSection:section withDefault:-1];
+ return (val != -1) ? (val == 1) : defaultValue;
}
#pragma mark - GSM management
diff --git a/Classes/LinphoneUI/Base.lproj/UICallCell.xib b/Classes/LinphoneUI/Base.lproj/UICallCell.xib
index c46edde08..a4b4f72ce 100644
--- a/Classes/LinphoneUI/Base.lproj/UICallCell.xib
+++ b/Classes/LinphoneUI/Base.lproj/UICallCell.xib
@@ -1,8 +1,7 @@
-
+
-
-
+
@@ -33,10 +32,10 @@
-
-
-
-
+
+
+
+
@@ -218,11 +217,11 @@
-
+
-
-
+
-
+
@@ -256,7 +255,7 @@
-
+
diff --git a/Classes/LinphoneUI/Base.lproj/UIChatRoomCell.xib b/Classes/LinphoneUI/Base.lproj/UIChatRoomCell.xib
index e4a9593a5..9817a998a 100644
--- a/Classes/LinphoneUI/Base.lproj/UIChatRoomCell.xib
+++ b/Classes/LinphoneUI/Base.lproj/UIChatRoomCell.xib
@@ -1,7 +1,8 @@
-
+
-
+
+
@@ -9,9 +10,11 @@
+
+
@@ -54,6 +57,7 @@
+
+
+
+
+
-
+
@@ -103,16 +127,23 @@
+
+
+
+
+
+
+
@@ -121,4 +152,9 @@
-
\ No newline at end of file
+
+
+
+
+
+
diff --git a/Classes/LinphoneUI/UICallCell.h b/Classes/LinphoneUI/UICallCell.h
index 71dbcb34d..43f4f13dd 100644
--- a/Classes/LinphoneUI/UICallCell.h
+++ b/Classes/LinphoneUI/UICallCell.h
@@ -78,10 +78,10 @@ typedef enum _UICallCellOtherView {
@property (nonatomic, strong) IBOutlet UILabel* videoCodecLabel;
@property (nonatomic, strong) IBOutlet UILabel* videoCodecHeaderLabel;
-@property (strong, nonatomic) IBOutlet UILabel *videoSentSizeHeaderLabel;
-@property (strong, nonatomic) IBOutlet UILabel *videoSentSizeLabel;
-@property (strong, nonatomic) IBOutlet UILabel *videoRecvSizeHeaderLabel;
-@property (strong, nonatomic) IBOutlet UILabel *videoRecvSizeLabel;
+@property(strong, nonatomic) IBOutlet UILabel *videoSentSizeFPSHeaderLabel;
+@property(strong, nonatomic) IBOutlet UILabel *videoSentSizeFPSLabel;
+@property(strong, nonatomic) IBOutlet UILabel *videoRecvSizeFPSHeaderLabel;
+@property(strong, nonatomic) IBOutlet UILabel *videoRecvSizeFPSLabel;
@property (nonatomic, strong) IBOutlet UILabel* videoUploadBandwidthLabel;
@property (nonatomic, strong) IBOutlet UILabel* videoUploadBandwidthHeaderLabel;
diff --git a/Classes/LinphoneUI/UICallCell.m b/Classes/LinphoneUI/UICallCell.m
index 90634f21d..4c9cfa5f2 100644
--- a/Classes/LinphoneUI/UICallCell.m
+++ b/Classes/LinphoneUI/UICallCell.m
@@ -120,8 +120,8 @@
@synthesize videoDownloadBandwidthLabel, videoDownloadBandwidthHeaderLabel;
@synthesize videoIceConnectivityLabel, videoIceConnectivityHeaderLabel;
-@synthesize videoRecvSizeHeaderLabel, videoRecvSizeLabel;
-@synthesize videoSentSizeHeaderLabel, videoSentSizeLabel;
+@synthesize videoRecvSizeFPSHeaderLabel, videoRecvSizeFPSLabel;
+@synthesize videoSentSizeFPSHeaderLabel, videoSentSizeFPSLabel;
@synthesize otherView;
@@ -433,24 +433,28 @@
const LinphoneCallStats *stats = linphone_call_get_video_stats(call);
- MSVideoSize sentSize = linphone_call_params_get_sent_video_size(params);
- MSVideoSize recvSize = linphone_call_params_get_received_video_size(params);
+ if (stats != NULL && linphone_call_params_video_enabled(params)) {
+ MSVideoSize sentSize = linphone_call_params_get_sent_video_size(params);
+ MSVideoSize recvSize = linphone_call_params_get_received_video_size(params);
+ float sentFPS = linphone_call_params_get_sent_framerate(params);
+ float recvFPS = linphone_call_params_get_received_framerate(params);
- if(stats != NULL) {
- [videoUploadBandwidthLabel setText:[NSString stringWithFormat:@"%1.1f kbits/s", stats->upload_bandwidth]];
- [videoDownloadBandwidthLabel setText:[NSString stringWithFormat:@"%1.1f kbits/s", stats->download_bandwidth]];
- [videoIceConnectivityLabel setText:[UICallCell iceToString:stats->ice_state]];
- [videoSentSizeLabel setText:[NSString stringWithFormat:@"%dx%d",sentSize.width, sentSize.height]];
- [videoRecvSizeLabel setText:[NSString stringWithFormat:@"%dx%d",recvSize.width, recvSize.height]];
- } else {
- [videoUploadBandwidthLabel setText:@""];
- [videoDownloadBandwidthLabel setText:@""];
- [videoIceConnectivityLabel setText:@""];
- [videoSentSizeLabel setText:@"0x0"];
- [videoRecvSizeLabel setText:@"0x0"];
-
- }
- }
+ [videoUploadBandwidthLabel setText:[NSString stringWithFormat:@"%1.1f kbits/s", stats->upload_bandwidth]];
+ [videoDownloadBandwidthLabel
+ setText:[NSString stringWithFormat:@"%1.1f kbits/s", stats->download_bandwidth]];
+ [videoIceConnectivityLabel setText:[UICallCell iceToString:stats->ice_state]];
+ [videoSentSizeFPSLabel
+ setText:[NSString stringWithFormat:@"%dx%d (%.1fFPS)", sentSize.width, sentSize.height, sentFPS]];
+ [videoRecvSizeFPSLabel
+ setText:[NSString stringWithFormat:@"%dx%d (%.1fFPS)", recvSize.width, recvSize.height, recvFPS]];
+ } else {
+ [videoUploadBandwidthLabel setText:@""];
+ [videoDownloadBandwidthLabel setText:@""];
+ [videoIceConnectivityLabel setText:@""];
+ [videoSentSizeFPSLabel setText:@"0x0"];
+ [videoRecvSizeFPSLabel setText:@"0x0"];
+ }
+ }
}
diff --git a/Classes/LinphoneUI/UIChatCell.m b/Classes/LinphoneUI/UIChatCell.m
index aacc5e510..b80e2cfd7 100644
--- a/Classes/LinphoneUI/UIChatCell.m
+++ b/Classes/LinphoneUI/UIChatCell.m
@@ -106,11 +106,12 @@
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);
- // Message
- if(url) {
- [chatContentLabel setText:@""];
+ 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) {
NSString *message = [NSString stringWithUTF8String:text];
// shorten long messages
diff --git a/Classes/LinphoneUI/UIChatRoomCell.h b/Classes/LinphoneUI/UIChatRoomCell.h
index d71a9ec27..9502e5e05 100644
--- a/Classes/LinphoneUI/UIChatRoomCell.h
+++ b/Classes/LinphoneUI/UIChatRoomCell.h
@@ -24,7 +24,7 @@
#import "UITransparentTVCell.h"
#import "UITextViewNoDefine.h"
#include "linphone/linphonecore.h"
-
+#import "FileTransferDelegate.h"
@interface UIChatRoomCell : UITransparentTVCell {
LinphoneChatMessage* chat;
@@ -41,6 +41,8 @@
@property (nonatomic, strong) IBOutlet UIButton* downloadButton;
@property (nonatomic, strong) IBOutlet UITapGestureRecognizer* imageTapGestureRecognizer;
@property (nonatomic, strong) IBOutlet UITapGestureRecognizer* resendTapGestureRecognizer;
+@property (weak, nonatomic) IBOutlet UIProgressView *fileTransferProgress;
+@property (weak, nonatomic) IBOutlet UIButton *cancelButton;
- (id)initWithIdentifier:(NSString*)identifier;
+ (CGFloat)height:(LinphoneChatMessage*)chatMessage width:(int)width;
@@ -50,7 +52,10 @@
- (IBAction)onDeleteClick:(id)event;
- (IBAction)onDownloadClick:(id)event;
- (IBAction)onImageClick:(id)event;
+- (IBAction)onCancelDownloadClick:(id)sender;
- (void)setChatMessage:(LinphoneChatMessage*)message;
+- (void)connectToFileDelegate:(FileTransferDelegate*)ftd;
+
@end
diff --git a/Classes/LinphoneUI/UIChatRoomCell.m b/Classes/LinphoneUI/UIChatRoomCell.m
index 45d02b40b..21d11c0c1 100644
--- a/Classes/LinphoneUI/UIChatRoomCell.m
+++ b/Classes/LinphoneUI/UIChatRoomCell.m
@@ -28,7 +28,9 @@
#import
#include "linphone/linphonecore.h"
-@implementation UIChatRoomCell
+@implementation UIChatRoomCell {
+ FileTransferDelegate* ftd;
+}
@synthesize innerView;
@synthesize bubbleView;
@@ -56,306 +58,418 @@ static UIFont *CELL_FONT = nil;
#pragma mark - Lifecycle Functions
- (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:)];
- [messageImageView addGestureRecognizer:imageTapGestureRecognizer];
+ if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
+ [[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:)];
- [dateLabel addGestureRecognizer:resendTapGestureRecognizer];
+ resendTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onResendClick:)];
+ [dateLabel addGestureRecognizer:resendTapGestureRecognizer];
+ [statusImage addGestureRecognizer:resendTapGestureRecognizer];
- [self addSubview:innerView];
- [deleteButton setAlpha:0.0f];
+ [self addSubview:innerView];
+ [deleteButton setAlpha:0.0f];
- // shift message box, otherwise it will collide with the bubble
- CGRect messageCoords = [messageText frame];
- messageCoords.origin.x += 2;
- messageCoords.origin.y += 2;
- messageCoords.size.width -= 5;
- [messageText setFrame:messageCoords];
- messageText.allowSelectAll = TRUE;
- }
- return self;
+ // shift message box, otherwise it will collide with the bubble
+ CGRect messageCoords = [messageText frame];
+ messageCoords.origin.x += 2;
+ messageCoords.origin.y += 2;
+ messageCoords.size.width -= 5;
+ [messageText setFrame:messageCoords];
+ messageText.allowSelectAll = TRUE;
+ }
+
+ return self;
}
+- (void)dealloc {
+ [self disconnectFromFileDelegate];
+}
#pragma mark -
- (void)setChatMessage:(LinphoneChatMessage *)message {
- self->chat = message;
- [self update];
+ if (message != self->chat) {
+ self->chat = message;
+ messageImageView.image = nil;
+ [self disconnectFromFileDelegate];
+ for (FileTransferDelegate *aftd in [[LinphoneManager instance] fileTransferDelegates]) {
+ if (message &&
+ linphone_chat_message_get_storage_id(aftd.message) == linphone_chat_message_get_storage_id(message)) {
+ LOGI(@"Chat message [%p] with file transfer delegate [%p], connecting to it!", message,
+ linphone_chat_message_get_user_data(message));
+ [self connectToFileDelegate:aftd];
+ break;
+ }
+ }
+ [self update];
+ }
}
+ (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 ){
- decoded = @"(invalid string)";
- }
- }
- return decoded;
+ 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 ){
+ decoded = @"(invalid string)";
+ }
+ }
+ return decoded;
}
- (void)update {
- 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);
- BOOL is_external = url && (strstr(url, "http") == url);
- NSString* localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:chat];
+ 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);
+ BOOL is_external =
+ (url && (strstr(url, "http") == url)) || linphone_chat_message_get_file_transfer_information(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 (messageImageView.image == nil) {
+ NSURL *imageUrl = [NSURL URLWithString:localImage];
+ messageText.hidden = YES;
+ [messageImageView startLoading];
+ __block LinphoneChatMessage *achat = chat;
+ [[LinphoneManager instance]
+ .photoLibrary assetForURL:imageUrl
+ resultBlock:^(ALAsset *asset) {
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL),
+ ^(void) {
+ if (achat == self->chat) { // Avoid glitch and scrolling
+ UIImage *image = [[UIImage alloc] initWithCGImage:[asset thumbnail]];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [messageImageView setImage:image];
+ [messageImageView setFullImageUrl:asset];
+ [messageImageView stopLoading];
+ messageImageView.hidden = NO;
+ });
+ }
+ });
+ }
+ failureBlock:^(NSError *error) {
+ LOGE(@"Can't read image");
+ }];
+ }
+ if (ftd.message != nil) {
+ _cancelButton.hidden = NO;
+ _fileTransferProgress.hidden = NO;
+ downloadButton.hidden = YES;
+ } else {
+ _cancelButton.hidden = _fileTransferProgress.hidden = downloadButton.hidden = YES;
+ }
+ } else {
+ messageText.hidden = YES;
+ messageImageView.hidden = _cancelButton.hidden = _fileTransferProgress.hidden = (ftd.message == nil);
+ downloadButton.hidden = !_cancelButton.hidden;
+ }
+ // simple text message
+ } else {
+ [messageText setHidden:FALSE];
+ if ( text ){
+ NSString* nstext = [UIChatRoomCell decodeTextMessage:text];
- if(is_external && !localImage ) {
- [messageText setHidden:TRUE];
- [messageImageView setImage:nil];
- [messageImageView setHidden:TRUE];
- [downloadButton setHidden:FALSE];
+ /* 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 */
- } else if(localImage) {
+ NSAttributedString* attr_text = [[NSAttributedString alloc]
+ initWithString:nstext
+ attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:17.0],
+ NSForegroundColorAttributeName:[UIColor darkGrayColor]}];
+ messageText.attributedText = attr_text;
- NSURL* imageUrl = [NSURL URLWithString:localImage];
+ } else {
+ messageText.text = @"";
+ }
+ messageImageView.hidden = YES;
+ _cancelButton.hidden = _fileTransferProgress.hidden = downloadButton.hidden = YES;
+ }
- [messageText setHidden:TRUE];
- [messageImageView setImage:nil];
- [messageImageView startLoading];
- __block LinphoneChatMessage *achat = chat;
- [[LinphoneManager instance].photoLibrary assetForURL:imageUrl resultBlock:^(ALAsset *asset) {
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void) {
- if(achat == self->chat) { //Avoid glitch and scrolling
- UIImage* image = [[UIImage alloc] initWithCGImage:[asset thumbnail]];
- dispatch_async(dispatch_get_main_queue(), ^{
- [messageImageView setImage:image];
- [messageImageView setFullImageUrl:asset];
- [messageImageView stopLoading];
- });
- }
- });
- } failureBlock:^(NSError *error) {
- LOGE(@"Can't read image");
- }];
+ // Date
+ time_t chattime = linphone_chat_message_get_time(chat);
+ NSDate *message_date = (chattime == 0) ? [[NSDate alloc] init] : [NSDate dateWithTimeIntervalSince1970:chattime];
+ NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
+ [dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
+ [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
+ NSLocale *locale = [NSLocale currentLocale];
+ [dateFormatter setLocale:locale];
+ [dateLabel setText:[dateFormatter stringFromDate:message_date]];
- [messageImageView setHidden:FALSE];
- [downloadButton setHidden:TRUE];
- } else {
- // simple text message
- [messageText setHidden:FALSE];
- if ( text ){
- NSString* nstext = [UIChatRoomCell decodeTextMessage:text];
+ LinphoneChatMessageState state = linphone_chat_message_get_state(chat);
+ BOOL outgoing = linphone_chat_message_is_outgoing(chat);
- /* 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]}];
- messageText.attributedText = attr_text;
-
- } else {
- messageText.text = @"";
- }
-
- [messageImageView setImage:nil];
- [messageImageView setHidden:TRUE];
-
- [downloadButton setHidden:TRUE];
- }
-
- // Date
- NSDate* message_date = [NSDate dateWithTimeIntervalSince1970:linphone_chat_message_get_time(chat)];
- NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
- [dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
- [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
- NSLocale *locale = [NSLocale currentLocale];
- [dateFormatter setLocale:locale];
- [dateLabel setText:[dateFormatter stringFromDate:message_date]];
-
- LinphoneChatMessageState state = linphone_chat_message_get_state(chat);
- BOOL outgoing = linphone_chat_message_is_outgoing(chat);
-
- if( !outgoing ){
- statusImage.hidden = TRUE; // not useful for incoming chats..
- } else if (state== LinphoneChatMessageStateInProgress) {
+ if( !outgoing ){
+ statusImage.hidden = TRUE; // not useful for incoming chats..
+ } else if (state== LinphoneChatMessageStateInProgress) {
[statusImage setImage:[UIImage imageNamed:@"chat_message_inprogress.png"]];
- [statusImage setAccessibilityValue:@"in progress"];
+ [statusImage setAccessibilityValue:@"in progress"];
statusImage.hidden = FALSE;
- } else if (state == LinphoneChatMessageStateDelivered) {
+ } else if (state == LinphoneChatMessageStateDelivered || state == LinphoneChatMessageStateFileTransferDone) {
[statusImage setImage:[UIImage imageNamed:@"chat_message_delivered.png"]];
- [statusImage setAccessibilityValue:@"delivered"];
+ [statusImage setAccessibilityValue:@"delivered"];
statusImage.hidden = FALSE;
} else {
[statusImage setImage:[UIImage imageNamed:@"chat_message_not_delivered.png"]];
- [statusImage setAccessibilityValue:@"not delivered"];
+ [statusImage setAccessibilityValue:@"not delivered"];
statusImage.hidden = FALSE;
- NSAttributedString* resend_text = [[NSAttributedString alloc]
- initWithString:NSLocalizedString(@"Resend", @"Resend")
- attributes:@{NSForegroundColorAttributeName: [UIColor redColor]}];
- [dateLabel setAttributedText:resend_text];
+ NSAttributedString* resend_text = [[NSAttributedString alloc]
+ initWithString:NSLocalizedString(@"Resend", @"Resend")
+ attributes:@{NSForegroundColorAttributeName: [UIColor redColor]}];
+ [dateLabel setAttributedText:resend_text];
}
- if( outgoing){
- [messageText setAccessibilityLabel:@"Outgoing message"];
- } else {
- [messageText setAccessibilityLabel:@"Incoming message"];
- }
-
+ if( outgoing){
+ [messageText setAccessibilityLabel:@"Outgoing message"];
+ } else {
+ [messageText setAccessibilityLabel:@"Incoming message"];
+ }
}
- (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];
+ }
}
+ (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] : @"";
- if(url == nil) {
- if(CELL_FONT == nil) {
- CELL_FONT = [UIFont systemFontOfSize:CELL_FONT_SIZE];
- }
+ 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] : @"";
+ if (url == nil && linphone_chat_message_get_file_transfer_information(chat) == NULL) {
+ 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;
- } else
+ 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];
- }
- } else {
- messageSize = CGSizeMake(CELL_IMAGE_WIDTH, CELL_IMAGE_HEIGHT);
- }
- messageSize.height += CELL_MESSAGE_Y_MARGIN;
- if(messageSize.height < CELL_MIN_HEIGHT)
- messageSize.height = CELL_MIN_HEIGHT;
- messageSize.width += CELL_MESSAGE_X_MARGIN;
- if(messageSize.width < CELL_MIN_WIDTH)
- messageSize.width = CELL_MIN_WIDTH;
- return messageSize;
+ {
+ 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)
+ messageSize.height = CELL_MIN_HEIGHT;
+ messageSize.width += CELL_MESSAGE_X_MARGIN;
+ if(messageSize.width < CELL_MIN_WIDTH)
+ messageSize.width = CELL_MIN_WIDTH;
+ return messageSize;
}
+ (CGFloat)height:(LinphoneChatMessage*)chatMessage width:(int)width {
- return [UIChatRoomCell viewSize:chatMessage width:width].height;
+ return [UIChatRoomCell viewSize:chatMessage width:width].height;
}
#pragma mark - View Functions
- (void)layoutSubviews {
- [super layoutSubviews];
- 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
- innerFrame.origin.x = 0.0f;
- innerFrame.origin.y = 0.0f;
- } else {
- innerFrame.origin.x = [self frame].size.width - innerFrame.size.width;
- innerFrame.origin.y = 0.0f;
- }
- [innerView setFrame:innerFrame];
+ [super layoutSubviews];
+ 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
+ innerFrame.origin.x = 0.0f;
+ innerFrame.origin.y = 0.0f;
+ } else {
+ innerFrame.origin.x = [self frame].size.width - innerFrame.size.width;
+ innerFrame.origin.y = 0.0f;
+ }
+ [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"];
- image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(26, 32, 34, 56)];
- [backgroundImage setImage:image];
- messageFrame.origin.y += 5;
- } else {
- UIImage* image = [UIImage imageNamed:@"chat_bubble_outgoing"];
- image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(14, 15, 25, 40)];
- [backgroundImage setImage:image];
- messageFrame.origin.y -= 5;
- }
- [bubbleView setFrame:messageFrame];
- }
+ 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"];
+ image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(26, 32, 34, 56)];
+ [backgroundImage setImage:image];
+ messageFrame.origin.y += 5;
+ } else {
+ UIImage* image = [UIImage imageNamed:@"chat_bubble_outgoing"];
+ image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(14, 15, 25, 40)];
+ [backgroundImage setImage:image];
+ messageFrame.origin.y -= 5;
+ }
+ [bubbleView setFrame:messageFrame];
+ }
}
#pragma mark - Action Functions
- (IBAction)onDeleteClick:(id)event {
- if(chat != 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(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;
+ NSIndexPath *indexPath = [tableView indexPathForCell:self];
+ [[tableView dataSource] tableView:tableView commitEditingStyle:UITableViewCellEditingStyleDelete forRowAtIndexPath:indexPath];
+ }
+ }
}
- (IBAction)onDownloadClick:(id)event {
- NSURL* url = [NSURL URLWithString:[NSString stringWithUTF8String:linphone_chat_message_get_external_body_url(chat)]];
- [chatRoomDelegate chatRoomStartImageDownload:url userInfo:[NSValue valueWithPointer:chat]];
-
+ if (ftd.message == nil) {
+ ftd = [[FileTransferDelegate alloc] init];
+ [[[LinphoneManager instance] fileTransferDelegates] addObject:ftd];
+ [self connectToFileDelegate:ftd];
+ [ftd download:chat];
+ _cancelButton.hidden = NO;
+ downloadButton.hidden = YES;
+ }
}
+- (IBAction)onCancelDownloadClick:(id)sender {
+ [ftd cancel];
+ [self disconnectFromFileDelegate];
+ [self update];
+}
+
+
- (IBAction)onImageClick:(id)event {
- if(![messageImageView isLoading]) {
- ImageViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ImageViewController compositeViewDescription] push:TRUE], ImageViewController);
- if(controller != nil) {
- CGImageRef fullScreenRef = [[messageImageView.fullImageUrl defaultRepresentation] fullScreenImage];
- UIImage* fullScreen = [UIImage imageWithCGImage:fullScreenRef];
- [controller setImage:fullScreen];
- }
- }
+ LinphoneChatMessageState state = linphone_chat_message_get_state(self->chat);
+ if (state == LinphoneChatMessageStateNotDelivered) {
+ [self onResendClick:nil];
+ } else {
+ if (![messageImageView isLoading]) {
+ ImageViewController *controller = DYNAMIC_CAST(
+ [[PhoneMainView instance] changeCurrentView:[ImageViewController compositeViewDescription] push:TRUE],
+ ImageViewController);
+ if (controller != nil) {
+ CGImageRef fullScreenRef = [[messageImageView.fullImageUrl defaultRepresentation] fullScreenImage];
+ UIImage *fullScreen = [UIImage imageWithCGImage:fullScreenRef];
+ [controller setImage:fullScreen];
+ }
+ }
+ }
}
- (IBAction)onResendClick:(id)event {
- if( chat == nil ) return;
+ if( chat == nil ) return;
- LinphoneChatMessageState state = linphone_chat_message_get_state(self->chat);
- if (state == LinphoneChatMessageStateNotDelivered) {
- const char* text = linphone_chat_message_get_text(self->chat);
- const char* url = linphone_chat_message_get_external_body_url(self->chat);
- NSString* message = text ? [NSString stringWithUTF8String:text] : nil;
- NSString* exturl = url ? [NSString stringWithUTF8String:url] : nil;
+ LinphoneChatMessageState state = linphone_chat_message_get_state(self->chat);
+ if (state == LinphoneChatMessageStateNotDelivered) {
+ if (linphone_chat_message_get_file_transfer_information(chat) != NULL) {
+ NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:chat];
+ NSURL *imageUrl = [NSURL URLWithString:localImage];
- [self onDeleteClick:nil];
+ [self onDeleteClick:nil];
- double delayInSeconds = 0.4;
- dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
- dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
- [chatRoomDelegate resendChat:message withExternalUrl:exturl];
- });
- }
+ [[LinphoneManager instance]
+ .photoLibrary assetForURL:imageUrl
+ resultBlock:^(ALAsset *asset) {
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL),
+ ^(void) {
+ UIImage *image = [[UIImage alloc] initWithCGImage:[asset thumbnail]];
+ [chatRoomDelegate chatRoomStartImageUpload:image url:imageUrl];
+ });
+ }
+ failureBlock:^(NSError *error) {
+ LOGE(@"Can't read image");
+ }];
+ } else {
+ const char *text = linphone_chat_message_get_text(self->chat);
+ NSString *message = text ? [NSString stringWithUTF8String:text] : nil;
+
+ [self onDeleteClick:nil];
+
+ double delayInSeconds = 0.4;
+ dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
+ dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
+ [chatRoomDelegate resendChat:message withExternalUrl:nil];
+ });
+ }
+ }
+}
+
+#pragma mark - LinphoneFileTransfer Notifications Handling
+
+- (void)connectToFileDelegate:(FileTransferDelegate*)aftd {
+ ftd = aftd;
+ _fileTransferProgress.progress = 0;
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(onFileTransferSendUpdate:)
+ name:kLinphoneFileTransferSendUpdate
+ object:ftd];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(onFileTransferRecvUpdate:)
+ name:kLinphoneFileTransferRecvUpdate
+ object:ftd];
+}
+
+- (void)disconnectFromFileDelegate {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ ftd = nil;
+}
+
+- (void)onFileTransferSendUpdate:(NSNotification*)notif {
+ LinphoneChatMessageState state = [[[notif userInfo] objectForKey:@"state"] intValue];
+
+ if (state == LinphoneChatMessageStateInProgress) {
+ float progress = [[[notif userInfo] objectForKey:@"progress"] floatValue];
+ // When uploading a file, the message file is first uploaded to the server,
+ // so we are in progress state. Then state goes to filetransfertdone. Then,
+ // the exact same message is sent to the other chat participant and we come
+ // back to in progress again. This second time is NOT an upload, so we must
+ // not update progress!
+ _fileTransferProgress.progress = MAX(_fileTransferProgress.progress, progress);
+ _fileTransferProgress.hidden = _cancelButton.hidden = (_fileTransferProgress.progress == 1.f);
+ } else {
+ [self update];
+ }
+}
+- (void)onFileTransferRecvUpdate:(NSNotification*)notif {
+ LinphoneChatMessageState state = [[[notif userInfo] objectForKey:@"state"] intValue];
+ if (state == LinphoneChatMessageStateInProgress) {
+ float progress = [[[notif userInfo] objectForKey:@"progress"] floatValue];
+ _fileTransferProgress.progress = MAX(_fileTransferProgress.progress, progress);
+ _fileTransferProgress.hidden = _cancelButton.hidden = (_fileTransferProgress.progress == 1.f);
+ } else {
+ [self update];
+ }
}
@end
diff --git a/Classes/PhoneMainView.m b/Classes/PhoneMainView.m
index d5a9eeec8..2298bd5f1 100644
--- a/Classes/PhoneMainView.m
+++ b/Classes/PhoneMainView.m
@@ -20,7 +20,6 @@
#import
#import
-#import "InAppProductsViewController.h"
#import "LinphoneAppDelegate.h"
#import "PhoneMainView.h"
#import "Utils.h"
diff --git a/Classes/SettingsViewController.m b/Classes/SettingsViewController.m
index d1a07dec2..2fd4cf558 100644
--- a/Classes/SettingsViewController.m
+++ b/Classes/SettingsViewController.m
@@ -22,7 +22,6 @@
#import "PhoneMainView.h"
#import "UILinphone.h"
#import "UACellBackgroundView.h"
-#import "InAppProductsViewController.h"
#import "DCRoundSwitch.h"
@@ -46,88 +45,85 @@
@interface SettingsViewController (private)
-+ (IASKSpecifier*)filterSpecifier:(IASKSpecifier *)specifier;
++ (IASKSpecifier *)filterSpecifier:(IASKSpecifier *)specifier;
@end
-
#pragma mark - IASKSwitchEx Class
@interface IASKSwitchEx : DCRoundSwitch {
- NSString *_key;
+ NSString *_key;
}
-@property (nonatomic, strong) NSString *key;
+@property(nonatomic, strong) NSString *key;
@end
@implementation IASKSwitchEx
-@synthesize key=_key;
+@synthesize key = _key;
- (void)dealloc {
- _key = nil;
-
+ _key = nil;
}
@end
-
#pragma mark - IASKSpecifierValuesViewControllerEx Class
// Patch IASKSpecifierValuesViewController
-@interface IASKSpecifierValuesViewControllerEx: IASKSpecifierValuesViewController
+@interface IASKSpecifierValuesViewControllerEx : IASKSpecifierValuesViewController
@end
@implementation IASKSpecifierValuesViewControllerEx
- (void)initIASKSpecifierValuesViewControllerEx {
- [self.view setBackgroundColor:[UIColor clearColor]];
+ [self.view setBackgroundColor:[UIColor clearColor]];
}
- (id)init {
- self = [super init];
- if(self != nil) {
- [self initIASKSpecifierValuesViewControllerEx];
- }
- return self;
+ self = [super init];
+ if (self != nil) {
+ [self initIASKSpecifierValuesViewControllerEx];
+ }
+ return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
- self = [super initWithCoder:aDecoder];
- if(self != nil) {
- [self initIASKSpecifierValuesViewControllerEx];
- }
- return self;
+ self = [super initWithCoder:aDecoder];
+ if (self != nil) {
+ [self initIASKSpecifierValuesViewControllerEx];
+ }
+ return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
- self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
- if(self != nil) {
- [self initIASKSpecifierValuesViewControllerEx];
- }
- return self;
+ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+ if (self != nil) {
+ [self initIASKSpecifierValuesViewControllerEx];
+ }
+ return self;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- UITableViewCell * cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
+ UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
- // Background View
- UACellBackgroundView *selectedBackgroundView = [[UACellBackgroundView alloc] initWithFrame:CGRectZero];
- cell.selectedBackgroundView = selectedBackgroundView;
- [selectedBackgroundView setBackgroundColor:LINPHONE_TABLE_CELL_BACKGROUND_COLOR];
- return cell;
+ // Background View
+ UACellBackgroundView *selectedBackgroundView = [[UACellBackgroundView alloc] initWithFrame:CGRectZero];
+ cell.selectedBackgroundView = selectedBackgroundView;
+ [selectedBackgroundView setBackgroundColor:LINPHONE_TABLE_CELL_BACKGROUND_COLOR];
+ return cell;
}
@end
-
#pragma mark - IASKAppSettingsViewControllerEx Class
-@interface IASKAppSettingsViewController(PrivateInterface)
-- (UITableViewCell*)newCellForIdentifier:(NSString*)identifier;
-@end;
+@interface IASKAppSettingsViewController (PrivateInterface)
+- (UITableViewCell *)newCellForIdentifier:(NSString *)identifier;
+@end
+;
@interface IASKAppSettingsViewControllerEx : IASKAppSettingsViewController
@@ -135,197 +131,200 @@
@implementation IASKAppSettingsViewControllerEx
-- (UITableViewCell*)newCellForIdentifier:(NSString*)identifier {
+- (UITableViewCell *)newCellForIdentifier:(NSString *)identifier {
UITableViewCell *cell = nil;
if ([identifier isEqualToString:kIASKPSToggleSwitchSpecifier]) {
- cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kIASKPSToggleSwitchSpecifier];
+ cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
+ reuseIdentifier:kIASKPSToggleSwitchSpecifier];
cell.accessoryView = [[IASKSwitchEx alloc] initWithFrame:CGRectMake(0, 0, 79, 27)];
- [((IASKSwitchEx*)cell.accessoryView) addTarget:self action:@selector(toggledValue:) forControlEvents:UIControlEventValueChanged];
- [((IASKSwitchEx*)cell.accessoryView) setOnTintColor:LINPHONE_MAIN_COLOR];
+ [((IASKSwitchEx *)cell.accessoryView)addTarget:self
+ action:@selector(toggledValue:)
+ forControlEvents:UIControlEventValueChanged];
+ [((IASKSwitchEx *)cell.accessoryView)setOnTintColor:LINPHONE_MAIN_COLOR];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
- cell.textLabel.minimumScaleFactor = kIASKMinimumFontSize/[UIFont systemFontSize];
- cell.detailTextLabel.minimumScaleFactor = kIASKMinimumFontSize/[UIFont systemFontSize];
+ cell.textLabel.minimumScaleFactor = kIASKMinimumFontSize / [UIFont systemFontSize];
+ cell.detailTextLabel.minimumScaleFactor = kIASKMinimumFontSize / [UIFont systemFontSize];
} else {
- cell = [super newCellForIdentifier:identifier];
- }
- return cell;
+ cell = [super newCellForIdentifier:identifier];
+ }
+ return cell;
}
- (void)toggledValue:(id)sender {
- IASKSwitchEx *toggle = (IASKSwitchEx*)sender;
- IASKSpecifier *spec = [_settingsReader specifierForKey:[toggle key]];
+ IASKSwitchEx *toggle = (IASKSwitchEx *)sender;
+ IASKSpecifier *spec = [_settingsReader specifierForKey:[toggle key]];
- if ([toggle isOn]) {
- if ([spec trueValue] != nil) {
- [self.settingsStore setObject:[spec trueValue] forKey:[toggle key]];
- }
- else {
- [self.settingsStore setBool:YES forKey:[toggle key]];
- }
- }
- else {
- if ([spec falseValue] != nil) {
- [self.settingsStore setObject:[spec falseValue] forKey:[toggle key]];
- }
- else {
- [self.settingsStore setBool:NO forKey:[toggle key]];
- }
- }
- // Start notification after animation of DCRoundSwitch
- dispatch_async(dispatch_get_main_queue(), ^{
- [[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged
- object:[toggle key]
- userInfo:[NSDictionary dictionaryWithObject:[self.settingsStore objectForKey:[toggle key]]
- forKey:[toggle key]]];
- });
+ if ([toggle isOn]) {
+ if ([spec trueValue] != nil) {
+ [self.settingsStore setObject:[spec trueValue] forKey:[toggle key]];
+ } else {
+ [self.settingsStore setBool:YES forKey:[toggle key]];
+ }
+ } else {
+ if ([spec falseValue] != nil) {
+ [self.settingsStore setObject:[spec falseValue] forKey:[toggle key]];
+ } else {
+ [self.settingsStore setBool:NO forKey:[toggle key]];
+ }
+ }
+ // Start notification after animation of DCRoundSwitch
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [[NSNotificationCenter defaultCenter]
+ postNotificationName:kIASKAppSettingChanged
+ object:[toggle key]
+ userInfo:[NSDictionary dictionaryWithObject:[self.settingsStore objectForKey:[toggle key]]
+ forKey:[toggle key]]];
+ });
}
- (void)initIASKAppSettingsViewControllerEx {
- [self.view setBackgroundColor:[UIColor clearColor]];
+ [self.view setBackgroundColor:[UIColor clearColor]];
- // Force kIASKSpecifierValuesViewControllerIndex
- static int kIASKSpecifierValuesViewControllerIndex = 0;
- _viewList = [[NSMutableArray alloc] init];
- [_viewList addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"IASKSpecifierValuesView", @"ViewName",nil]];
- [_viewList addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"IASKAppSettingsView", @"ViewName",nil]];
+ // Force kIASKSpecifierValuesViewControllerIndex
+ static int kIASKSpecifierValuesViewControllerIndex = 0;
+ _viewList = [[NSMutableArray alloc] init];
+ [_viewList addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"IASKSpecifierValuesView", @"ViewName", nil]];
+ [_viewList addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"IASKAppSettingsView", @"ViewName", nil]];
- NSMutableDictionary *newItemDict = [NSMutableDictionary dictionaryWithCapacity:3];
- [newItemDict addEntriesFromDictionary: [_viewList objectAtIndex:kIASKSpecifierValuesViewControllerIndex]]; // copy the title and explain strings
+ NSMutableDictionary *newItemDict = [NSMutableDictionary dictionaryWithCapacity:3];
+ [newItemDict addEntriesFromDictionary:[_viewList objectAtIndex:kIASKSpecifierValuesViewControllerIndex]]; // copy
+ // the
+ // title
+ // and
+ // explain
+ // strings
- IASKSpecifierValuesViewController *targetViewController = [[IASKSpecifierValuesViewControllerEx alloc] init];
- // add the new view controller to the dictionary and then to the 'viewList' array
- [newItemDict setObject:targetViewController forKey:@"viewController"];
- [_viewList replaceObjectAtIndex:kIASKSpecifierValuesViewControllerIndex withObject:newItemDict];
+ IASKSpecifierValuesViewController *targetViewController = [[IASKSpecifierValuesViewControllerEx alloc] init];
+ // add the new view controller to the dictionary and then to the 'viewList' array
+ [newItemDict setObject:targetViewController forKey:@"viewController"];
+ [_viewList replaceObjectAtIndex:kIASKSpecifierValuesViewControllerIndex withObject:newItemDict];
}
-- (IASKSettingsReader*)settingsReader {
- IASKSettingsReader *r = [super settingsReader];
- NSMutableArray *dataSource = [NSMutableArray arrayWithArray:[r dataSource]];
- for (int i = 0; i < [dataSource count]; ++i) {
- NSMutableArray *specifiers = [NSMutableArray arrayWithArray:[dataSource objectAtIndex:i]];
- for (int j = 0; j < [specifiers count]; ++j) {
- id sp = [specifiers objectAtIndex:j];
- if ([sp isKindOfClass:[IASKSpecifier class]]) {
- sp = [SettingsViewController filterSpecifier:sp];
- }
- [specifiers replaceObjectAtIndex:j withObject:sp];
- }
+- (IASKSettingsReader *)settingsReader {
+ IASKSettingsReader *r = [super settingsReader];
+ NSMutableArray *dataSource = [NSMutableArray arrayWithArray:[r dataSource]];
+ for (int i = 0; i < [dataSource count]; ++i) {
+ NSMutableArray *specifiers = [NSMutableArray arrayWithArray:[dataSource objectAtIndex:i]];
+ for (int j = 0; j < [specifiers count]; ++j) {
+ id sp = [specifiers objectAtIndex:j];
+ if ([sp isKindOfClass:[IASKSpecifier class]]) {
+ sp = [SettingsViewController filterSpecifier:sp];
+ }
+ [specifiers replaceObjectAtIndex:j withObject:sp];
+ }
- [dataSource replaceObjectAtIndex:i withObject:specifiers];
- }
- [r setDataSource:dataSource];
- return r;
+ [dataSource replaceObjectAtIndex:i withObject:specifiers];
+ }
+ [r setDataSource:dataSource];
+ return r;
}
- (void)viewDidLoad {
- [super viewDidLoad];
+ [super viewDidLoad];
-
- [self.tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4
- [self.tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
+ [self.tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4
+ [self.tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
}
- (id)initWithStyle:(UITableViewStyle)style {
- self = [super initWithStyle:style];
- if(self != nil) {
- [self initIASKAppSettingsViewControllerEx];
- }
- return self;
+ self = [super initWithStyle:style];
+ if (self != nil) {
+ [self initIASKAppSettingsViewControllerEx];
+ }
+ return self;
}
- (void)viewWillAppear:(BOOL)animated {
- [super viewWillAppear:animated];
+ [super viewWillAppear:animated];
-
- UIEdgeInsets inset = {0, 0, 10, 0};
- UIScrollView *scrollView = self.tableView;
- [scrollView setContentInset:inset];
- [scrollView setScrollIndicatorInsets:inset];
+ UIEdgeInsets inset = {0, 0, 10, 0};
+ UIScrollView *scrollView = self.tableView;
+ [scrollView setContentInset:inset];
+ [scrollView setScrollIndicatorInsets:inset];
}
- (void)viewDidAppear:(BOOL)animated {
- [super viewDidAppear:animated];
+ [super viewDidAppear:animated];
- UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"About", nil) style:UIBarButtonItemStyleBordered target:self action:@selector(onAboutClick:)];
- self.navigationItem.rightBarButtonItem = buttonItem;
+ UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"About", nil)
+ style:UIBarButtonItemStyleBordered
+ target:self
+ action:@selector(onAboutClick:)];
+ self.navigationItem.rightBarButtonItem = buttonItem;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- UITableViewCell * cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
+ UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
- if([cell isKindOfClass:[IASKPSTextFieldSpecifierViewCell class]]) {
- UITextField *field = ((IASKPSTextFieldSpecifierViewCell*)cell).textField;
- [field setTextColor:LINPHONE_MAIN_COLOR];
- }
+ if ([cell isKindOfClass:[IASKPSTextFieldSpecifierViewCell class]]) {
+ UITextField *field = ((IASKPSTextFieldSpecifierViewCell *)cell).textField;
+ [field setTextColor:LINPHONE_MAIN_COLOR];
+ }
- if([cell isKindOfClass:[IASKPSTitleValueSpecifierViewCell class]]) {
- cell.detailTextLabel.textColor = [UIColor grayColor];
- } else {
- cell.detailTextLabel.textColor = LINPHONE_MAIN_COLOR;
- }
+ if ([cell isKindOfClass:[IASKPSTitleValueSpecifierViewCell class]]) {
+ cell.detailTextLabel.textColor = [UIColor grayColor];
+ } else {
+ cell.detailTextLabel.textColor = LINPHONE_MAIN_COLOR;
+ }
- // Background View
- UACellBackgroundView *selectedBackgroundView = [[UACellBackgroundView alloc] initWithFrame:CGRectZero];
- cell.selectedBackgroundView = selectedBackgroundView;
- [selectedBackgroundView setBackgroundColor:LINPHONE_TABLE_CELL_BACKGROUND_COLOR];
- return cell;
+ // Background View
+ UACellBackgroundView *selectedBackgroundView = [[UACellBackgroundView alloc] initWithFrame:CGRectZero];
+ cell.selectedBackgroundView = selectedBackgroundView;
+ [selectedBackgroundView setBackgroundColor:LINPHONE_TABLE_CELL_BACKGROUND_COLOR];
+ return cell;
}
-- (IBAction)onAboutClick: (id)sender {
- [[PhoneMainView instance] changeCurrentView:[AboutViewController compositeViewDescription] push:TRUE];
+- (IBAction)onAboutClick:(id)sender {
+ [[PhoneMainView instance] changeCurrentView:[AboutViewController compositeViewDescription] push:TRUE];
}
@end
-
#pragma mark - UINavigationBarEx Class
-@interface UINavigationBarEx: UINavigationBar {
-
+@interface UINavigationBarEx : UINavigationBar {
}
@end
@implementation UINavigationBarEx
-
#pragma mark - Lifecycle Functions
- (void)initUINavigationBarEx {
- [self setTintColor:[LINPHONE_MAIN_COLOR adjustHue:5.0f/180.0f saturation:0.0f brightness:0.0f alpha:0.0f]];
+ [self setTintColor:[LINPHONE_MAIN_COLOR adjustHue:5.0f / 180.0f saturation:0.0f brightness:0.0f alpha:0.0f]];
}
- (id)init {
- self = [super init];
- if (self) {
- [self initUINavigationBarEx];
- }
- return self;
+ self = [super init];
+ if (self) {
+ [self initUINavigationBarEx];
+ }
+ return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
- self = [super initWithCoder:aDecoder];
- if (self) {
- [self initUINavigationBarEx];
- }
- return self;
+ self = [super initWithCoder:aDecoder];
+ if (self) {
+ [self initUINavigationBarEx];
+ }
+ return self;
}
- (id)initWithFrame:(CGRect)frame {
- self = [super initWithFrame:frame];
- if (self) {
- [self initUINavigationBarEx];
- }
- return self;
+ self = [super initWithFrame:frame];
+ if (self) {
+ [self initUINavigationBarEx];
+ }
+ return self;
}
- (void)drawRect:(CGRect)rect {
- UIImage *img = [UIImage imageNamed:@"toolsbar_background.png"];
- [img drawInRect:rect];
+ UIImage *img = [UIImage imageNamed:@"toolsbar_background.png"];
+ [img drawInRect:rect];
}
@end
-
#pragma mark - UINavigationControllerEx Class
@interface UINavigationControllerEx : UINavigationController
@@ -335,53 +334,52 @@
@implementation UINavigationControllerEx
- (id)initWithRootViewController:(UIViewController *)rootViewController {
- [UINavigationControllerEx removeBackground:rootViewController.view];
- return [self initWithRootViewController:rootViewController];
+ [UINavigationControllerEx removeBackground:rootViewController.view];
+ return [self initWithRootViewController:rootViewController];
}
-+ (void)removeBackground:(UIView*)view {
- // iOS7 transparent background is *really* transparent: with an alpha != 0
- // it messes up the transitions. Use non-transparent BG for iOS7
- if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7)
- [view setBackgroundColor:LINPHONE_SETTINGS_BG_IOS7];
- else
- [view setBackgroundColor:[UIColor clearColor]];
++ (void)removeBackground:(UIView *)view {
+ // iOS7 transparent background is *really* transparent: with an alpha != 0
+ // it messes up the transitions. Use non-transparent BG for iOS7
+ if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7)
+ [view setBackgroundColor:LINPHONE_SETTINGS_BG_IOS7];
+ else
+ [view setBackgroundColor:[UIColor clearColor]];
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
- [UINavigationControllerEx removeBackground:viewController.view];
+ [UINavigationControllerEx removeBackground:viewController.view];
- [viewController viewWillAppear:animated]; // Force view
- UILabel *labelTitleView = [[UILabel alloc] init];
- labelTitleView.backgroundColor = [UIColor clearColor];
- labelTitleView.textColor = [UIColor colorWithRed:0x41/255.0f green:0x48/255.0f blue:0x4f/255.0f alpha:1.0];
- labelTitleView.shadowColor = [UIColor colorWithWhite:1.0 alpha:0.5];
- labelTitleView.font = [UIFont boldSystemFontOfSize:20];
- labelTitleView.shadowOffset = CGSizeMake(0,1);
- labelTitleView.textAlignment = NSTextAlignmentCenter;
- labelTitleView.text = viewController.title;
- [labelTitleView sizeToFit];
- viewController.navigationItem.titleView = labelTitleView;
- [super pushViewController:viewController animated:animated];
+ [viewController viewWillAppear:animated]; // Force view
+ UILabel *labelTitleView = [[UILabel alloc] init];
+ labelTitleView.backgroundColor = [UIColor clearColor];
+ labelTitleView.textColor = [UIColor colorWithRed:0x41 / 255.0f green:0x48 / 255.0f blue:0x4f / 255.0f alpha:1.0];
+ labelTitleView.shadowColor = [UIColor colorWithWhite:1.0 alpha:0.5];
+ labelTitleView.font = [UIFont boldSystemFontOfSize:20];
+ labelTitleView.shadowOffset = CGSizeMake(0, 1);
+ labelTitleView.textAlignment = NSTextAlignmentCenter;
+ labelTitleView.text = viewController.title;
+ [labelTitleView sizeToFit];
+ viewController.navigationItem.titleView = labelTitleView;
+ [super pushViewController:viewController animated:animated];
}
- (void)setViewControllers:(NSArray *)viewControllers {
- for(UIViewController *controller in viewControllers) {
- [UINavigationControllerEx removeBackground:controller.view];
- }
- [super setViewControllers:viewControllers];
+ for (UIViewController *controller in viewControllers) {
+ [UINavigationControllerEx removeBackground:controller.view];
+ }
+ [super setViewControllers:viewControllers];
}
- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated {
- for(UIViewController *controller in viewControllers) {
- [UINavigationControllerEx removeBackground:controller.view];
- }
- [super setViewControllers:viewControllers animated:animated];
+ for (UIViewController *controller in viewControllers) {
+ [UINavigationControllerEx removeBackground:controller.view];
+ }
+ [super setViewControllers:viewControllers animated:animated];
}
@end
-
@implementation SettingsViewController
@synthesize settingsController;
@@ -390,13 +388,12 @@
#pragma mark - Lifecycle Functions
- (id)init {
- return [super initWithNibName:@"SettingsViewController" bundle:[NSBundle mainBundle]];
+ return [super initWithNibName:@"SettingsViewController" bundle:[NSBundle mainBundle]];
}
-
- (void)dealloc {
- // Remove all observer
- [[NSNotificationCenter defaultCenter] removeObserver:self];
+ // Remove all observer
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - UICompositeViewDelegate Functions
@@ -404,161 +401,161 @@
static UICompositeViewDescription *compositeDescription = nil;
+ (UICompositeViewDescription *)compositeViewDescription {
- if(compositeDescription == nil) {
- compositeDescription = [[UICompositeViewDescription alloc] init:@"Settings"
- content:@"SettingsViewController"
- stateBar:nil
- stateBarEnabled:false
- tabBar: @"UIMainBar"
- tabBarEnabled:true
- fullscreen:false
- landscapeMode:[LinphoneManager runningOnIpad]
- portraitMode:true];
- }
- return compositeDescription;
+ if (compositeDescription == nil) {
+ compositeDescription = [[UICompositeViewDescription alloc] init:@"Settings"
+ content:@"SettingsViewController"
+ stateBar:nil
+ stateBarEnabled:false
+ tabBar:@"UIMainBar"
+ tabBarEnabled:true
+ fullscreen:false
+ landscapeMode:[LinphoneManager runningOnIpad]
+ portraitMode:true];
+ }
+ return compositeDescription;
}
-
#pragma mark - ViewController Functions
- (void)viewDidLoad {
- [super viewDidLoad];
+ [super viewDidLoad];
settingsStore = [[LinphoneCoreSettingsStore alloc] init];
- settingsController.showDoneButton = FALSE;
- settingsController.delegate = self;
- settingsController.showCreditsFooter = FALSE;
- settingsController.settingsStore = settingsStore;
+ settingsController.showDoneButton = FALSE;
+ settingsController.delegate = self;
+ settingsController.showCreditsFooter = FALSE;
+ settingsController.settingsStore = settingsStore;
- [navigationController.view setBackgroundColor:[UIColor clearColor]];
+ [navigationController.view setBackgroundColor:[UIColor clearColor]];
- navigationController.view.frame = self.view.frame;
- [navigationController pushViewController:settingsController animated:FALSE];
- [self.view addSubview: navigationController.view];
+ navigationController.view.frame = self.view.frame;
+ [navigationController pushViewController:settingsController animated:FALSE];
+ [self.view addSubview:navigationController.view];
}
- (void)viewWillDisappear:(BOOL)animated {
- [super viewWillDisappear:animated];
- [settingsController dismiss:self];
- // Set observer
- [[NSNotificationCenter defaultCenter] removeObserver:self
- name:kIASKAppSettingChanged
- object:nil];
+ [super viewWillDisappear:animated];
+ [settingsController dismiss:self];
+ // Set observer
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:kIASKAppSettingChanged object:nil];
}
- (void)viewWillAppear:(BOOL)animated {
- [super viewWillAppear:animated];
+ [super viewWillAppear:animated];
- [settingsStore transformLinphoneCoreToKeys]; // Sync settings with linphone core settings
- settingsController.hiddenKeys = [self findHiddenKeys];
- [settingsController.tableView reloadData];
-
- // Set observer
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(appSettingChanged:)
- name:kIASKAppSettingChanged
- object:nil];
+ [settingsStore transformLinphoneCoreToKeys]; // Sync settings with linphone core settings
+ settingsController.hiddenKeys = [self findHiddenKeys];
+ [settingsController.tableView reloadData];
+ // Set observer
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(appSettingChanged:)
+ name:kIASKAppSettingChanged
+ object:nil];
}
-
#pragma mark - Event Functions
-- (void)appSettingChanged:(NSNotification*) notif {
+- (void)appSettingChanged:(NSNotification *)notif {
NSMutableSet *hiddenKeys = [NSMutableSet setWithSet:[settingsController hiddenKeys]];
- NSMutableArray* keys = [NSMutableArray array];
+ NSMutableArray *keys = [NSMutableArray array];
BOOL removeFromHiddenKeys = TRUE;
- if([@"enable_video_preference" compare: notif.object] == NSOrderedSame) {
- removeFromHiddenKeys = [[notif.userInfo objectForKey:@"enable_video_preference"] boolValue];
+ if ([@"enable_video_preference" compare:notif.object] == NSOrderedSame) {
+ removeFromHiddenKeys = [[notif.userInfo objectForKey:@"enable_video_preference"] boolValue];
[keys addObject:@"video_menu"];
- } else if ([@"random_port_preference" compare: notif.object] == NSOrderedSame) {
- removeFromHiddenKeys = ! [[notif.userInfo objectForKey:@"random_port_preference"] boolValue];
+ } else if ([@"random_port_preference" compare:notif.object] == NSOrderedSame) {
+ removeFromHiddenKeys = ![[notif.userInfo objectForKey:@"random_port_preference"] boolValue];
[keys addObject:@"port_preference"];
- } else if ([@"backgroundmode_preference" compare: notif.object] == NSOrderedSame) {
+ } else if ([@"backgroundmode_preference" compare:notif.object] == NSOrderedSame) {
removeFromHiddenKeys = [[notif.userInfo objectForKey:@"backgroundmode_preference"] boolValue];
[keys addObject:@"start_at_boot_preference"];
- } else if ([@"stun_preference" compare: notif.object] == NSOrderedSame) {
+ } else if ([@"stun_preference" compare:notif.object] == NSOrderedSame) {
NSString *stun_server = [notif.userInfo objectForKey:@"stun_preference"];
removeFromHiddenKeys = (stun_server && ([stun_server length] > 0));
[keys addObject:@"ice_preference"];
- } else if ([@"debugenable_preference" compare: notif.object] == NSOrderedSame) {
+ } else if ([@"debugenable_preference" compare:notif.object] == NSOrderedSame) {
BOOL debugEnabled = [[notif.userInfo objectForKey:@"debugenable_preference"] boolValue];
removeFromHiddenKeys = debugEnabled;
- [keys addObject:@"send_logs_button"];
+ [keys addObject:@"send_logs_button"];
[keys addObject:@"reset_logs_button"];
[[LinphoneManager instance] setLogsEnabled:debugEnabled];
- } else if( [@"advanced_account_preference" compare:notif.object] == NSOrderedSame) {
+ } else if ([@"advanced_account_preference" compare:notif.object] == NSOrderedSame) {
removeFromHiddenKeys = [[notif.userInfo objectForKey:@"advanced_account_preference"] boolValue];
-
[keys addObject:@"userid_preference"];
[keys addObject:@"proxy_preference"];
[keys addObject:@"outbound_proxy_preference"];
[keys addObject:@"avpf_preference"];
+ } else if ([@"video_preset_preference" compare:notif.object] == NSOrderedSame) {
+ NSString *video_preset = [notif.userInfo objectForKey:@"video_preset_preference"];
+ removeFromHiddenKeys = [video_preset isEqualToString:@"custom"];
+ [keys addObject:@"video_preferred_fps_preference"];
+ [keys addObject:@"download_bandwidth_preference"];
}
- for(NSString* key in keys){
- if( removeFromHiddenKeys ) [hiddenKeys removeObject:key];
- else [hiddenKeys addObject:key];
+ for (NSString *key in keys) {
+ if (removeFromHiddenKeys)
+ [hiddenKeys removeObject:key];
+ else
+ [hiddenKeys addObject:key];
}
[settingsController setHiddenKeys:hiddenKeys animated:TRUE];
-
}
-
#pragma mark -
-+ (IASKSpecifier*)disableCodecSpecifier:(IASKSpecifier *)specifier {
- NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[specifier specifierDict]];
++ (IASKSpecifier *)disableCodecSpecifier:(IASKSpecifier *)specifier {
+ NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[specifier specifierDict]];
- NSMutableString *type = [NSMutableString stringWithString:[dict objectForKey:kIASKType]];
- [type setString:kIASKPSTitleValueSpecifier];
- [dict setObject:type forKey:kIASKType];
+ NSMutableString *type = [NSMutableString stringWithString:[dict objectForKey:kIASKType]];
+ [type setString:kIASKPSTitleValueSpecifier];
+ [dict setObject:type forKey:kIASKType];
- NSMutableArray *values = [NSMutableArray arrayWithObjects:[NSNumber numberWithInt:0], [NSNumber numberWithInt:1], nil ];
- [dict setObject:values forKey:kIASKValues];
+ NSMutableArray *values =
+ [NSMutableArray arrayWithObjects:[NSNumber numberWithInt:0], [NSNumber numberWithInt:1], nil];
+ [dict setObject:values forKey:kIASKValues];
- NSString* title = NSLocalizedString(@"Disabled, build from sources to enable", nil);
- NSMutableArray *titles = [NSMutableArray arrayWithObjects:title, title, nil];
- [dict setObject:titles forKey:kIASKTitles];
+ NSString *title = NSLocalizedString(@"Disabled, build from sources to enable", nil);
+ NSMutableArray *titles = [NSMutableArray arrayWithObjects:title, title, nil];
+ [dict setObject:titles forKey:kIASKTitles];
- return [[IASKSpecifier alloc] initWithSpecifier:dict];
+ return [[IASKSpecifier alloc] initWithSpecifier:dict];
}
-+ (IASKSpecifier*)filterSpecifier:(IASKSpecifier *)specifier {
++ (IASKSpecifier *)filterSpecifier:(IASKSpecifier *)specifier {
#ifndef HAVE_SSL
- if ([[specifier key] isEqualToString:@"transport_preference"]) {
- NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[specifier specifierDict]];
- NSMutableArray *titles = [NSMutableArray arrayWithArray:[dict objectForKey:@"Titles"]];
- [titles removeObject:@"TLS"];
- [dict setObject:titles forKey:@"Titles"];
- NSMutableArray *values = [NSMutableArray arrayWithArray:[dict objectForKey:@"Values"]];
- [values removeObject:@"tls"];
- [dict setObject:values forKey:@"Values"];
- return [[IASKSpecifier alloc] initWithSpecifier:dict];
- }
+ if ([[specifier key] isEqualToString:@"transport_preference"]) {
+ NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[specifier specifierDict]];
+ NSMutableArray *titles = [NSMutableArray arrayWithArray:[dict objectForKey:@"Titles"]];
+ [titles removeObject:@"TLS"];
+ [dict setObject:titles forKey:@"Titles"];
+ NSMutableArray *values = [NSMutableArray arrayWithArray:[dict objectForKey:@"Values"]];
+ [values removeObject:@"tls"];
+ [dict setObject:values forKey:@"Values"];
+ return [[IASKSpecifier alloc] initWithSpecifier:dict];
+ }
#else
- if ([[specifier key] isEqualToString:@"media_encryption_preference"]) {
- NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[specifier specifierDict]];
- if(!linphone_core_media_encryption_supported([LinphoneManager getLc], LinphoneMediaEncryptionZRTP)) {
- NSMutableArray *titles = [NSMutableArray arrayWithArray:[dict objectForKey:@"Titles"]];
- [titles removeObject:@"ZRTP"];
- [dict setObject:titles forKey:@"Titles"];
- NSMutableArray *values = [NSMutableArray arrayWithArray:[dict objectForKey:@"Values"]];
- [values removeObject:@"ZRTP"];
- [dict setObject:values forKey:@"Values"];
- }
- if(!linphone_core_media_encryption_supported([LinphoneManager getLc], LinphoneMediaEncryptionSRTP)) {
- NSMutableArray *titles = [NSMutableArray arrayWithArray:[dict objectForKey:@"Titles"]];
- [titles removeObject:@"SRTP"];
- [dict setObject:titles forKey:@"Titles"];
- NSMutableArray *values = [NSMutableArray arrayWithArray:[dict objectForKey:@"Values"]];
- [values removeObject:@"SRTP"];
- [dict setObject:values forKey:@"Values"];
- }
- if(!linphone_core_media_encryption_supported([LinphoneManager getLc], LinphoneMediaEncryptionDTLS)) {
+ if ([[specifier key] isEqualToString:@"media_encryption_preference"]) {
+ NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[specifier specifierDict]];
+ if (!linphone_core_media_encryption_supported([LinphoneManager getLc], LinphoneMediaEncryptionZRTP)) {
+ NSMutableArray *titles = [NSMutableArray arrayWithArray:[dict objectForKey:@"Titles"]];
+ [titles removeObject:@"ZRTP"];
+ [dict setObject:titles forKey:@"Titles"];
+ NSMutableArray *values = [NSMutableArray arrayWithArray:[dict objectForKey:@"Values"]];
+ [values removeObject:@"ZRTP"];
+ [dict setObject:values forKey:@"Values"];
+ }
+ if (!linphone_core_media_encryption_supported([LinphoneManager getLc], LinphoneMediaEncryptionSRTP)) {
+ NSMutableArray *titles = [NSMutableArray arrayWithArray:[dict objectForKey:@"Titles"]];
+ [titles removeObject:@"SRTP"];
+ [dict setObject:titles forKey:@"Titles"];
+ NSMutableArray *values = [NSMutableArray arrayWithArray:[dict objectForKey:@"Values"]];
+ [values removeObject:@"SRTP"];
+ [dict setObject:values forKey:@"Values"];
+ }
+ if (!linphone_core_media_encryption_supported([LinphoneManager getLc], LinphoneMediaEncryptionDTLS)) {
NSMutableArray *titles = [NSMutableArray arrayWithArray:[dict objectForKey:@"Titles"]];
[titles removeObject:@"DTLS"];
[dict setObject:titles forKey:@"Titles"];
@@ -566,127 +563,135 @@ static UICompositeViewDescription *compositeDescription = nil;
[values removeObject:@"DTLS"];
[dict setObject:values forKey:@"Values"];
}
- return [[IASKSpecifier alloc] initWithSpecifier:dict];
- }
+ return [[IASKSpecifier alloc] initWithSpecifier:dict];
+ }
-#endif //HAVE_SSL
+#endif // HAVE_SSL
+ // Add "build from source" if MPEG4 or H264 disabled
+ if ([[specifier key] isEqualToString:@"h264_preference"] && ![LinphoneManager isCodecSupported:"h264"]) {
+ return [SettingsViewController disableCodecSpecifier:specifier];
+ }
+ if ([[specifier key] isEqualToString:@"mp4v-es_preference"] && ![LinphoneManager isCodecSupported:"mp4v-es"]) {
+ return [SettingsViewController disableCodecSpecifier:specifier];
+ }
- // Add "build from source" if MPEG4 or H264 disabled
- if ([[specifier key] isEqualToString:@"h264_preference"] && ![LinphoneManager isCodecSupported:"h264"]) {
- return [SettingsViewController disableCodecSpecifier:specifier];
- }
- if ([[specifier key] isEqualToString:@"mp4v-es_preference"] && ![LinphoneManager isCodecSupported:"mp4v-es"]) {
- return [SettingsViewController disableCodecSpecifier:specifier];
- }
-
- return specifier;
+ return specifier;
}
-- (NSSet*)findHiddenKeys {
- LinphoneManager* lm = [LinphoneManager instance];
- NSMutableSet *hiddenKeys = [NSMutableSet set];
+- (NSSet *)findHiddenKeys {
+ LinphoneManager *lm = [LinphoneManager instance];
+ NSMutableSet *hiddenKeys = [NSMutableSet set];
#ifndef HAVE_SSL
[hiddenKeys addObject:@"media_encryption_preference"];
#endif
#ifndef DEBUG
- [hiddenKeys addObject:@"release_button"];
- [hiddenKeys addObject:@"clear_cache_button"];
- [hiddenKeys addObject:@"battery_alert_button"];
+ [hiddenKeys addObject:@"release_button"];
+ [hiddenKeys addObject:@"clear_cache_button"];
+ [hiddenKeys addObject:@"battery_alert_button"];
#endif
- if (! [[LinphoneManager instance] lpConfigBoolForKey:@"debugenable_preference"]) {
+ if (![[LinphoneManager instance] lpConfigBoolForKey:@"debugenable_preference"]) {
[hiddenKeys addObject:@"send_logs_button"];
[hiddenKeys addObject:@"reset_logs_button"];
}
- [hiddenKeys addObject:@"playback_gain_preference"];
- [hiddenKeys addObject:@"microphone_gain_preference"];
+ [hiddenKeys addObject:@"playback_gain_preference"];
+ [hiddenKeys addObject:@"microphone_gain_preference"];
- [hiddenKeys addObject:@"network_limit_group"];
- [hiddenKeys addObject:@"upload_bandwidth_preference"];
- [hiddenKeys addObject:@"download_bandwidth_preference"];
+ [hiddenKeys addObject:@"network_limit_group"];
- [hiddenKeys addObject:@"incoming_call_timeout_preference"];
- [hiddenKeys addObject:@"in_call_timeout_preference"];
+ [hiddenKeys addObject:@"incoming_call_timeout_preference"];
+ [hiddenKeys addObject:@"in_call_timeout_preference"];
- [hiddenKeys addObject:@"wifi_only_preference"];
+ [hiddenKeys addObject:@"wifi_only_preference"];
- [hiddenKeys addObject:@"quit_button"]; // Hide for the moment
- [hiddenKeys addObject:@"about_button"]; // Hide for the moment
+ [hiddenKeys addObject:@"quit_button"]; // Hide for the moment
+ [hiddenKeys addObject:@"about_button"]; // Hide for the moment
- if (!linphone_core_video_supported([LinphoneManager getLc]))
- [hiddenKeys addObject:@"video_menu"];
+ if (!linphone_core_video_supported([LinphoneManager getLc]))
+ [hiddenKeys addObject:@"video_menu"];
- if (![LinphoneManager isNotIphone3G])
- [hiddenKeys addObject:@"silk_24k_preference"];
+ if (![LinphoneManager isNotIphone3G])
+ [hiddenKeys addObject:@"silk_24k_preference"];
- UIDevice* device = [UIDevice currentDevice];
- if (![device respondsToSelector:@selector(isMultitaskingSupported)] || ![device isMultitaskingSupported]) {
- [hiddenKeys addObject:@"backgroundmode_preference"];
- [hiddenKeys addObject:@"start_at_boot_preference"];
- } else {
- if(![lm lpConfigBoolForKey:@"backgroundmode_preference"]) {
- [hiddenKeys addObject:@"start_at_boot_preference"];
- }
- }
+ UIDevice *device = [UIDevice currentDevice];
+ if (![device respondsToSelector:@selector(isMultitaskingSupported)] || ![device isMultitaskingSupported]) {
+ [hiddenKeys addObject:@"backgroundmode_preference"];
+ [hiddenKeys addObject:@"start_at_boot_preference"];
+ } else {
+ if (![lm lpConfigBoolForKey:@"backgroundmode_preference"]) {
+ [hiddenKeys addObject:@"start_at_boot_preference"];
+ }
+ }
- [hiddenKeys addObject:@"enable_first_login_view_preference"];
+ [hiddenKeys addObject:@"enable_first_login_view_preference"];
#ifndef VIDEO_ENABLED
- [hiddenKeys addObject:@"enable_video_preference"];
-#endif //VIDEO_ENABLED
+ [hiddenKeys addObject:@"enable_video_preference"];
+#endif // VIDEO_ENABLED
- if (!linphone_core_video_enabled([LinphoneManager getLc])) {
- [hiddenKeys addObject:@"video_menu"];
- }
+ if (!linphone_core_video_enabled([LinphoneManager getLc])) {
+ [hiddenKeys addObject:@"video_menu"];
+ }
+ if (!linphone_core_get_video_preset([LinphoneManager getLc]) ||
+ strcmp(linphone_core_get_video_preset([LinphoneManager getLc]), "custom") != 0) {
+ [hiddenKeys addObject:@"video_preferred_fps_preference"];
+ [hiddenKeys addObject:@"download_bandwidth_preference"];
+ }
- [hiddenKeys addObjectsFromArray:[[LinphoneManager unsupportedCodecs] allObjects]];
+ [hiddenKeys addObjectsFromArray:[[LinphoneManager unsupportedCodecs] allObjects]];
- BOOL random_port = [lm lpConfigBoolForKey:@"random_port_preference"];
- if(random_port) {
- [hiddenKeys addObject:@"port_preference"];
- }
+ BOOL random_port = [lm lpConfigBoolForKey:@"random_port_preference"];
+ if (random_port) {
+ [hiddenKeys addObject:@"port_preference"];
+ }
- if(linphone_core_get_stun_server([LinphoneManager getLc]) == NULL) {
- [hiddenKeys addObject:@"ice_preference"];
- }
+ if (linphone_core_get_stun_server([LinphoneManager getLc]) == NULL) {
+ [hiddenKeys addObject:@"ice_preference"];
+ }
- if(![lm lpConfigBoolForKey:@"debugenable_preference"]) {
- [hiddenKeys addObject:@"console_button"];
- }
+ if (![lm lpConfigBoolForKey:@"debugenable_preference"]) {
+ [hiddenKeys addObject:@"console_button"];
+ }
- if(![LinphoneManager runningOnIpad]) {
- [hiddenKeys addObject:@"preview_preference"];
- }
- if([lm lpConfigBoolForKey:@"hide_run_assistant_preference"]) {
+ if (![LinphoneManager runningOnIpad]) {
+ [hiddenKeys addObject:@"preview_preference"];
+ }
+ if ([lm lpConfigBoolForKey:@"hide_run_assistant_preference"]) {
[hiddenKeys addObject:@"wizard_button"];
}
- if (!linphone_core_tunnel_available()){
+ if (!linphone_core_tunnel_available()) {
[hiddenKeys addObject:@"tunnel_menu"];
}
- if( ![lm lpConfigBoolForKey:@"advanced_account_preference"] ){
- [hiddenKeys addObject:@"userid_preference"];
- [hiddenKeys addObject:@"proxy_preference"];
- [hiddenKeys addObject:@"outbound_proxy_preference"];
- [hiddenKeys addObject:@"avpf_preference"];
- }
+ if (![lm lpConfigBoolForKey:@"advanced_account_preference"]) {
+ [hiddenKeys addObject:@"userid_preference"];
+ [hiddenKeys addObject:@"proxy_preference"];
+ [hiddenKeys addObject:@"outbound_proxy_preference"];
+ [hiddenKeys addObject:@"avpf_preference"];
+ }
if (![[[LinphoneManager instance] iapManager] enabled]) {
[hiddenKeys addObject:@"in_app_products_button"];
}
- return hiddenKeys;
+ if ([[UIDevice currentDevice].systemVersion floatValue] < 8) {
+ [hiddenKeys addObject:@"repeat_call_notification_preference"];
+ }
+
+ return hiddenKeys;
}
- (void)goToWizard {
- WizardViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[WizardViewController compositeViewDescription]], WizardViewController);
- if(controller != nil) {
+ WizardViewController *controller =
+ DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[WizardViewController compositeViewDescription]],
+ WizardViewController);
+ if (controller != nil) {
[controller reset];
}
}
@@ -696,57 +701,66 @@ static UICompositeViewDescription *compositeDescription = nil;
- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController *)sender {
}
-- (void)settingsViewController:(IASKAppSettingsViewController*)sender buttonTappedForSpecifier:(IASKSpecifier*)specifier {
- NSString *key = [specifier.specifierDict objectForKey:kIASKKey];
- LinphoneCore* lc = [LinphoneManager getLc];
+- (void)settingsViewController:(IASKAppSettingsViewController *)sender
+ buttonTappedForSpecifier:(IASKSpecifier *)specifier {
+ NSString *key = [specifier.specifierDict objectForKey:kIASKKey];
+ LinphoneCore *lc = [LinphoneManager getLc];
#ifdef DEBUG
- if([key isEqual:@"release_button"]) {
- [UIApplication sharedApplication].keyWindow.rootViewController = nil;
- [[UIApplication sharedApplication].keyWindow setRootViewController:nil];
- [[LinphoneManager instance] destroyLinphoneCore];
- [LinphoneManager instanceRelease];
- } else if([key isEqual:@"clear_cache_button"]) {
- [[PhoneMainView instance].mainViewController clearCache:[NSArray arrayWithObject:[[PhoneMainView instance] currentView]]];
- } else if([key isEqual:@"battery_alert_button"]) {
- [[UIDevice currentDevice] _setBatteryState:UIDeviceBatteryStateUnplugged];
- [[UIDevice currentDevice] _setBatteryLevel:0.01f];
- [[NSNotificationCenter defaultCenter] postNotificationName:UIDeviceBatteryLevelDidChangeNotification object:self];
- }
+ if ([key isEqual:@"release_button"]) {
+ [UIApplication sharedApplication].keyWindow.rootViewController = nil;
+ [[UIApplication sharedApplication].keyWindow setRootViewController:nil];
+ [[LinphoneManager instance] destroyLinphoneCore];
+ [LinphoneManager instanceRelease];
+ } else if ([key isEqual:@"clear_cache_button"]) {
+ [[PhoneMainView instance]
+ .mainViewController clearCache:[NSArray arrayWithObject:[[PhoneMainView instance] currentView]]];
+ } else if ([key isEqual:@"battery_alert_button"]) {
+ [[UIDevice currentDevice] _setBatteryState:UIDeviceBatteryStateUnplugged];
+ [[UIDevice currentDevice] _setBatteryLevel:0.01f];
+ [[NSNotificationCenter defaultCenter] postNotificationName:UIDeviceBatteryLevelDidChangeNotification
+ object:self];
+ }
#endif
- if([key isEqual:@"wizard_button"]) {
- if (linphone_core_get_default_proxy_config(lc) == NULL ) {
+ if ([key isEqual:@"wizard_button"]) {
+ if (linphone_core_get_default_proxy_config(lc) == NULL) {
[self goToWizard];
return;
}
- UIAlertView* alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Warning",nil)
- message:NSLocalizedString(@"Launching the Wizard will delete any existing proxy config.\nAre you sure to want it?",nil)
- delegate:self
- cancelButtonTitle:NSLocalizedString(@"Cancel",nil)
- otherButtonTitles:NSLocalizedString(@"Launch Wizard",nil), nil];
- [alert show];
- } else if ( [key isEqual:@"clear_proxy_button"] ) {
- if ( linphone_core_get_default_proxy_config(lc) == NULL ) {
+ UIAlertView *alert = [[UIAlertView alloc]
+ initWithTitle:NSLocalizedString(@"Warning", nil)
+ message:
+ NSLocalizedString(
+ @"Launching the Wizard will delete any existing proxy config.\nAre you sure to want it?",
+ nil)
+ delegate:self
+ cancelButtonTitle:NSLocalizedString(@"Cancel", nil)
+ otherButtonTitles:NSLocalizedString(@"Launch Wizard", nil), nil];
+ [alert show];
+ } else if ([key isEqual:@"clear_proxy_button"]) {
+ if (linphone_core_get_default_proxy_config(lc) == NULL) {
return;
}
- DTAlertView* alert = [[DTAlertView alloc] initWithTitle:NSLocalizedString(@"Warning", nil) message:NSLocalizedString(@"Are you sure to want to clear your proxy setup?",nil)];
+ DTAlertView *alert = [[DTAlertView alloc]
+ initWithTitle:NSLocalizedString(@"Warning", nil)
+ message:NSLocalizedString(@"Are you sure to want to clear your proxy setup?", nil)];
[alert addCancelButtonWithTitle:NSLocalizedString(@"Cancel", nil) block:nil];
[alert addButtonWithTitle:NSLocalizedString(@"Yes", nil)
block:^{
- linphone_core_clear_proxy_config(lc);
- linphone_core_clear_all_auth_info(lc);
- [settingsStore transformLinphoneCoreToKeys];
- [settingsController.tableView reloadData];
+ linphone_core_clear_proxy_config(lc);
+ linphone_core_clear_all_auth_info(lc);
+ [settingsStore transformLinphoneCoreToKeys];
+ [settingsController.tableView reloadData];
}];
[alert show];
- } else if([key isEqual:@"about_button"]) {
- [[PhoneMainView instance] changeCurrentView:[AboutViewController compositeViewDescription] push:TRUE];
+ } else if ([key isEqual:@"about_button"]) {
+ [[PhoneMainView instance] changeCurrentView:[AboutViewController compositeViewDescription] push:TRUE];
} else if ([key isEqualToString:@"reset_logs_button"]) {
linphone_core_reset_log_collection();
} else if ([key isEqual:@"send_logs_button"]) {
- char * filepath = linphone_core_compress_log_collection(lc);
+ char *filepath = linphone_core_compress_log_collection(lc);
if (filepath == NULL) {
LOGE(@"Cannot sent logs: file is NULL");
return;
@@ -768,59 +782,66 @@ static UICompositeViewDescription *compositeDescription = nil;
LOGE(@"Unknown extension type: %@, cancelling email", filename);
return;
}
- [self emailAttachment:[NSData dataWithContentsOfFile:[NSString stringWithUTF8String:filepath]] mimeType:mimeType name:filename];
+ [self emailAttachment:[NSData dataWithContentsOfFile:[NSString stringWithUTF8String:filepath]]
+ mimeType:mimeType
+ name:filename];
ms_free(filepath);
- } else if([key isEqual:@"in_app_products_button"]) {
- [[PhoneMainView instance] changeCurrentView:[InAppProductsViewController compositeViewDescription] push:TRUE];
}
}
#pragma mark - UIAlertView delegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
- if( buttonIndex != 1 ) return; /* cancel */
- else [self goToWizard];
+ if (buttonIndex != 1)
+ return; /* cancel */
+ else
+ [self goToWizard];
}
#pragma mark - Mail composer for send log
-- (void)emailAttachment: (NSData*)attachment mimeType:(NSString*)type name:(NSString*)attachmentName
-{
+- (void)emailAttachment:(NSData *)attachment mimeType:(NSString *)type name:(NSString *)attachmentName {
if (attachmentName == nil || type == nil || attachmentName == nil) {
LOGE(@"Trying to email attachment but mandatory field is missing");
return;
}
#if TARGET_IPHONE_SIMULATOR
- UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Cannot send email",nil)
- message:NSLocalizedString(@"Simulator cannot send emails. To test this feature, please use a real device.",nil)
- delegate:nil
- cancelButtonTitle:NSLocalizedString(@"Continue",nil)
- otherButtonTitles:nil];
+ UIAlertView *error = [[UIAlertView alloc]
+ initWithTitle:NSLocalizedString(@"Cannot send email", nil)
+ message:NSLocalizedString(
+ @"Simulator cannot send emails. To test this feature, please use a real device.", nil)
+ delegate:nil
+ cancelButtonTitle:NSLocalizedString(@"Continue", nil)
+ otherButtonTitles:nil];
[error show];
#else
if ([MFMailComposeViewController canSendMail] == YES) {
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
- [picker setSubject:NSLocalizedString(@"Linphone Logs",nil)];
+ [picker setSubject:NSLocalizedString(@"Linphone Logs", nil)];
[picker setToRecipients:[NSArray arrayWithObjects:@"linphone-iphone@belledonne-communications.com", nil]];
[picker setMessageBody:NSLocalizedString(@"Linphone logs", nil) isHTML:NO];
[picker addAttachmentData:attachment mimeType:type fileName:attachmentName];
[self presentViewController:picker animated:true completion:nil];
} else {
- UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Cannot send email",nil)
- message:NSLocalizedString(@"Your device is not configured to send emails. Please configure mail application prior to send logs.",nil)
- delegate:nil
- cancelButtonTitle:NSLocalizedString(@"Continue",nil)
- otherButtonTitles:nil];
+ UIAlertView *error = [[UIAlertView alloc]
+ initWithTitle:NSLocalizedString(@"Cannot send email", nil)
+ message:NSLocalizedString(@"Your device is not configured to send emails. Please configure mail "
+ @"application prior to send logs.",
+ nil)
+ delegate:nil
+ cancelButtonTitle:NSLocalizedString(@"Continue", nil)
+ otherButtonTitles:nil];
[error show];
}
#endif
}
-- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
-{
+- (void)mailComposeController:(MFMailComposeViewController *)controller
+ didFinishWithResult:(MFMailComposeResult)result
+ error:(NSError *)error {
if (error != nil) {
LOGW(@"Error while sending mail: %@", error);
} else {
diff --git a/Classes/Utils/FileTransferDelegate.h b/Classes/Utils/FileTransferDelegate.h
new file mode 100644
index 000000000..a62af10e0
--- /dev/null
+++ b/Classes/Utils/FileTransferDelegate.h
@@ -0,0 +1,20 @@
+//
+// FileTransferDelegate.h
+// linphone
+//
+// Created by Gautier Pelloux-Prayer on 10/06/15.
+//
+//
+
+#import
+
+#import "LinphoneManager.h"
+
+@interface FileTransferDelegate : NSObject
+
+- (void)upload:(UIImage *)image withURL:(NSURL *)url forChatRoom:(LinphoneChatRoom *)chatRoom;
+- (void)cancel;
+- (BOOL)download:(LinphoneChatMessage *)message;
+
+@property() LinphoneChatMessage *message;
+@end
diff --git a/Classes/Utils/FileTransferDelegate.m b/Classes/Utils/FileTransferDelegate.m
new file mode 100644
index 000000000..36419cbf4
--- /dev/null
+++ b/Classes/Utils/FileTransferDelegate.m
@@ -0,0 +1,207 @@
+//
+// FileTransferDelegate.m
+// linphone
+//
+// Created by Gautier Pelloux-Prayer on 10/06/15.
+//
+//
+
+#import "FileTransferDelegate.h"
+@interface FileTransferDelegate ()
+@property(strong) NSMutableData *data;
+@end
+
+@implementation FileTransferDelegate
+
+- (void)dealloc {
+ if (_message != nil) {
+ [self cancel];
+ }
+}
+
+static void linphone_iphone_file_transfer_recv(LinphoneChatMessage *message, const LinphoneContent *content,
+ const LinphoneBuffer *buffer) {
+ FileTransferDelegate *thiz = (__bridge FileTransferDelegate *)linphone_chat_message_get_user_data(message);
+ size_t size = linphone_buffer_get_size(buffer);
+
+ if (!thiz.data) {
+ thiz.data = [[NSMutableData alloc] initWithCapacity:linphone_content_get_size(content)];
+ }
+
+ if (size == 0) {
+ LOGI(@"Transfer of %s (%d bytes): download finished", linphone_content_get_name(content), size);
+ assert([thiz.data length] == linphone_content_get_size(content));
+
+ // we're finished, save the image and update the message
+ UIImage *image = [UIImage imageWithData:thiz.data];
+
+
+ [[[LinphoneManager instance] fileTransferDelegates] removeObject:thiz];
+
+ [[LinphoneManager instance]
+ .photoLibrary
+ writeImageToSavedPhotosAlbum:image.CGImage
+ orientation:(ALAssetOrientation)[image imageOrientation]
+ completionBlock:^(NSURL *assetURL, NSError *error) {
+ if (error) {
+ LOGE(@"Cannot save image data downloaded [%@]", [error localizedDescription]);
+
+ UIAlertView *errorAlert = [[UIAlertView alloc]
+ initWithTitle:NSLocalizedString(@"Transfer error", nil)
+ message:NSLocalizedString(@"Cannot write image to photo library", nil)
+ delegate:nil
+ cancelButtonTitle:NSLocalizedString(@"Ok", nil)
+ otherButtonTitles:nil, nil];
+ [errorAlert show];
+ } else {
+ LOGI(@"Image saved to [%@]", [assetURL absoluteString]);
+ [LinphoneManager setValueInMessageAppData:[assetURL absoluteString]
+ forKey:@"localimage"
+ inMessage:message];
+ }
+ thiz.message = NULL;
+ [[NSNotificationCenter defaultCenter]
+ postNotificationName:kLinphoneFileTransferRecvUpdate
+ object:thiz
+ userInfo:@{
+ @"state" : @(linphone_chat_message_get_state(message)),
+ @"image" : image,
+ @"progress" :
+ @([thiz.data length] * 1.f / linphone_content_get_size(content)),
+ }];
+
+ CFRelease((__bridge CFTypeRef)thiz);
+ }];
+ } else {
+ LOGD(@"Transfer of %s (%d bytes): already %ld sent, adding %ld", linphone_content_get_name(content),
+ linphone_content_get_size(content), [thiz.data length], size);
+ [thiz.data appendBytes:linphone_buffer_get_string_content(buffer) length:size];
+ [[NSNotificationCenter defaultCenter]
+ postNotificationName:kLinphoneFileTransferRecvUpdate
+ object:thiz
+ userInfo:@{
+ @"state" : @(linphone_chat_message_get_state(message)),
+ @"progress" : @([thiz.data length] * 1.f / linphone_content_get_size(content)),
+ }];
+ }
+}
+
+static LinphoneBuffer *linphone_iphone_file_transfer_send(LinphoneChatMessage *message, const LinphoneContent *content,
+ size_t offset, size_t size) {
+ FileTransferDelegate *thiz = (__bridge FileTransferDelegate *)linphone_chat_message_get_user_data(message);
+ size_t total = thiz.data.length;
+ if (thiz.data) {
+ size_t remaining = total - offset;
+
+ NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:@{
+ @"state" : @(linphone_chat_message_get_state(message)),
+ @"progress" : @(offset * 1.f / total),
+ }];
+ LOGD(@"Transfer of %s (%d bytes): already sent %ld, remaining %ld", linphone_content_get_name(content), total,
+ offset, remaining);
+ [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneFileTransferSendUpdate
+ object:thiz
+ userInfo:dict];
+ @try {
+ return linphone_buffer_new_from_data([thiz.data subdataWithRange:NSMakeRange(offset, size)].bytes, size);
+ } @catch (NSException *exception) {
+ LOGE(@"Exception: %@", exception);
+ }
+ } else {
+ LOGE(@"Transfer of %s (%d bytes): %d Error - no upload data in progress!", linphone_content_get_name(content),
+ total, offset);
+ }
+
+ return NULL;
+}
+
+static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState state) {
+ FileTransferDelegate *thiz = (__bridge FileTransferDelegate *)linphone_chat_message_get_user_data(msg);
+
+ NSString *notification =
+ linphone_chat_message_is_outgoing(msg) ? kLinphoneFileTransferSendUpdate : kLinphoneFileTransferRecvUpdate;
+
+ const char *text = (linphone_chat_message_get_file_transfer_information(msg) != NULL)
+ ? "photo transfer"
+ : linphone_chat_message_get_text(msg);
+ LOGI(@"Delivery status for [%s] is [%s]", text, linphone_chat_message_state_to_string(state));
+
+ NSDictionary *dict = @{ @"state" : @(state), @"progress" : @0.f };
+ if (state == LinphoneChatMessageStateFileTransferDone || state == LinphoneChatMessageStateFileTransferError) {
+ thiz.message = NULL;
+ }
+ [[NSNotificationCenter defaultCenter] postNotificationName:notification object:thiz userInfo:dict];
+ if (linphone_chat_message_is_outgoing(msg)) {
+ [thiz stopAndDestroy];
+ }
+}
+
+- (void)upload:(UIImage *)image withURL:(NSURL *)url forChatRoom:(LinphoneChatRoom *)chatRoom {
+ LinphoneContent *content = linphone_core_create_content(linphone_chat_room_get_lc(chatRoom));
+ _data = [NSMutableData dataWithData:UIImageJPEGRepresentation(image, 1.0)];
+ linphone_content_set_type(content, "image");
+ linphone_content_set_subtype(content, "jpeg");
+ linphone_content_set_name(content,
+ [[NSString stringWithFormat:@"%li-%f.jpg", (long)[image hash],
+ [NSDate timeIntervalSinceReferenceDate]] UTF8String]);
+ linphone_content_set_size(content, [_data length]);
+
+ CFTypeRef myself = (__bridge CFTypeRef)self;
+ _message = linphone_chat_room_create_file_transfer_message(chatRoom, content);
+ linphone_chat_message_ref(_message);
+ linphone_chat_message_set_user_data(_message, (void *)CFRetain(myself));
+ linphone_chat_message_cbs_set_file_transfer_send(linphone_chat_message_get_callbacks(_message),
+ linphone_iphone_file_transfer_send);
+ linphone_chat_message_cbs_set_msg_state_changed(linphone_chat_message_get_callbacks(_message), message_status);
+
+ if (url) {
+ // internal url is saved in the appdata for display and later save
+ [LinphoneManager setValueInMessageAppData:[url absoluteString] forKey:@"localimage" inMessage:_message];
+ }
+
+ linphone_chat_room_send_chat_message(chatRoom, _message);
+}
+
+- (BOOL)download:(LinphoneChatMessage *)message {
+ _message = message;
+ // we need to keep a ref on the message to continue downloading even if user quit a chatroom which destroy all chat
+ // messages
+ linphone_chat_message_ref(_message);
+ const char *url = linphone_chat_message_get_external_body_url(_message);
+ LOGI(@"Content to download: %s", url);
+
+ if (url == nil)
+ return FALSE;
+
+ linphone_chat_message_set_user_data(_message, (void *)CFBridgingRetain(self));
+
+ linphone_chat_message_cbs_set_file_transfer_recv(linphone_chat_message_get_callbacks(_message),
+ linphone_iphone_file_transfer_recv);
+ linphone_chat_message_cbs_set_msg_state_changed(linphone_chat_message_get_callbacks(_message), message_status);
+
+ linphone_chat_message_download_file(_message);
+
+ return TRUE;
+}
+
+- (void)stopAndDestroy {
+ [[[LinphoneManager instance] fileTransferDelegates] removeObject:self];
+ if (_message != NULL) {
+ linphone_chat_message_set_user_data(_message, NULL);
+
+ linphone_chat_message_cbs_set_file_transfer_progress_indication(linphone_chat_message_get_callbacks(_message),
+ NULL);
+ linphone_chat_message_cbs_set_file_transfer_recv(linphone_chat_message_get_callbacks(_message), NULL);
+ linphone_chat_message_cbs_set_msg_state_changed(linphone_chat_message_get_callbacks(_message), NULL);
+ linphone_chat_message_cancel_file_transfer(_message);
+ linphone_chat_message_unref(_message);
+ }
+ _message = nil;
+ _data = nil;
+}
+
+- (void)cancel {
+ [self stopAndDestroy];
+}
+
+@end
diff --git a/Classes/Utils/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.m b/Classes/Utils/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.m
index 6e1791aec..533eb508b 100755
--- a/Classes/Utils/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.m
+++ b/Classes/Utils/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.m
@@ -105,6 +105,7 @@
}
- (void)viewDidUnload {
+ [super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.tableView = nil;
diff --git a/Classes/Utils/UIAlertView+Blocks/UIAlertView+Blocks.h b/Classes/Utils/UIAlertView+Blocks/UIAlertView+Blocks.h
new file mode 100644
index 000000000..d5372d8d2
--- /dev/null
+++ b/Classes/Utils/UIAlertView+Blocks/UIAlertView+Blocks.h
@@ -0,0 +1,59 @@
+//
+// UIAlertView+Blocks.h
+// UIAlertViewBlocks
+//
+// Created by Ryan Maxwell on 29/08/13.
+//
+// The MIT License (MIT)
+//
+// Copyright (c) 2013 Ryan Maxwell
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do so,
+// subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#import
+
+typedef void (^UIAlertViewBlock) (UIAlertView *alertView);
+typedef void (^UIAlertViewCompletionBlock) (UIAlertView *alertView, NSInteger buttonIndex);
+
+@interface UIAlertView (Blocks)
+
++ (instancetype)showWithTitle:(NSString *)title
+ message:(NSString *)message
+ style:(UIAlertViewStyle)style
+ cancelButtonTitle:(NSString *)cancelButtonTitle
+ otherButtonTitles:(NSArray *)otherButtonTitles
+ tapBlock:(UIAlertViewCompletionBlock)tapBlock;
+
++ (instancetype)showWithTitle:(NSString *)title
+ message:(NSString *)message
+ cancelButtonTitle:(NSString *)cancelButtonTitle
+ otherButtonTitles:(NSArray *)otherButtonTitles
+ tapBlock:(UIAlertViewCompletionBlock)tapBlock;
+
+@property (copy, nonatomic) UIAlertViewCompletionBlock tapBlock;
+@property (copy, nonatomic) UIAlertViewCompletionBlock willDismissBlock;
+@property (copy, nonatomic) UIAlertViewCompletionBlock didDismissBlock;
+
+@property (copy, nonatomic) UIAlertViewBlock willPresentBlock;
+@property (copy, nonatomic) UIAlertViewBlock didPresentBlock;
+@property (copy, nonatomic) UIAlertViewBlock cancelBlock;
+
+@property (copy, nonatomic) BOOL(^shouldEnableFirstOtherButtonBlock)(UIAlertView *alertView);
+
+@end
diff --git a/Classes/Utils/UIAlertView+Blocks/UIAlertView+Blocks.m b/Classes/Utils/UIAlertView+Blocks/UIAlertView+Blocks.m
new file mode 100644
index 000000000..2cdfd71ff
--- /dev/null
+++ b/Classes/Utils/UIAlertView+Blocks/UIAlertView+Blocks.m
@@ -0,0 +1,264 @@
+//
+// UIAlertView+Blocks.m
+// UIAlertViewBlocks
+//
+// Created by Ryan Maxwell on 29/08/13.
+//
+// The MIT License (MIT)
+//
+// Copyright (c) 2013 Ryan Maxwell
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do so,
+// subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#import "UIAlertView+Blocks.h"
+
+#import
+
+static const void *UIAlertViewOriginalDelegateKey = &UIAlertViewOriginalDelegateKey;
+
+static const void *UIAlertViewTapBlockKey = &UIAlertViewTapBlockKey;
+static const void *UIAlertViewWillPresentBlockKey = &UIAlertViewWillPresentBlockKey;
+static const void *UIAlertViewDidPresentBlockKey = &UIAlertViewDidPresentBlockKey;
+static const void *UIAlertViewWillDismissBlockKey = &UIAlertViewWillDismissBlockKey;
+static const void *UIAlertViewDidDismissBlockKey = &UIAlertViewDidDismissBlockKey;
+static const void *UIAlertViewCancelBlockKey = &UIAlertViewCancelBlockKey;
+static const void *UIAlertViewShouldEnableFirstOtherButtonBlockKey = &UIAlertViewShouldEnableFirstOtherButtonBlockKey;
+
+@implementation UIAlertView (Blocks)
+
++ (instancetype)showWithTitle:(NSString *)title
+ message:(NSString *)message
+ style:(UIAlertViewStyle)style
+ cancelButtonTitle:(NSString *)cancelButtonTitle
+ otherButtonTitles:(NSArray *)otherButtonTitles
+ tapBlock:(UIAlertViewCompletionBlock)tapBlock {
+
+ NSString *firstObject = otherButtonTitles.count ? otherButtonTitles[0] : nil;
+
+ UIAlertView *alertView = [[self alloc] initWithTitle:title
+ message:message
+ delegate:nil
+ cancelButtonTitle:cancelButtonTitle
+ otherButtonTitles:firstObject, nil];
+
+ alertView.alertViewStyle = style;
+
+ if (otherButtonTitles.count > 1) {
+ for (NSString *buttonTitle in [otherButtonTitles subarrayWithRange:NSMakeRange(1, otherButtonTitles.count - 1)]) {
+ [alertView addButtonWithTitle:buttonTitle];
+ }
+ }
+
+ if (tapBlock) {
+ alertView.tapBlock = tapBlock;
+ }
+
+ [alertView show];
+
+#if !__has_feature(objc_arc)
+ return [alertView autorelease];
+#else
+ return alertView;
+#endif
+}
+
+
++ (instancetype)showWithTitle:(NSString *)title
+ message:(NSString *)message
+ cancelButtonTitle:(NSString *)cancelButtonTitle
+ otherButtonTitles:(NSArray *)otherButtonTitles
+ tapBlock:(UIAlertViewCompletionBlock)tapBlock {
+
+ return [self showWithTitle:title
+ message:message
+ style:UIAlertViewStyleDefault
+ cancelButtonTitle:cancelButtonTitle
+ otherButtonTitles:otherButtonTitles
+ tapBlock:tapBlock];
+}
+
+#pragma mark -
+
+- (void)_checkAlertViewDelegate {
+ if (self.delegate != (id)self) {
+ objc_setAssociatedObject(self, UIAlertViewOriginalDelegateKey, self.delegate, OBJC_ASSOCIATION_ASSIGN);
+ self.delegate = (id)self;
+ }
+}
+
+- (UIAlertViewCompletionBlock)tapBlock {
+ return objc_getAssociatedObject(self, UIAlertViewTapBlockKey);
+}
+
+- (void)setTapBlock:(UIAlertViewCompletionBlock)tapBlock {
+ [self _checkAlertViewDelegate];
+ objc_setAssociatedObject(self, UIAlertViewTapBlockKey, tapBlock, OBJC_ASSOCIATION_COPY);
+}
+
+- (UIAlertViewCompletionBlock)willDismissBlock {
+ return objc_getAssociatedObject(self, UIAlertViewWillDismissBlockKey);
+}
+
+- (void)setWillDismissBlock:(UIAlertViewCompletionBlock)willDismissBlock {
+ [self _checkAlertViewDelegate];
+ objc_setAssociatedObject(self, UIAlertViewWillDismissBlockKey, willDismissBlock, OBJC_ASSOCIATION_COPY);
+}
+
+- (UIAlertViewCompletionBlock)didDismissBlock {
+ return objc_getAssociatedObject(self, UIAlertViewDidDismissBlockKey);
+}
+
+- (void)setDidDismissBlock:(UIAlertViewCompletionBlock)didDismissBlock {
+ [self _checkAlertViewDelegate];
+ objc_setAssociatedObject(self, UIAlertViewDidDismissBlockKey, didDismissBlock, OBJC_ASSOCIATION_COPY);
+}
+
+- (UIAlertViewBlock)willPresentBlock {
+ return objc_getAssociatedObject(self, UIAlertViewWillPresentBlockKey);
+}
+
+- (void)setWillPresentBlock:(UIAlertViewBlock)willPresentBlock {
+ [self _checkAlertViewDelegate];
+ objc_setAssociatedObject(self, UIAlertViewWillPresentBlockKey, willPresentBlock, OBJC_ASSOCIATION_COPY);
+}
+
+- (UIAlertViewBlock)didPresentBlock {
+ return objc_getAssociatedObject(self, UIAlertViewDidPresentBlockKey);
+}
+
+- (void)setDidPresentBlock:(UIAlertViewBlock)didPresentBlock {
+ [self _checkAlertViewDelegate];
+ objc_setAssociatedObject(self, UIAlertViewDidPresentBlockKey, didPresentBlock, OBJC_ASSOCIATION_COPY);
+}
+
+- (UIAlertViewBlock)cancelBlock {
+ return objc_getAssociatedObject(self, UIAlertViewCancelBlockKey);
+}
+
+- (void)setCancelBlock:(UIAlertViewBlock)cancelBlock {
+ [self _checkAlertViewDelegate];
+ objc_setAssociatedObject(self, UIAlertViewCancelBlockKey, cancelBlock, OBJC_ASSOCIATION_COPY);
+}
+
+- (void)setShouldEnableFirstOtherButtonBlock:(BOOL(^)(UIAlertView *alertView))shouldEnableFirstOtherButtonBlock {
+ [self _checkAlertViewDelegate];
+ objc_setAssociatedObject(self, UIAlertViewShouldEnableFirstOtherButtonBlockKey, shouldEnableFirstOtherButtonBlock, OBJC_ASSOCIATION_COPY);
+}
+
+- (BOOL(^)(UIAlertView *alertView))shouldEnableFirstOtherButtonBlock {
+ return objc_getAssociatedObject(self, UIAlertViewShouldEnableFirstOtherButtonBlockKey);
+}
+
+#pragma mark - UIAlertViewDelegate
+
+- (void)willPresentAlertView:(UIAlertView *)alertView {
+ UIAlertViewBlock block = alertView.willPresentBlock;
+
+ if (block) {
+ block(alertView);
+ }
+
+ id originalDelegate = objc_getAssociatedObject(self, UIAlertViewOriginalDelegateKey);
+ if (originalDelegate && [originalDelegate respondsToSelector:@selector(willPresentAlertView:)]) {
+ [originalDelegate willPresentAlertView:alertView];
+ }
+}
+
+- (void)didPresentAlertView:(UIAlertView *)alertView {
+ UIAlertViewBlock block = alertView.didPresentBlock;
+
+ if (block) {
+ block(alertView);
+ }
+
+ id originalDelegate = objc_getAssociatedObject(self, UIAlertViewOriginalDelegateKey);
+ if (originalDelegate && [originalDelegate respondsToSelector:@selector(didPresentAlertView:)]) {
+ [originalDelegate didPresentAlertView:alertView];
+ }
+}
+
+
+- (void)alertViewCancel:(UIAlertView *)alertView {
+ UIAlertViewBlock block = alertView.cancelBlock;
+
+ if (block) {
+ block(alertView);
+ }
+
+ id originalDelegate = objc_getAssociatedObject(self, UIAlertViewOriginalDelegateKey);
+ if (originalDelegate && [originalDelegate respondsToSelector:@selector(alertViewCancel:)]) {
+ [originalDelegate alertViewCancel:alertView];
+ }
+}
+
+- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
+ UIAlertViewCompletionBlock completion = alertView.tapBlock;
+
+ if (completion) {
+ completion(alertView, buttonIndex);
+ }
+
+ id originalDelegate = objc_getAssociatedObject(self, UIAlertViewOriginalDelegateKey);
+ if (originalDelegate && [originalDelegate respondsToSelector:@selector(alertView:clickedButtonAtIndex:)]) {
+ [originalDelegate alertView:alertView clickedButtonAtIndex:buttonIndex];
+ }
+}
+
+- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex {
+ UIAlertViewCompletionBlock completion = alertView.willDismissBlock;
+
+ if (completion) {
+ completion(alertView, buttonIndex);
+ }
+
+ id originalDelegate = objc_getAssociatedObject(self, UIAlertViewOriginalDelegateKey);
+ if (originalDelegate && [originalDelegate respondsToSelector:@selector(alertView:willDismissWithButtonIndex:)]) {
+ [originalDelegate alertView:alertView willDismissWithButtonIndex:buttonIndex];
+ }
+}
+
+- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
+ UIAlertViewCompletionBlock completion = alertView.didDismissBlock;
+
+ if (completion) {
+ completion(alertView, buttonIndex);
+ }
+
+ id originalDelegate = objc_getAssociatedObject(self, UIAlertViewOriginalDelegateKey);
+ if (originalDelegate && [originalDelegate respondsToSelector:@selector(alertView:didDismissWithButtonIndex:)]) {
+ [originalDelegate alertView:alertView didDismissWithButtonIndex:buttonIndex];
+ }
+}
+
+- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView {
+ BOOL(^shouldEnableFirstOtherButtonBlock)(UIAlertView *alertView) = alertView.shouldEnableFirstOtherButtonBlock;
+
+ if (shouldEnableFirstOtherButtonBlock) {
+ return shouldEnableFirstOtherButtonBlock(alertView);
+ }
+
+ id originalDelegate = objc_getAssociatedObject(self, UIAlertViewOriginalDelegateKey);
+ if (originalDelegate && [originalDelegate respondsToSelector:@selector(alertViewShouldEnableFirstOtherButton:)]) {
+ return [originalDelegate alertViewShouldEnableFirstOtherButton:alertView];
+ }
+
+ return YES;
+}
+
+@end
diff --git a/Classes/Utils/Utils.m b/Classes/Utils/Utils.m
index c9d56d7d1..971a7da71 100644
--- a/Classes/Utils/Utils.m
+++ b/Classes/Utils/Utils.m
@@ -29,7 +29,10 @@
OrtpLogLevel ortp_severity;
int filesize = 20;
if (severity <= LinphoneLoggerDebug) {
- ortp_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]);
+ return;
} else if(severity <= LinphoneLoggerLog) {
ortp_severity = ORTP_MESSAGE;
} else if(severity <= LinphoneLoggerWarning) {
diff --git a/KifTests/ChatTester.m b/KifTests/ChatTester.m
index 1b0056fc5..76cd623c5 100644
--- a/KifTests/ChatTester.m
+++ b/KifTests/ChatTester.m
@@ -8,6 +8,7 @@
#import "ChatTester.h"
#include "LinphoneManager.h"
+#import "UIChatRoomCell.h"
@implementation ChatTester
@@ -17,12 +18,36 @@
- (void)beforeAll {
[super beforeAll];
[self switchToValidAccountIfNeeded];
-
- [tester tapViewWithAccessibilityLabel:LOCALIZED(@"Chat")];
+}
+
+- (void)beforeEach {
+ [super beforeEach];
+ if ([tester tryFindingTappableViewWithAccessibilityLabel:LOCALIZED(@"Back") error:nil]) {
+ [self goBackFromChat];
+ }
+ [tester tapViewWithAccessibilityLabel:LOCALIZED(@"Chat")];
+ [self removeAllRooms];
+}
+
+- (void)afterAll {
+ // at the end of tests, go back to chat rooms to display main bar
+ if ([tester tryFindingTappableViewWithAccessibilityLabel:LOCALIZED(@"Back") error:nil]) {
+ [self goBackFromChat];
+ }
}
#pragma mark - tools
+- (void)removeAllRooms {
+ [tester tapViewWithAccessibilityLabel:@"Edit" traits:UIAccessibilityTraitButton];
+ while (
+ [tester tryFindingTappableViewWithAccessibilityLabel:@"Delete" traits:UIAccessibilityTraitButton error:nil]) {
+ [tester tapViewWithAccessibilityLabel:@"Delete" traits:UIAccessibilityTraitButton];
+ }
+ [tester tapViewWithAccessibilityLabel:@"Edit"
+ traits:UIAccessibilityTraitButton]; // same as the first but it is "OK" on screen
+}
+
- (void)goBackFromChat {
[tester tapViewWithAccessibilityLabel:LOCALIZED(@"Back")];
}
@@ -114,29 +139,100 @@
for( int i =0; i< uuids.count; i++){
[tester tapViewWithAccessibilityLabel:@"Delete" traits:UIAccessibilityTraitButton];
}
-
- // then we try to delete all the rest of chatrooms
- while ( [tester tryFindingTappableViewWithAccessibilityLabel:@"Delete" traits:UIAccessibilityTraitButton error:nil] )
- {
- [tester tapViewWithAccessibilityLabel:@"Delete" traits:UIAccessibilityTraitButton];
- NSLog(@"Deleting an extra chat");
- }
-
- [tester tapViewWithAccessibilityLabel:@"Edit" traits:UIAccessibilityTraitButton]; // same as the first but it is "OK" on screen
-
- // check that the tableview is empty
- UITableView* tv = nil;
- NSError* err = nil;
- if( [tester tryFindingAccessibilityElement:nil view:&tv withIdentifier:@"ChatRoom list" tappable:false error:&err] ){
- XCTAssert(tv != nil);
- XCTAssert([tv numberOfRowsInSection:0] == 0); // no more chat rooms
- } else {
- NSLog(@"Error: %@",err);
- }
-
- // test that there's no more chatrooms in the core
- XCTAssert(linphone_core_get_chat_rooms([LinphoneManager getLc]) == nil);
+
+ [tester tapViewWithAccessibilityLabel:@"Edit"
+ traits:UIAccessibilityTraitButton]; // same as the first but it is "OK" on screen
+
+ // check that the tableview is empty
+ UITableView *tv = [self findTableView:@"ChatRoom list"];
+ XCTAssert([tv numberOfRowsInSection:0] == 0);
+
+ // test that there's no more chatrooms in the core
+ XCTAssert(linphone_core_get_chat_rooms([LinphoneManager getLc]) == nil);
}
+- (UITableView *)findTableView:(NSString *)table {
+ UITableView *tv = nil;
+ NSError *err = nil;
+ if ([tester tryFindingAccessibilityElement:nil view:&tv withIdentifier:table tappable:false error:&err]) {
+ XCTAssertNotNil(tv);
+ } else {
+ XCTFail(@"Error: %@", err);
+ }
+ return tv;
+}
+
+- (void)uploadImage {
+ NSString *user = @"testios";
+
+ [self startChatWith:user];
+
+ [tester tapViewWithAccessibilityLabel:LOCALIZED(@"Send picture")];
+ [tester tapViewWithAccessibilityLabel:LOCALIZED(@"Photo library")];
+ // if popup "Linphone would access your photo" pops up, click OK.
+ if ([ALAssetsLibrary authorizationStatus] == ALAuthorizationStatusNotDetermined) {
+#if TARGET_IPHONE_SIMULATOR
+ [tester acknowledgeSystemAlert];
+#endif
+ }
+
+ [tester choosePhotoInAlbum:@"Camera Roll" atRow:1 column:1];
+
+ // TODO: do not harcode size!
+ [tester tapViewWithAccessibilityLabel:LOCALIZED(@"Minimum (108.9 KB)")];
+
+ UITableView *tv = [self findTableView:@"Chat list"];
+ XCTAssertEqual([tv numberOfRowsInSection:0], 1);
+ XCTAssertEqual([[[LinphoneManager instance] fileTransferDelegates] count], 1);
+}
+
+- (void)testUploadImage {
+ NSString *user = @"testios";
+
+ [self uploadImage];
+ [self goBackFromChat];
+
+ // if we go back to the same chatroom, the message should be still there
+ [self startChatWith:user];
+ UITableView *tv = [self findTableView:@"Chat list"];
+ XCTAssertEqual([tv numberOfRowsInSection:0], 1);
+
+ [tester waitForViewWithAccessibilityLabel:LOCALIZED(@"Download")];
+
+ XCTAssertEqual([tv numberOfRowsInSection:0], 2);
+ XCTAssertEqual([[[LinphoneManager instance] fileTransferDelegates] count], 0);
+}
+
+- (void)testCancelUploadImage {
+ [self uploadImage];
+ [tester tapViewWithAccessibilityLabel:LOCALIZED(@"Cancel transfer")];
+ XCTAssertEqual([[[LinphoneManager instance] fileTransferDelegates] count], 0);
+}
+
+- (void)downloadImage {
+ [self uploadImage];
+ // wait for the upload to terminate...
+ for (int i = 0; i < 15; i++) {
+ [tester waitForTimeInterval:1.f];
+ if ([[[LinphoneManager instance] fileTransferDelegates] count] == 0)
+ break;
+ }
+ [tester waitForViewWithAccessibilityLabel:LOCALIZED(@"Download")];
+ [tester tapViewWithAccessibilityLabel:LOCALIZED(@"Download")];
+ [tester waitForTimeInterval:.5f]; // just wait a few secs to start download
+ XCTAssertEqual([[[LinphoneManager instance] fileTransferDelegates] count], 1);
+}
+
+- (void)testDownloadImage {
+ [self downloadImage];
+ [tester waitForAbsenceOfViewWithAccessibilityLabel:@"Cancel transfer"];
+ XCTAssertEqual([[[LinphoneManager instance] fileTransferDelegates] count], 0);
+}
+
+- (void)testCancelDownloadImage {
+ [self downloadImage];
+ [tester tapViewWithAccessibilityLabel:LOCALIZED(@"Cancel transfer")];
+ XCTAssertEqual([[[LinphoneManager instance] fileTransferDelegates] count], 0);
+}
@end
diff --git a/Resources/licenses.html b/Resources/licenses.html
index 31b1bdba7..183077683 100644
--- a/Resources/licenses.html
+++ b/Resources/licenses.html
@@ -37,6 +37,11 @@
http://www.tortuga22.com
Apache license
+Ryan Maxwell
+UIAlertview+Blocks
+https://github.com/ryanmaxwell/UIAlertView-Blocks
+MIT license
+
OrderedDictionary
Matt Gallagher
http://cocoawithlove.com
diff --git a/Resources/linphonerc b/Resources/linphonerc
index 0f3e852c7..b773a7c27 100644
--- a/Resources/linphonerc
+++ b/Resources/linphonerc
@@ -73,7 +73,7 @@ username_length=4
expires=1314000
push_notification=1
transport=tls
-sharing_server=https://www.linphone.org:444/upload.php
+sharing_server=https://www.linphone.org:444/lft.php
ice=1
stun=stun.linphone.org
diff --git a/Resources/linphonerc~ipad b/Resources/linphonerc~ipad
index 787349e1a..d2e96d5c1 100644
--- a/Resources/linphonerc~ipad
+++ b/Resources/linphonerc~ipad
@@ -73,7 +73,7 @@ username_length=4
expires=1314000
push_notification=1
transport=tls
-sharing_server=https://www.linphone.org:444/upload.php
+sharing_server=https://www.linphone.org:444/lft.php
ice=1
stun=stun.linphone.org
diff --git a/Resources/wizard_linphone_create.rc b/Resources/wizard_linphone_create.rc
index 292d662d4..e023f4454 100644
--- a/Resources/wizard_linphone_create.rc
+++ b/Resources/wizard_linphone_create.rc
@@ -22,7 +22,7 @@
1
- https://www.linphone.org:444/upload.php
+ https://www.linphone.org:444/lft.php
1
stun.linphone.org
1
diff --git a/Resources/wizard_linphone_existing.rc b/Resources/wizard_linphone_existing.rc
index 2244776e8..1e71c41d3 100644
--- a/Resources/wizard_linphone_existing.rc
+++ b/Resources/wizard_linphone_existing.rc
@@ -22,7 +22,7 @@
1
- https://www.linphone.org:444/upload.php
+ https://www.linphone.org:444/lft.php
1
stun.linphone.org
1
diff --git a/Settings/InAppSettings.bundle/Audio.plist b/Settings/InAppSettings.bundle/Audio.plist
index b9b3278f4..e61a70df2 100644
--- a/Settings/InAppSettings.bundle/Audio.plist
+++ b/Settings/InAppSettings.bundle/Audio.plist
@@ -218,36 +218,6 @@
IASKTextAlignment
IASKUITextAlignmentRight
-
- DefaultValue
-
- Key
- adaptive_rate_control_preference
- Title
- Adaptive rate control
- Type
- PSToggleSwitchSpecifier
-
-
- DefaultValue
- Simple
- Key
- adaptive_rate_algorithm_preference
- Title
- Adaptive rate algorithm
- Titles
-
- Simple
- Stateful
-
- Type
- PSMultiValueSpecifier
- Values
-
- Simple
- Stateful
-
-
DefaultValue
36
diff --git a/Settings/InAppSettings.bundle/Call.plist b/Settings/InAppSettings.bundle/Call.plist
index ae0855c79..61ec80f69 100644
--- a/Settings/InAppSettings.bundle/Call.plist
+++ b/Settings/InAppSettings.bundle/Call.plist
@@ -106,6 +106,16 @@
IASKTextAlignment
IASKUITextAlignmentRight
+
+ DefaultValue
+
+ Key
+ repeat_call_notification_preference
+ Title
+ Repeat call notification
+ Type
+ PSToggleSwitchSpecifier
+
diff --git a/Settings/InAppSettings.bundle/Network.plist b/Settings/InAppSettings.bundle/Network.plist
index 4eb893d65..e97766b92 100644
--- a/Settings/InAppSettings.bundle/Network.plist
+++ b/Settings/InAppSettings.bundle/Network.plist
@@ -156,31 +156,41 @@
Key
- upload_bandwidth_preference
+ adaptive_rate_control_group
Title
- Upload bandwidth
+ Adaptive rate control
Type
- PSTextFieldSpecifier
- KeyboardType
- NumberPad
- DefaultValue
- 0
- IASKTextAlignment
- IASKUITextAlignmentRight
+ PSGroupSpecifier
- Key
- download_bandwidth_preference
- Title
- Download bandwidth
- Type
- PSTextFieldSpecifier
- KeyboardType
- NumberPad
DefaultValue
- 0
- IASKTextAlignment
- IASKUITextAlignmentRight
+
+ Key
+ adaptive_rate_control_preference
+ Title
+ Adaptive rate control
+ Type
+ PSToggleSwitchSpecifier
+
+
+ DefaultValue
+ Simple
+ Key
+ adaptive_rate_algorithm_preference
+ Title
+ Adaptive rate algorithm
+ Titles
+
+ Simple
+ Stateful
+
+ Type
+ PSMultiValueSpecifier
+ Values
+
+ Simple
+ Stateful
+
diff --git a/Settings/InAppSettings.bundle/Root.plist b/Settings/InAppSettings.bundle/Root.plist
index a3ad75a6c..dedc25c2d 100644
--- a/Settings/InAppSettings.bundle/Root.plist
+++ b/Settings/InAppSettings.bundle/Root.plist
@@ -242,14 +242,6 @@
Type
PSChildPaneSpecifier
-
- Key
- in_app_products_button
- Title
- Extra features
- Type
- IASKButtonSpecifier
-
Title
Development debug actions
@@ -276,7 +268,7 @@
Key
release_button
Title
- Exit
+ Release core
Type
IASKButtonSpecifier
diff --git a/Settings/InAppSettings.bundle/Video.plist b/Settings/InAppSettings.bundle/Video.plist
index 71e8964ff..4d72625e6 100644
--- a/Settings/InAppSettings.bundle/Video.plist
+++ b/Settings/InAppSettings.bundle/Video.plist
@@ -41,8 +41,28 @@
preview_preference
+ Key
+ video_preset_preference
+ Title
+ Video preset
+ Titles
+
+ Default
+ High FPS
+ Custom
+
+ Type
+ PSMultiValueSpecifier
+ Values
+
+ default
+ high-fps
+ custom
+
DefaultValue
- 1
+ default
+
+
Key
video_preferred_size_preference
Title
@@ -61,6 +81,56 @@
1
2
+ DefaultValue
+ 1
+
+
+ Key
+ video_preferred_fps_preference
+ Title
+ Preferred FPS
+ Type
+ PSMultiValueSpecifier
+ Titles
+
+ No preference
+ 5
+ 10
+ 15
+ 20
+ 25
+ 30
+
+ Values
+
+ 0
+ 5
+ 10
+ 15
+ 20
+ 25
+ 30
+
+ DefaultValue
+ 0
+
+
+ Key
+ download_bandwidth_preference
+ Title
+ Bandwidth limit in kbits/s
+ Type
+ PSTextFieldSpecifier
+ AutocapitalizationType
+ None
+ AutocorrectionType
+ No
+ KeyboardType
+ NumberPad
+ DefaultValue
+ 380
+ IASKTextAlignment
+ IASKUITextAlignmentRight
Title
diff --git a/linphone.xcodeproj/project.pbxproj b/linphone.xcodeproj/project.pbxproj
index cc23c79d1..b96c6ad3b 100755
--- a/linphone.xcodeproj/project.pbxproj
+++ b/linphone.xcodeproj/project.pbxproj
@@ -111,20 +111,17 @@
630CF5571AF7CE1500539F7A /* UITextField+DoneButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 630CF5561AF7CE1500539F7A /* UITextField+DoneButton.m */; };
631C4FB119D2A8F2004BFE77 /* UIDigitButtonLongPlus.m in Sources */ = {isa = PBXBuildFile; fileRef = 631C4FB019D2A8F2004BFE77 /* UIDigitButtonLongPlus.m */; };
631C4FB719D2C3A6004BFE77 /* UIDigitButtonLongVoiceMail.m in Sources */ = {isa = PBXBuildFile; fileRef = 631C4FB619D2C3A6004BFE77 /* UIDigitButtonLongVoiceMail.m */; };
- 6359DE7F1ADEB54200EA15C0 /* InAppProductsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6359DE7D1ADEB54200EA15C0 /* InAppProductsViewController.m */; };
- 6359DE801ADEB54200EA15C0 /* InAppProductsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6359DE7E1ADEB54200EA15C0 /* InAppProductsViewController.xib */; };
- 6359DE841ADEB64100EA15C0 /* InAppProductsCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6359DE821ADEB64100EA15C0 /* InAppProductsCell.m */; };
- 6359DE851ADEB64100EA15C0 /* InAppProductsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6359DE831ADEB64100EA15C0 /* InAppProductsCell.xib */; };
- 6359DE8B1ADF9EB900EA15C0 /* InAppProductsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6359DE8A1ADF9EB900EA15C0 /* InAppProductsTableViewController.m */; };
636316D11A1DEBCB0009B839 /* AboutViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 636316D31A1DEBCB0009B839 /* AboutViewController.xib */; };
636316D41A1DEC650009B839 /* SettingsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 636316D61A1DEC650009B839 /* SettingsViewController.xib */; };
636316D91A1DECC90009B839 /* PhoneMainView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 636316D71A1DECC90009B839 /* PhoneMainView.xib */; };
636316DE1A1DEF2F0009B839 /* UIButtonShrinkable.m in Sources */ = {isa = PBXBuildFile; fileRef = 636316DD1A1DEF2F0009B839 /* UIButtonShrinkable.m */; };
+ 637157A11B283FE200C91677 /* FileTransferDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 637157A01B283FE200C91677 /* FileTransferDelegate.m */; };
639CEAFD1A1DF4D9004DE38F /* UIStateBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEAFF1A1DF4D9004DE38F /* UIStateBar.xib */; };
639CEB001A1DF4E4004DE38F /* UIHistoryCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEB021A1DF4E4004DE38F /* UIHistoryCell.xib */; };
639CEB031A1DF4EB004DE38F /* UICompositeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEB051A1DF4EB004DE38F /* UICompositeViewController.xib */; };
639CEB061A1DF4F1004DE38F /* UIChatRoomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEB081A1DF4F1004DE38F /* UIChatRoomCell.xib */; };
639CEB091A1DF4FA004DE38F /* UIChatCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEB0B1A1DF4FA004DE38F /* UIChatCell.xib */; };
+ 63A4280A1B26F576000DAB93 /* libSKP_SILK_SDK.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 226183AA1472527D0037138E /* libSKP_SILK_SDK.a */; };
63CD4B4F1A5AAC8C00B84282 /* DTAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = 63CD4B4E1A5AAC8C00B84282 /* DTAlertView.m */; };
63D2680F1B174A5E00A2CC11 /* numpad_one_voicemail_default.png in Resources */ = {isa = PBXBuildFile; fileRef = 63D2680D1B174A5E00A2CC11 /* numpad_one_voicemail_default.png */; };
63D268101B174A5E00A2CC11 /* numpad_one_voicemail_over.png in Resources */ = {isa = PBXBuildFile; fileRef = 63D2680E1B174A5E00A2CC11 /* numpad_one_voicemail_over.png */; };
@@ -305,7 +302,6 @@
D36C43F7158F61EA0048BA40 /* call_state_play_over.png in Resources */ = {isa = PBXBuildFile; fileRef = D36C43F0158F61EA0048BA40 /* call_state_play_over.png */; };
D36FB2D51589EF7C0036F6F2 /* UIPauseButton.m in Sources */ = {isa = PBXBuildFile; fileRef = D36FB2D41589EF7C0036F6F2 /* UIPauseButton.m */; };
D37295DB158B3C9600D2C0C7 /* video_off_disabled.png in Resources */ = {isa = PBXBuildFile; fileRef = D37295DA158B3C9600D2C0C7 /* video_off_disabled.png */; };
- D374D3FD16071762003D25FF /* ImageSharing.m in Sources */ = {isa = PBXBuildFile; fileRef = D374D3FC16071762003D25FF /* ImageSharing.m */; };
D377BBFA15A19DA6002B696B /* video_on_disabled.png in Resources */ = {isa = PBXBuildFile; fileRef = D377BBF915A19DA6002B696B /* video_on_disabled.png */; };
D378906515AC373B00BD776C /* ContactDetailsLabelViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D378906315AC373B00BD776C /* ContactDetailsLabelViewController.m */; };
D378AB2A15DCDB4A0098505D /* ImagePickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D378AB2915DCDB490098505D /* ImagePickerViewController.m */; };
@@ -891,7 +887,6 @@
/* Begin PBXFileReference section */
045B5CB218D72E9A0088350C /* libbzrtp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbzrtp.a; path = "liblinphone-sdk/apple-darwin/lib/libbzrtp.a"; sourceTree = ""; };
- 15017E6F1773578400784ACB /* libxml2.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libxml2.a; path = "liblinphone-sdk/apple-darwin/lib/libxml2.a"; sourceTree = ""; };
152F22331B15E83B008C0621 /* libilbcrfc3951.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libilbcrfc3951.a; path = "liblinphone-sdk/apple-darwin/lib/libilbcrfc3951.a"; sourceTree = ""; };
152F22351B15E889008C0621 /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = usr/lib/libxml2.dylib; sourceTree = SDKROOT; };
1560821E18EEF26100765332 /* libmsopenh264.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmsopenh264.a; path = "liblinphone-sdk/apple-darwin/lib/mediastreamer/plugins/libmsopenh264.a"; sourceTree = ""; };
@@ -1023,14 +1018,6 @@
631C4FB519D2C3A6004BFE77 /* UIDigitButtonLongVoiceMail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIDigitButtonLongVoiceMail.h; sourceTree = ""; };
631C4FB619D2C3A6004BFE77 /* UIDigitButtonLongVoiceMail.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIDigitButtonLongVoiceMail.m; sourceTree = ""; };
633E388219FFB0F400936D1C /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; };
- 6359DE7C1ADEB54200EA15C0 /* InAppProductsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InAppProductsViewController.h; sourceTree = ""; };
- 6359DE7D1ADEB54200EA15C0 /* InAppProductsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InAppProductsViewController.m; sourceTree = ""; };
- 6359DE7E1ADEB54200EA15C0 /* InAppProductsViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = InAppProductsViewController.xib; sourceTree = ""; };
- 6359DE811ADEB64100EA15C0 /* InAppProductsCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InAppProductsCell.h; sourceTree = ""; };
- 6359DE821ADEB64100EA15C0 /* InAppProductsCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InAppProductsCell.m; sourceTree = ""; };
- 6359DE831ADEB64100EA15C0 /* InAppProductsCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = InAppProductsCell.xib; sourceTree = ""; };
- 6359DE891ADF9EB900EA15C0 /* InAppProductsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InAppProductsTableViewController.h; sourceTree = ""; };
- 6359DE8A1ADF9EB900EA15C0 /* InAppProductsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InAppProductsTableViewController.m; sourceTree = ""; };
636316D21A1DEBCB0009B839 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/AboutViewController.xib; sourceTree = ""; };
636316D51A1DEC650009B839 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/SettingsViewController.xib; sourceTree = ""; };
636316D81A1DECC90009B839 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PhoneMainView.xib; sourceTree = ""; };
@@ -1038,6 +1025,8 @@
636316DB1A1DEDD80009B839 /* ru */ = {isa = PBXFileReference; fileEncoding = 2483028224; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/HistoryDetailsViewController.strings; sourceTree = ""; };
636316DC1A1DEECB0009B839 /* UIButtonShrinkable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIButtonShrinkable.h; sourceTree = ""; };
636316DD1A1DEF2F0009B839 /* UIButtonShrinkable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIButtonShrinkable.m; sourceTree = ""; };
+ 6371579F1B283FE200C91677 /* FileTransferDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileTransferDelegate.h; path = Utils/FileTransferDelegate.h; sourceTree = ""; };
+ 637157A01B283FE200C91677 /* FileTransferDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FileTransferDelegate.m; path = Utils/FileTransferDelegate.m; sourceTree = ""; };
639CEAFE1A1DF4D9004DE38F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UIStateBar.xib; sourceTree = ""; };
639CEB011A1DF4E4004DE38F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UIHistoryCell.xib; sourceTree = ""; };
639CEB041A1DF4EB004DE38F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UICompositeViewController.xib; sourceTree = ""; };
@@ -1257,8 +1246,6 @@
D36FB2D31589EF7C0036F6F2 /* UIPauseButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIPauseButton.h; sourceTree = ""; };
D36FB2D41589EF7C0036F6F2 /* UIPauseButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIPauseButton.m; sourceTree = ""; };
D37295DA158B3C9600D2C0C7 /* video_off_disabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = video_off_disabled.png; path = Resources/video_off_disabled.png; sourceTree = ""; };
- D374D3FB16071762003D25FF /* ImageSharing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageSharing.h; sourceTree = ""; };
- D374D3FC16071762003D25FF /* ImageSharing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImageSharing.m; sourceTree = ""; };
D377BBF915A19DA6002B696B /* video_on_disabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = video_on_disabled.png; path = Resources/video_on_disabled.png; sourceTree = ""; };
D378906215AC373B00BD776C /* ContactDetailsLabelViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactDetailsLabelViewController.h; sourceTree = ""; };
D378906315AC373B00BD776C /* ContactDetailsLabelViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactDetailsLabelViewController.m; sourceTree = ""; };
@@ -1865,6 +1852,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 63A4280A1B26F576000DAB93 /* libSKP_SILK_SDK.a in Frameworks */,
152F22361B15E889008C0621 /* libxml2.dylib in Frameworks */,
152F22341B15E83B008C0621 /* libilbcrfc3951.a in Frameworks */,
F0B026F31AA710AF00FF49F7 /* libiconv.dylib in Frameworks */,
@@ -2039,21 +2027,11 @@
D38187D415FE346B00C3EDCA /* HistoryViewController.xib */,
D378AB2815DCDB480098505D /* ImagePickerViewController.h */,
D378AB2915DCDB490098505D /* ImagePickerViewController.m */,
- D374D3FB16071762003D25FF /* ImageSharing.h */,
- D374D3FC16071762003D25FF /* ImageSharing.m */,
22405EFD1601C19000B92522 /* ImageViewController.h */,
22405EFE1601C19100B92522 /* ImageViewController.m */,
D37EE11016035793003608A6 /* ImageViewController.xib */,
- 6359DE811ADEB64100EA15C0 /* InAppProductsCell.h */,
- 6359DE821ADEB64100EA15C0 /* InAppProductsCell.m */,
- 6359DE831ADEB64100EA15C0 /* InAppProductsCell.xib */,
63E59A3D1ADE6ECB00646FB3 /* InAppProductsManager.h */,
63E59A3E1ADE70D900646FB3 /* InAppProductsManager.m */,
- 6359DE891ADF9EB900EA15C0 /* InAppProductsTableViewController.h */,
- 6359DE8A1ADF9EB900EA15C0 /* InAppProductsTableViewController.m */,
- 6359DE7C1ADEB54200EA15C0 /* InAppProductsViewController.h */,
- 6359DE7D1ADEB54200EA15C0 /* InAppProductsViewController.m */,
- 6359DE7E1ADEB54200EA15C0 /* InAppProductsViewController.xib */,
D31AAF5C159B3919002C6B02 /* InCallTableViewController.h */,
D31AAF5D159B3919002C6B02 /* InCallTableViewController.m */,
D3F83EE91582021700336684 /* InCallViewController.h */,
@@ -2317,7 +2295,6 @@
D30BF33216A427BC00AF0026 /* libtunnel.a */,
7066FC0B13E830E400EFC6DC /* libvpx.a */,
22AA8AFB13D7125500B30535 /* libx264.a */,
- 15017E6F1773578400784ACB /* libxml2.a */,
F0B89C2118DC89E30050B60E /* MediaPlayer.framework */,
D37DC7171594AF3400B2A5EB /* MessageUI.framework */,
226EF06B15FA256B005865C7 /* MobileCoreServices.framework */,
@@ -2343,6 +2320,8 @@
D37EE15F160377D7003608A6 /* DTFoundation */,
D32B9DFA15A2F131000B6DEC /* FastAddressBook.h */,
D32B9DFB15A2F131000B6DEC /* FastAddressBook.m */,
+ 6371579F1B283FE200C91677 /* FileTransferDelegate.h */,
+ 637157A01B283FE200C91677 /* FileTransferDelegate.m */,
D3ED40141602172200BF332B /* GrowingTextView */,
D3807FC715C2894A005BE9BC /* InAppSettingsKit */,
D3B90E1115C2CB5700F64F8C /* NinePatch.xcodeproj */,
@@ -3342,7 +3321,6 @@
D38327F71580FE3A00FA0D23 /* settings_default.png in Resources */,
D38327F81580FE3A00FA0D23 /* settings_selected.png in Resources */,
D38327F91580FE3A00FA0D23 /* chat_default.png in Resources */,
- 6359DE801ADEB54200EA15C0 /* InAppProductsViewController.xib in Resources */,
D38327FA1580FE3A00FA0D23 /* chat_selected.png in Resources */,
D3832800158100E400FA0D23 /* contacts_over.png in Resources */,
D3832801158100E400FA0D23 /* history_over.png in Resources */,
@@ -3379,7 +3357,6 @@
D3F83F581582223B00336684 /* numpad_five_default.png in Resources */,
D3F83F5A1582223B00336684 /* numpad_five_over.png in Resources */,
D3F83F5C1582223B00336684 /* numpad_six_default.png in Resources */,
- 6359DE851ADEB64100EA15C0 /* InAppProductsCell.xib in Resources */,
636316D91A1DECC90009B839 /* PhoneMainView.xib in Resources */,
D3F83F5E1582223B00336684 /* numpad_six_over.png in Resources */,
D3F83F601582223B00336684 /* numpad_seven_default.png in Resources */,
@@ -4052,18 +4029,15 @@
D3807FFC15C2894A005BE9BC /* IASKPSTitleValueSpecifierViewCell.m in Sources */,
D3807FFE15C2894A005BE9BC /* IASKSlider.m in Sources */,
D380800015C2894A005BE9BC /* IASKSwitch.m in Sources */,
- 6359DE8B1ADF9EB900EA15C0 /* InAppProductsTableViewController.m in Sources */,
D380800215C2894A005BE9BC /* IASKTextField.m in Sources */,
D380800515C28A7A005BE9BC /* UILinphone.m in Sources */,
D380801315C299D0005BE9BC /* ColorSpaceUtilites.m in Sources */,
- 6359DE7F1ADEB54200EA15C0 /* InAppProductsViewController.m in Sources */,
+ 637157A11B283FE200C91677 /* FileTransferDelegate.m in Sources */,
D378AB2A15DCDB4A0098505D /* ImagePickerViewController.m in Sources */,
- 6359DE841ADEB64100EA15C0 /* InAppProductsCell.m in Sources */,
22405F001601C19200B92522 /* ImageViewController.m in Sources */,
D3ED40191602172200BF332B /* HPGrowingTextView.m in Sources */,
D3ED401B1602172200BF332B /* HPTextViewInternal.m in Sources */,
D37EE162160377D7003608A6 /* DTActionSheet.m in Sources */,
- D374D3FD16071762003D25FF /* ImageSharing.m in Sources */,
D35E91F4160CA10B0023116B /* UILinphoneTextField.m in Sources */,
D35E91F8160CA4FF0023116B /* UILinphoneButton.m in Sources */,
D306459E1611EC2A00BB571E /* UILoadingImageView.m in Sources */,
diff --git a/prepare.py b/prepare.py
index 50dd95b81..ac9fdfc30 100755
--- a/prepare.py
+++ b/prepare.py
@@ -27,12 +27,14 @@ import os
import re
import shutil
import sys
+from subprocess import Popen
sys.dont_write_bytecode = True
sys.path.insert(0, 'submodules/cmake-builder')
import prepare
class IOSTarget(prepare.Target):
+
def __init__(self, arch):
prepare.Target.__init__(self, 'ios-' + arch)
current_path = os.path.dirname(os.path.realpath(__file__))
@@ -40,62 +42,77 @@ class IOSTarget(prepare.Target):
self.toolchain_file = 'toolchains/toolchain-ios-' + arch + '.cmake'
self.output = 'liblinphone-sdk/' + arch + '-apple-darwin.ios'
self.additional_args = [
- '-DLINPHONE_BUILDER_EXTERNAL_SOURCE_PATH=' + current_path + '/submodules'
+ '-DLINPHONE_BUILDER_EXTERNAL_SOURCE_PATH=' +
+ current_path + '/submodules'
]
def clean(self):
if os.path.isdir('WORK'):
- shutil.rmtree('WORK', ignore_errors=False, onerror=self.handle_remove_read_only)
+ shutil.rmtree(
+ 'WORK', ignore_errors=False, onerror=self.handle_remove_read_only)
if os.path.isdir('liblinphone-sdk'):
- shutil.rmtree('liblinphone-sdk', ignore_errors=False, onerror=self.handle_remove_read_only)
+ shutil.rmtree(
+ 'liblinphone-sdk', ignore_errors=False, onerror=self.handle_remove_read_only)
class IOSi386Target(IOSTarget):
+
def __init__(self):
IOSTarget.__init__(self, 'i386')
+
class IOSx8664Target(IOSTarget):
+
def __init__(self):
IOSTarget.__init__(self, 'x86_64')
+
class IOSarmv7Target(IOSTarget):
+
def __init__(self):
IOSTarget.__init__(self, 'armv7')
+
class IOSarm64Target(IOSTarget):
+
def __init__(self):
IOSTarget.__init__(self, 'arm64')
targets = {}
-targets[ 'i386'] = IOSi386Target()
+targets['i386'] = IOSi386Target()
targets['x86_64'] = IOSx8664Target()
-targets[ 'armv7'] = IOSarmv7Target()
-targets[ 'arm64'] = IOSarm64Target()
+targets['armv7'] = IOSarmv7Target()
+targets['arm64'] = IOSarm64Target()
archs_device = ['arm64', 'armv7']
archs_simu = ['i386', 'x86_64']
platforms = ['all', 'devices', 'simulators'] + archs_device + archs_simu
+
class PlatformListAction(argparse.Action):
+
def __call__(self, parser, namespace, values, option_string=None):
if values:
for value in values:
if value not in platforms:
- message = ("invalid platform: {0!r} (choose from {1})".format(value, ', '.join([repr(platform) for platform in platforms])))
+ message = ("invalid platform: {0!r} (choose from {1})".format(
+ value, ', '.join([repr(platform) for platform in platforms])))
raise argparse.ArgumentError(self, message)
setattr(namespace, self.dest, values)
+
def warning(platforms):
gpl_third_parties_enabled = False
regex = re.compile("^ENABLE_GPL_THIRD_PARTIES:BOOL=ON")
- f = open('WORK/ios-{arch}/cmake/CMakeCache.txt'.format(arch=platforms[0]), 'r')
+ f = open(
+ 'WORK/ios-{arch}/cmake/CMakeCache.txt'.format(arch=platforms[0]), 'r')
for line in f:
if regex.match(line):
gpl_third_parties_enabled = True
break
f.close()
-
+
if gpl_third_parties_enabled:
print("""
***************************************************************************
@@ -121,17 +138,52 @@ def warning(platforms):
""")
-def main(argv = None):
+def extract_libs_list():
+ l = []
+ # name = libspeexdsp.a; path = "liblinphone-sdk/apple-darwin/lib/libspeexdsp.a"; sourceTree = ""; };
+ regex = re.compile("name = (lib(\S+)\.a); path = \"liblinphone-sdk/apple-darwin/")
+ f = open('linphone.xcodeproj/project.pbxproj', 'r')
+ lines = f.readlines()
+ f.close()
+ for line in lines:
+ m = regex.search(line)
+ if m is not None:
+ l += [m.group(1)]
+ return list(set(l))
+
+
+def install_git_hook():
+ git_hook_path = ".git{sep}hooks{sep}pre-commit".format(sep=os.sep)
+ if os.path.isdir(".git{sep}hooks".format(sep=os.sep)) and not os.path.isfile(git_hook_path):
+ print("Installing Git pre-commit hook")
+ shutil.copyfile(".git-pre-commit", git_hook_path)
+ os.chmod(git_hook_path, 0755)
+
+
+def main(argv=None):
if argv is None:
argv = sys.argv
- argparser = argparse.ArgumentParser(description="Prepare build of Linphone and its dependencies.")
- argparser.add_argument('-c', '-C', '--clean', help="Clean a previous build instead of preparing a build.", action='store_true')
- argparser.add_argument('-d', '--debug', help="Prepare a debug build.", action='store_true')
- argparser.add_argument('-f', '--force', help="Force preparation, even if working directory already exist.", action='store_true')
- argparser.add_argument('-L', '--list-cmake-variables', help="List non-advanced CMake cache variables.", action='store_true', dest='list_cmake_variables')
- argparser.add_argument('platform', nargs='*', action=PlatformListAction, default=['all'], help="The platform to build for (default is all), one of: {0}.".format(', '.join([repr(platform) for platform in platforms])))
+ argparser = argparse.ArgumentParser(
+ description="Prepare build of Linphone and its dependencies.")
+ argparser.add_argument(
+ '-c', '-C', '--clean', help="Clean a previous build instead of preparing a build.", action='store_true')
+ argparser.add_argument(
+ '-d', '--debug', help="Prepare a debug build, eg. add debug symbols and use no optimizations.", action='store_true')
+ argparser.add_argument(
+ '-dv', '--debug-verbose', help="Activate ms_debug logs.", action='store_true')
+ argparser.add_argument(
+ '-f', '--force', help="Force preparation, even if working directory already exist.", action='store_true')
+ argparser.add_argument('-L', '--list-cmake-variables',
+ help="List non-advanced CMake cache variables.", action='store_true',
+ dest='list_cmake_variables')
+ argparser.add_argument('platform', nargs='*', action=PlatformListAction, default=[
+ 'x86_64', 'devices'],
+ help="The platform to build for (default is 'x86_64 devices'). Space separated"
+ " architectures in list: {0}.".format(', '.join([repr(platform) for platform in platforms])))
args, additional_args = argparser.parse_known_args()
+ install_git_hook()
+
selected_platforms = []
for platform in args.platform:
if platform == 'all':
@@ -152,14 +204,18 @@ def main(argv = None):
if args.clean:
target.clean()
else:
- if args.debug:
+ if args.debug_verbose:
additional_args += ["-DENABLE_DEBUG_LOGS=YES"]
- retcode = prepare.run(target, args.debug, False, args.list_cmake_variables, args.force, additional_args)
+ retcode = prepare.run(
+ target, args.debug, False, args.list_cmake_variables, args.force, additional_args)
if retcode != 0:
+ if retcode == 51:
+ p = Popen(["make", "help-prepare-options"])
return retcode
makefile_platforms += [platform]
if makefile_platforms:
+ libs_list = extract_libs_list()
packages = os.listdir('WORK/ios-' + makefile_platforms[0] + '/Build')
packages.sort()
arch_targets = ""
@@ -167,6 +223,12 @@ def main(argv = None):
arch_targets += """
{arch}: all-{arch}
+package-in-list-%:
+ if ! grep -q " $* " <<< " $(packages) "; then \\
+ echo "$* not in list of available packages: $(packages)"; \\
+ exit 3; \\
+ fi
+
{arch}-build:
@for package in $(packages); do \\
$(MAKE) {arch}-build-$$package; \\
@@ -182,16 +244,16 @@ def main(argv = None):
$(MAKE) {arch}-veryclean-$$package; \\
done
-{arch}-build-%:
+{arch}-build-%: package-in-list-%
rm -f WORK/ios-{arch}/Stamp/EP_$*/EP_$*-update; \\
$(MAKE) -C WORK/ios-{arch}/cmake EP_$*
-{arch}-clean-%:
+{arch}-clean-%: package-in-list-%
$(MAKE) -C WORK/ios-{arch}/Build/$* clean; \\
rm -f WORK/ios-{arch}/Stamp/EP_$*/EP_$*-build; \\
rm -f WORK/ios-{arch}/Stamp/EP_$*/EP_$*-install;
-{arch}-veryclean-%:
+{arch}-veryclean-%: package-in-list-%
cat WORK/ios-{arch}/Build/$*/install_manifest.txt | xargs rm; \\
rm -rf WORK/ios-{arch}/Build/$*/*; \\
rm -f WORK/ios-{arch}/Stamp/EP_$*/*; \\
@@ -226,7 +288,7 @@ def main(argv = None):
multiarch = ""
for arch in makefile_platforms[1:]:
multiarch += \
-""" if test -f "$${arch}_path"; then \\
+ """ if test -f "$${arch}_path"; then \\
all_paths=`echo $$all_paths $${arch}_path`; \\
all_archs="$$all_archs,{arch}" ; \\
else \\
@@ -236,6 +298,7 @@ def main(argv = None):
makefile = """
archs={archs}
packages={packages}
+libs_list={libs_list}
LINPHONE_IPHONE_VERSION=$(shell git describe --always)
.PHONY: all
@@ -249,19 +312,19 @@ all-%:
done
$(MAKE) -C WORK/ios-$*/cmake
-build-%:
+build-%: package-in-list-%
@for arch in $(archs); do \\
echo "==== starting build of $* for arch $$arch ===="; \\
$(MAKE) $$arch-build-$*; \\
done
-clean-%:
+clean-%: package-in-list-%
@for arch in $(archs); do \\
echo "==== starting clean of $* for arch $$arch ===="; \\
$(MAKE) $$arch-clean-$*; \\
done
-veryclean-%:
+veryclean-%: package-in-list-%
@for arch in $(archs); do \\
echo "==== starting veryclean of $* for arch $$arch ===="; \\
$(MAKE) $$arch-veryclean-$*; \\
@@ -292,9 +355,17 @@ libs: $(addprefix all-,$(archs))
echo "[$$all_archs] Mixing `basename $$archive` in $$destpath"; \\
lipo -create $$all_paths -output $$destpath; \\
done && \\
- if ! test -f liblinphone-sdk/apple-darwin/lib/libtunnel.a ; then \\
- cp -f submodules/binaries/libdummy.a liblinphone-sdk/apple-darwin/lib/libtunnel.a ; \\
- fi
+ for lib in {libs_list} ; do \\
+ if [ $${{lib:0:5}} = "libms" ] ; then \\
+ library_path=liblinphone-sdk/apple-darwin/lib/mediastreamer/plugins/$$lib ; \\
+ else \\
+ library_path=liblinphone-sdk/apple-darwin/lib/$$lib ; \\
+ fi ; \\
+ if ! test -f $$library_path ; then \\
+ echo "[$$all_archs] Generating dummy $$lib static library." ; \\
+ cp -f submodules/binaries/libdummy.a $$library_path ; \\
+ fi \\
+ done
ipa: build
xcodebuild -configuration Release \\
@@ -318,7 +389,12 @@ push-transifex:
zipres:
@tar -czf ios_assets.tar.gz Resources iTunesArtwork
-help:
+help-prepare-options:
+ @echo "prepare.py was previously executed with the following options:"
+ @echo " {options}"
+
+help: help-prepare-options
+ @echo ""
@echo "(please read the README.md file first)"
@echo ""
@echo "Available architectures: {archs}"
@@ -339,7 +415,9 @@ help:
@echo ""
@echo " * sdk : re-add all generated libraries to the SDK. Use this only after a full build."
@echo " * libs : after a rebuild of a subpackage, will mix the new libs in liblinphone-sdk/apple-darwin directory"
-""".format(archs=' '.join(makefile_platforms), arch_opts='|'.join(makefile_platforms), first_arch=makefile_platforms[0], arch_targets=arch_targets, packages=' '.join(packages), multiarch=multiarch)
+""".format(archs=' '.join(makefile_platforms), arch_opts='|'.join(makefile_platforms),
+ first_arch=makefile_platforms[0], options=' '.join(sys.argv),
+ arch_targets=arch_targets, packages=' '.join(packages), libs_list=' '.join(libs_list), multiarch=multiarch)
f = open('Makefile', 'w')
f.write(makefile)
f.close()
diff --git a/submodules/belle-sip b/submodules/belle-sip
index 611762072..7780031ed 160000
--- a/submodules/belle-sip
+++ b/submodules/belle-sip
@@ -1 +1 @@
-Subproject commit 611762072933bf7bcbac9848bfead5a367a22ded
+Subproject commit 7780031ed6742e6653c3718ed506c851d129f86f
diff --git a/submodules/binaries/dummy.c b/submodules/binaries/dummy.c
new file mode 100644
index 000000000..bf722ecc4
--- /dev/null
+++ b/submodules/binaries/dummy.c
@@ -0,0 +1,6 @@
+//regenerate libdummy.a using:
+// for arch in arm64 armv7 i386 x86_64; do
+// clang -c dummy.c -o dummy-$arch.a -arch $arch
+// done
+// lipo -create -output libdummy.a dummy-*.a
+void dummy_does_nothing() {}
diff --git a/submodules/binaries/libdummy.a b/submodules/binaries/libdummy.a
index a4910d080..7f9f9467f 100644
Binary files a/submodules/binaries/libdummy.a and b/submodules/binaries/libdummy.a differ
diff --git a/submodules/build/builder-iphone-os.mk b/submodules/build/builder-iphone-os.mk
index 01c8f6cdf..d1273ffa2 100644
--- a/submodules/build/builder-iphone-os.mk
+++ b/submodules/build/builder-iphone-os.mk
@@ -155,7 +155,7 @@ init:
mkdir -p $(prefix)/include
mkdir -p $(prefix)/lib/pkgconfig
-veryclean: veryclean-linphone
+veryclean: veryclean-linphone
rm -rf $(BUILDER_BUILD_DIR)
list-packages:
diff --git a/submodules/build/builders.d/libilbc.mk b/submodules/build/builders.d/libilbc.mk
index 6cc5c2411..b52414a0b 100644
--- a/submodules/build/builders.d/libilbc.mk
+++ b/submodules/build/builders.d/libilbc.mk
@@ -15,7 +15,8 @@ $(LIBILBC_BUILD_DIR)/Makefile: $(LIBILBC_SRC_DIR)/configure
$(LIBILBC_SRC_DIR)/configure -prefix=$(prefix) --host=$(host) $(library_mode)
build-libilbc: $(LIBILBC_BUILD_DIR)/Makefile
- cd $(LIBILBC_BUILD_DIR) && make && make install
+ cd $(LIBILBC_BUILD_DIR) && make && make install && \
+ mv $(prefix)/lib/libilbc.a $(prefix)/lib/libilbcrfc3951.a
clean-libilbc:
cd $(LIBILBC_BUILD_DIR) && make clean
diff --git a/submodules/cmake-builder b/submodules/cmake-builder
index cf6ad6e18..3955daa45 160000
--- a/submodules/cmake-builder
+++ b/submodules/cmake-builder
@@ -1 +1 @@
-Subproject commit cf6ad6e18ce9707e8236a6ab2c0fd789bdb9287d
+Subproject commit 3955daa45fa1f0eeb13b041560f78cfa7450968b
diff --git a/submodules/libilbc-rfc3951 b/submodules/libilbc-rfc3951
index bc20f1196..a6bb1eb6d 160000
--- a/submodules/libilbc-rfc3951
+++ b/submodules/libilbc-rfc3951
@@ -1 +1 @@
-Subproject commit bc20f11963878a1f32511de59b05490093e5c9b8
+Subproject commit a6bb1eb6dab5541cdded6a1f0326539234954c5d
diff --git a/submodules/linphone b/submodules/linphone
index ad1d7c12c..b843685bd 160000
--- a/submodules/linphone
+++ b/submodules/linphone
@@ -1 +1 @@
-Subproject commit ad1d7c12c9b459660b34d63408b144bf5890f3b6
+Subproject commit b843685bd8e03b047bc85239397bd1961ff9a9a0
diff --git a/submodules/msopenh264 b/submodules/msopenh264
index 172e97a83..40c29ef77 160000
--- a/submodules/msopenh264
+++ b/submodules/msopenh264
@@ -1 +1 @@
-Subproject commit 172e97a83aa2a868fd3dbbd6e7d57ad7d55f3054
+Subproject commit 40c29ef7736feb11af1e34f587788e49fa18b5c8
diff --git a/submodules/mssilk b/submodules/mssilk
index 06504344a..dd9dd3e81 160000
--- a/submodules/mssilk
+++ b/submodules/mssilk
@@ -1 +1 @@
-Subproject commit 06504344a367c033598a9dcaa6ff8387269e5a9a
+Subproject commit dd9dd3e81719972232d9d4df7bc5e7c5282722bb