Merge branch 'master' into travis_cmake

This commit is contained in:
Gautier Pelloux-Prayer 2015-06-17 14:52:38 +02:00
commit 86d0b3f489
65 changed files with 2837 additions and 2501 deletions

64
.clang-format Normal file
View file

@ -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
...

51
.git-pre-commit Executable file
View file

@ -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 <some_file.c>"
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 <some_file.cpp>"
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

2
.gitignore vendored
View file

@ -10,3 +10,5 @@ build
test-reports
WORK
Makefile
OUTPUT
git-clang-format.diff

2
.gitmodules vendored
View file

@ -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

View file

@ -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

View file

@ -1,31 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6751" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6736"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ChatRoomViewController">
<connections>
<outlet property="addressLabel" destination="40" id="43"/>
<outlet property="avatarImage" destination="41" id="44"/>
<outlet property="cancelTransferButton" destination="75" id="85"/>
<outlet property="chatView" destination="49" id="54"/>
<outlet property="composeIndicatorView" destination="fx4-ao-53M" id="xk5-nK-lur"/>
<outlet property="composeLabel" destination="fpY-Fv-ht2" id="4L6-ik-ZAe"/>
<outlet property="editButton" destination="10" id="35"/>
<outlet property="headerView" destination="39" id="45"/>
<outlet property="imageTransferProgressBar" destination="74" id="79"/>
<outlet property="messageBackgroundImage" destination="66" id="90"/>
<outlet property="messageField" destination="63" id="64"/>
<outlet property="messageView" destination="14" id="89"/>
<outlet property="pictureButton" destination="73" id="84"/>
<outlet property="sendButton" destination="15" id="27"/>
<outlet property="tableController" destination="29" id="32"/>
<outlet property="transferBackgroundImage" destination="83" id="88"/>
<outlet property="transferView" destination="72" id="86"/>
<outlet property="view" destination="6" id="11"/>
<outlet property="waitView" destination="91" id="93"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
@ -90,46 +85,11 @@
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<view hidden="YES" contentMode="scaleToFill" id="72" userLabel="transferView">
<rect key="frame" x="0.0" y="359" width="320" height="57"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="chat_progressbar_background.png" id="83" userLabel="transfertBackgroundImage">
<rect key="frame" x="0.0" y="0.0" width="320" height="57"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</imageView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" id="75" userLabel="cancelTransferButton">
<rect key="frame" x="262" y="0.0" width="58" height="57"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Cancel"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" backgroundImage="chat_cancel_default.png">
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="highlighted" backgroundImage="chat_cancel_over.png">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="onTransferCancelClick:" destination="-1" eventType="touchUpInside" id="78"/>
</connections>
</button>
<progressView opaque="NO" contentMode="scaleToFill" progress="0.5" id="74" userLabel="transferProgressBar">
<rect key="frame" x="20" y="27" width="222" height="2"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Upload or download progression">
<accessibilityTraits key="traits" none="YES" notEnabled="YES" updatesFrequently="YES"/>
</accessibility>
</progressView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<view contentMode="scaleToFill" id="14" userLabel="messageView">
<rect key="frame" x="0.0" y="359" width="320" height="57"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="chat_message_background.png" id="66" userLabel="messageBackgroundImage">
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" id="66" userLabel="messageBackgroundImage">
<rect key="frame" x="0.0" y="0.0" width="320" height="57"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
@ -235,17 +195,6 @@
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<view hidden="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="91" userLabel="waitView">
<rect key="frame" x="0.0" y="0.0" width="320" height="460"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<activityIndicatorView opaque="NO" clearsContextBeforeDrawing="NO" userInteractionEnabled="NO" contentMode="scaleToFill" animating="YES" style="whiteLarge" id="92" userLabel="activityIndicator">
<rect key="frame" x="142" y="211" width="37" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
</activityIndicatorView>
</subviews>
<color key="backgroundColor" white="1" alpha="0.66000000000000003" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<gestureRecognizers/>
@ -264,16 +213,12 @@
<image name="avatar_unknown_small.png" width="131" height="131"/>
<image name="chat_back_default.png" width="320" height="88"/>
<image name="chat_back_over.png" width="320" height="88"/>
<image name="chat_cancel_default.png" width="116" height="115"/>
<image name="chat_cancel_over.png" width="116" height="115"/>
<image name="chat_edit_default.png" width="320" height="88"/>
<image name="chat_edit_over.png" width="320" height="88"/>
<image name="chat_message_background.png" width="640" height="117"/>
<image name="chat_ok_default.png" width="320" height="88"/>
<image name="chat_photo_default.png" width="71" height="115"/>
<image name="chat_photo_disabled.png" width="71" height="115"/>
<image name="chat_photo_over.png" width="71" height="115"/>
<image name="chat_progressbar_background.png" width="524" height="115"/>
<image name="chat_send_default.png" width="117" height="115"/>
<image name="chat_send_disabled.png" width="117" height="115"/>
<image name="chat_send_over.png" width="117" height="115"/>

View file

@ -23,7 +23,6 @@
@protocol ChatRoomDelegate <NSObject>
- (BOOL)chatRoomStartImageDownload:(NSURL*)url userInfo:(id)userInfo;
- (BOOL)chatRoomStartImageUpload:(UIImage*)image url:(NSURL*)url;
- (void)resendChat:(NSString*)message withExternalUrl:(NSString*)url;

View file

@ -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);

View file

@ -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<HPGrowingTextViewDelegate, UICompositeViewDelegate, ImagePickerDelegate, ImageSharingDelegate, ChatRoomDelegate> {
@interface ChatRoomViewController : UIViewController<HPGrowingTextViewDelegate, UICompositeViewDelegate, ImagePickerDelegate, ChatRoomDelegate> {
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;

View file

@ -21,10 +21,12 @@
#import "PhoneMainView.h"
#import "DTActionSheet.h"
#import "UILinphone.h"
#import "DTAlertView.h"
#import "Utils/FileTransferDelegate.h"
#import <NinePatch.h>
#import <MobileCoreServices/UTCoreTypes.h>
#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 {

View file

@ -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]

View file

@ -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);

View file

@ -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 <Foundation/Foundation.h>
@class ImageSharing;
@protocol ImageSharingDelegate <NSObject>
- (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<NSURLConnectionDataDelegate> {
@private
NSInteger totalBytesExpectedToRead;
id<ImageSharingDelegate> delegate;
NSInteger statusCode;
}
+ (id)newImageSharingUpload:(NSURL*)url image:(UIImage*)image delegate:(id<ImageSharingDelegate>)delegate userInfo:(id)userInfo;
+ (id)newImageSharingDownload:(NSURL*)url delegate:(id<ImageSharingDelegate>)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

View file

@ -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<ImageSharingDelegate>)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<ImageSharingDelegate>)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

View file

@ -1,27 +0,0 @@
//
// InAppProductsCell.h
// linphone
//
// Created by Gautier Pelloux-Prayer on 15/04/15.
//
//
#import <UIKit/UIKit.h>
#import <StoreKit/StoreKit.h>
@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

View file

@ -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

View file

@ -1,58 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6751" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" variant="6xAndEarlier" propertyAccessControl="none">
<dependencies>
<deployment identifier="iOS"/>
<development version="5100" identifier="xcode"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6736"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="InAppProductsCell">
<connections>
<outlet property="pdescription" destination="4s8-UV-skT" id="gYv-YR-7Kx"/>
<outlet property="pprice" destination="jzs-nJ-jrK" id="UBe-qg-Gmj"/>
<outlet property="ppurchased" destination="Bcv-Vz-Tq1" id="EB5-Ic-nCq"/>
<outlet property="ptitle" destination="Np2-5N-fTR" id="X3D-TQ-R8R"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="Jvg-Ga-qnD" userLabel="view">
<rect key="frame" x="0.0" y="0.0" width="340" height="40"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="title" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="6" id="Np2-5N-fTR" userLabel="ptitle">
<rect key="frame" x="0.0" y="6" width="55" height="27"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="description..." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" id="4s8-UV-skT" userLabel="pdescription">
<rect key="frame" x="119" y="6" width="136" height="27"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" tag="2" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="$0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" id="jzs-nJ-jrK" userLabel="pprice">
<rect key="frame" x="63" y="6" width="48" height="27"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" id="Bcv-Vz-Tq1" userLabel="ppurchased">
<rect key="frame" x="263" y="6" width="79" height="27"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
</switch>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="14" y="539"/>
</view>
</objects>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

View file

@ -29,7 +29,6 @@
#import "LinphoneManager.h"
#import "PhoneMainView.h"
#import "InAppProductsViewController.h"
@interface InAppProductsManager()
@property (strong, nonatomic) NSDate *expirationDate;

View file

@ -1,13 +0,0 @@
//
// InAppProductsTableViewController.h
// linphone
//
// Created by Gautier Pelloux-Prayer on 16/04/15.
//
//
#import <UIKit/UIKit.h>
@interface InAppProductsTableViewController : UITableViewController
@end

View file

@ -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

View file

@ -1,20 +0,0 @@
//
// InAppProductsViewController.h
// linphone
//
// Created by Gautier Pelloux-Prayer on 15/04/15.
//
//
#import <UIKit/UIKit.h>
#import "UICompositeViewController.h"
#import "InAppProductsTableViewController.h"
@interface InAppProductsViewController : UIViewController<UICompositeViewDelegate> {
}
@property (nonatomic, strong) IBOutlet InAppProductsTableViewController* tableController;
@property (strong, nonatomic) IBOutlet UIView *waitView;
- (IBAction)onRestoreClicked:(UIButton *)sender;
@end

View file

@ -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

View file

@ -1,70 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6751" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6736"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="InAppProductsViewController">
<connections>
<outlet property="tableController" destination="FRQ-Fw-iZ8" id="HVZ-37-Tau"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
<outlet property="waitView" destination="4pA-a2-gQ7" id="4f0-jJ-Wv4"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
<rect key="frame" x="0.0" y="0.0" width="320" height="460"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="1" sectionFooterHeight="10" id="fwu-cz-Gse" userLabel="productsTable">
<rect key="frame" x="0.0" y="38" width="320" height="422"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="calibratedRGB"/>
<connections>
<outlet property="dataSource" destination="FRQ-Fw-iZ8" id="uQQ-fT-hHp"/>
<outlet property="delegate" destination="FRQ-Fw-iZ8" id="2Dx-aQ-XVB"/>
</connections>
</tableView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="XrD-Mn-6EM" userLabel="restoreButton">
<rect key="frame" x="0.0" y="0.0" width="320" height="30"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
<state key="normal" title="Restore">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="onRestoreClicked:" destination="-1" eventType="touchUpInside" id="ZYY-WP-1of"/>
</connections>
</button>
<view hidden="YES" alpha="0.49999999999999961" contentMode="scaleToFill" id="4pA-a2-gQ7" userLabel="waitView">
<rect key="frame" x="0.0" y="0.0" width="320" height="460"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" animating="YES" style="whiteLarge" id="K5m-Dx-cXk" userLabel="spinner">
<rect key="frame" x="142" y="211" width="37" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
</activityIndicatorView>
</subviews>
<color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="517" y="-365"/>
</view>
<tableViewController extendedLayoutIncludesOpaqueBars="YES" id="FRQ-Fw-iZ8" userLabel="tableController" customClass="InAppProductsTableViewController">
<extendedEdge key="edgesForExtendedLayout" top="YES"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<size key="freeformSize" width="320" height="460"/>
<connections>
<outlet property="view" destination="fwu-cz-Gse" id="qar-Rf-89v"/>
</connections>
<point key="canvasLocation" x="139" y="-365"/>
</tableViewController>
</objects>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

View file

@ -4,18 +4,18 @@
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
*/
#import <Foundation/Foundation.h>
#import "IASKSettingsStore.h"
@ -28,7 +28,6 @@
NSDictionary *changedDict;
}
- (void)synchronizeAccount;
- (void)transformLinphoneCoreToKeys;
@end

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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

View file

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6254" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="UICallCell">
@ -33,10 +32,10 @@
<outlet property="videoDownloadBandwidthLabel" destination="109" id="125"/>
<outlet property="videoIceConnectivityHeaderLabel" destination="111" id="126"/>
<outlet property="videoIceConnectivityLabel" destination="112" id="127"/>
<outlet property="videoRecvSizeHeaderLabel" destination="nNJ-4U-pl2" id="r20-yj-TG9"/>
<outlet property="videoRecvSizeLabel" destination="RxS-YG-dqM" id="fPi-Uk-MHy"/>
<outlet property="videoSentSizeHeaderLabel" destination="6PM-O1-cYd" id="G8P-SK-lgu"/>
<outlet property="videoSentSizeLabel" destination="CCZ-g0-5g1" id="kgM-NY-RUy"/>
<outlet property="videoRecvSizeFPSHeaderLabel" destination="nNJ-4U-pl2" id="mMd-r3-eEC"/>
<outlet property="videoRecvSizeFPSLabel" destination="RxS-YG-dqM" id="paX-s0-Cjs"/>
<outlet property="videoSentSizeFPSHeaderLabel" destination="6PM-O1-cYd" id="I9e-1I-e8q"/>
<outlet property="videoSentSizeFPSLabel" destination="CCZ-g0-5g1" id="uzZ-aa-lnu"/>
<outlet property="videoStatsView" destination="99" id="128"/>
<outlet property="videoUploadBandwidthHeaderLabel" destination="107" id="129"/>
<outlet property="videoUploadBandwidthLabel" destination="108" id="130"/>
@ -218,11 +217,11 @@
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<view contentMode="scaleToFill" id="j5j-bZ-C2L" userLabel="videoSentSizeView">
<view contentMode="scaleToFill" id="j5j-bZ-C2L" userLabel="videoSentSizeFPSView">
<rect key="frame" x="10" y="80" width="310" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Size sent:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="6PM-O1-cYd" userLabel="videoSentSizeHeaderLabel">
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Size sent (FPS):" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="6PM-O1-cYd" userLabel="videoSentSizeFPSHeaderLabel">
<rect key="frame" x="0.0" y="0.0" width="160" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration">
@ -231,7 +230,7 @@
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="320x240" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="CCZ-g0-5g1" userLabel="videoSentSizeLabel">
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="320x240 (15FPS)" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="CCZ-g0-5g1" userLabel="videoSentSizeFPSLabel">
<rect key="frame" x="168" y="0.0" width="142" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Video upload bandwidth">
@ -243,11 +242,11 @@
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<view contentMode="scaleToFill" id="6oX-23-Ivn" userLabel="videoRecvSizeView">
<view contentMode="scaleToFill" id="6oX-23-Ivn" userLabel="videoRecvSizeFPSView">
<rect key="frame" x="10" y="110" width="310" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Size received:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="nNJ-4U-pl2" userLabel="videoRecvSizeHeaderLabel">
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Size received (FPS):" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="nNJ-4U-pl2" userLabel="videoRecvSizeFPSHeaderLabel">
<rect key="frame" x="0.0" y="0.0" width="160" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration">
@ -256,7 +255,7 @@
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="320x240" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="RxS-YG-dqM" userLabel="videoRecvSizeLabel">
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="320x240 (15FPS)" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="RxS-YG-dqM" userLabel="videoRecvSizeFPSLabel">
<rect key="frame" x="168" y="0.0" width="142" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Video upload bandwidth">

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3747"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="UIChatRoomCell">
@ -9,9 +10,11 @@
<outlet property="backgroundImage" destination="3" id="11"/>
<outlet property="backgroundView" destination="7" id="10"/>
<outlet property="bubbleView" destination="16" id="30"/>
<outlet property="cancelButton" destination="fGh-KI-efm" id="R65-2g-q7P"/>
<outlet property="dateLabel" destination="22" id="24"/>
<outlet property="deleteButton" destination="18" id="19"/>
<outlet property="downloadButton" destination="33" id="34"/>
<outlet property="fileTransferProgress" destination="Pd7-2N-Jg3" id="sct-Jr-HnV"/>
<outlet property="innerView" destination="2" id="25"/>
<outlet property="messageImageView" destination="28" id="31"/>
<outlet property="messageText" destination="43" id="44"/>
@ -54,6 +57,7 @@
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="33" userLabel="downloadButton">
<rect key="frame" x="81" y="33" width="132" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Download"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" title="Download image">
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
@ -66,11 +70,31 @@
<action selector="onDownloadClick:" destination="-1" eventType="touchUpInside" id="39"/>
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="fGh-KI-efm" userLabel="cancelButton">
<rect key="frame" x="81" y="34" width="132" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Cancel transfer"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" title="Cancel transfer">
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="highlighted">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="onCancelDownloadClick:" destination="-1" eventType="touchUpInside" id="Ag3-jA-20G"/>
</connections>
</button>
<progressView hidden="YES" opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" progress="0.5" id="Pd7-2N-Jg3" userLabel="fileTransferProgress">
<rect key="frame" x="15" y="94" width="264" height="2"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
</progressView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<label opaque="NO" clipsSubviews="YES" contentMode="left" text="09/09/2009 at 09:09" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="8" adjustsFontSizeToFit="NO" id="22" userLabel="timestampLabel">
<rect key="frame" x="0.0" y="104" width="280" height="10"/>
<rect key="frame" x="4" y="104" width="274" height="10"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="system" pointSize="9"/>
@ -103,16 +127,23 @@
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<rect key="contentStretch" x="0.0" y="0.0" width="0.59999999999999964" height="1"/>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
</view>
<view contentMode="scaleToFill" id="7" userLabel="backgroundView">
<rect key="frame" x="0.0" y="0.0" width="100" height="100"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
</view>
<view contentMode="scaleToFill" id="9" userLabel="selectedBackgroundView">
<rect key="frame" x="0.0" y="0.0" width="100" height="100"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
</view>
</objects>
<resources>
@ -121,4 +152,9 @@
<image name="list_delete_default.png" width="45" height="45"/>
<image name="list_delete_over.png" width="45" height="45"/>
</resources>
</document>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

View file

@ -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;

View file

@ -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"];
}
}
}

View file

@ -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

View file

@ -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

View file

@ -28,7 +28,9 @@
#import <NinePatch.h>
#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

View file

@ -20,7 +20,6 @@
#import <QuartzCore/QuartzCore.h>
#import <AudioToolbox/AudioServices.h>
#import "InAppProductsViewController.h"
#import "LinphoneAppDelegate.h"
#import "PhoneMainView.h"
#import "Utils.h"

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,20 @@
//
// FileTransferDelegate.h
// linphone
//
// Created by Gautier Pelloux-Prayer on 10/06/15.
//
//
#import <Foundation/Foundation.h>
#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

View file

@ -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

View file

@ -105,6 +105,7 @@
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.tableView = nil;

View file

@ -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 <UIKit/UIKit.h>
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

View file

@ -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 <objc/runtime.h>
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<UIAlertViewDelegate>)self) {
objc_setAssociatedObject(self, UIAlertViewOriginalDelegateKey, self.delegate, OBJC_ASSOCIATION_ASSIGN);
self.delegate = (id<UIAlertViewDelegate>)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

View file

@ -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) {

View file

@ -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

View file

@ -37,6 +37,11 @@
<a href="http://www.tortuga22.com">http://www.tortuga22.com</a><br />
<em>Apache license</em></p>
<h3>Ryan Maxwell</h3>
<p>UIAlertview+Blocks</p>
<a href="https://github.com/ryanmaxwell/UIAlertView-Blocks">https://github.com/ryanmaxwell/UIAlertView-Blocks</a><br />
<em>MIT license</em>
<h3>OrderedDictionary</h3>
<p>Matt Gallagher<br />
<a href="http://cocoawithlove.com">http://cocoawithlove.com</a></p>

View file

@ -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

View file

@ -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

View file

@ -22,7 +22,7 @@
<section name="app">
<entry name="pushnotification_preference" overwrite="true">1</entry>
<entry name="sharing_server_preference" overwrite="true">https://www.linphone.org:444/upload.php</entry>
<entry name="sharing_server_preference" overwrite="true">https://www.linphone.org:444/lft.php</entry>
<entry name="ice_preference" overwrite="true">1</entry>
<entry name="stun_preference" overwrite="true">stun.linphone.org</entry>
<entry name="random_port_preference" overwrite="true">1</entry>

View file

@ -22,7 +22,7 @@
<section name="app">
<entry name="pushnotification_preference" overwrite="true">1</entry>
<entry name="sharing_server_preference" overwrite="true">https://www.linphone.org:444/upload.php</entry>
<entry name="sharing_server_preference" overwrite="true">https://www.linphone.org:444/lft.php</entry>
<entry name="ice_preference" overwrite="true">1</entry>
<entry name="stun_preference" overwrite="true">stun.linphone.org</entry>
<entry name="random_port_preference" overwrite="true">1</entry>

View file

@ -218,36 +218,6 @@
<key>IASKTextAlignment</key>
<string>IASKUITextAlignmentRight</string>
</dict>
<dict>
<key>DefaultValue</key>
<true/>
<key>Key</key>
<string>adaptive_rate_control_preference</string>
<key>Title</key>
<string>Adaptive rate control</string>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
</dict>
<dict>
<key>DefaultValue</key>
<string>Simple</string>
<key>Key</key>
<string>adaptive_rate_algorithm_preference</string>
<key>Title</key>
<string>Adaptive rate algorithm</string>
<key>Titles</key>
<array>
<string>Simple</string>
<string>Stateful</string>
</array>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Values</key>
<array>
<string>Simple</string>
<string>Stateful</string>
</array>
</dict>
<dict>
<key>DefaultValue</key>
<integer>36</integer>

View file

@ -106,6 +106,16 @@
<key>IASKTextAlignment</key>
<string>IASKUITextAlignmentRight</string>
</dict>
<dict>
<key>DefaultValue</key>
<false/>
<key>Key</key>
<string>repeat_call_notification_preference</string>
<key>Title</key>
<string>Repeat call notification</string>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
</dict>
</array>
</dict>
</plist>

View file

@ -156,31 +156,41 @@
</dict>
<dict>
<key>Key</key>
<string>upload_bandwidth_preference</string>
<string>adaptive_rate_control_group</string>
<key>Title</key>
<string>Upload bandwidth</string>
<string>Adaptive rate control</string>
<key>Type</key>
<string>PSTextFieldSpecifier</string>
<key>KeyboardType</key>
<string>NumberPad</string>
<key>DefaultValue</key>
<integer>0</integer>
<key>IASKTextAlignment</key>
<string>IASKUITextAlignmentRight</string>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>Key</key>
<string>download_bandwidth_preference</string>
<key>Title</key>
<string>Download bandwidth</string>
<key>Type</key>
<string>PSTextFieldSpecifier</string>
<key>KeyboardType</key>
<string>NumberPad</string>
<key>DefaultValue</key>
<integer>0</integer>
<key>IASKTextAlignment</key>
<string>IASKUITextAlignmentRight</string>
<true/>
<key>Key</key>
<string>adaptive_rate_control_preference</string>
<key>Title</key>
<string>Adaptive rate control</string>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
</dict>
<dict>
<key>DefaultValue</key>
<string>Simple</string>
<key>Key</key>
<string>adaptive_rate_algorithm_preference</string>
<key>Title</key>
<string>Adaptive rate algorithm</string>
<key>Titles</key>
<array>
<string>Simple</string>
<string>Stateful</string>
</array>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Values</key>
<array>
<string>Simple</string>
<string>Stateful</string>
</array>
</dict>
</array>
</dict>

View file

@ -242,14 +242,6 @@
<key>Type</key>
<string>PSChildPaneSpecifier</string>
</dict>
<dict>
<key>Key</key>
<string>in_app_products_button</string>
<key>Title</key>
<string>Extra features</string>
<key>Type</key>
<string>IASKButtonSpecifier</string>
</dict>
<dict>
<key>Title</key>
<string>Development debug actions</string>
@ -276,7 +268,7 @@
<key>Key</key>
<string>release_button</string>
<key>Title</key>
<string>Exit</string>
<string>Release core</string>
<key>Type</key>
<string>IASKButtonSpecifier</string>
</dict>

View file

@ -41,8 +41,28 @@
<string>preview_preference</string>
</dict>
<dict>
<key>Key</key>
<string>video_preset_preference</string>
<key>Title</key>
<string>Video preset</string>
<key>Titles</key>
<array>
<string>Default</string>
<string>High FPS</string>
<string>Custom</string>
</array>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Values</key>
<array>
<string>default</string>
<string>high-fps</string>
<string>custom</string>
</array>
<key>DefaultValue</key>
<integer>1</integer>
<string>default</string>
</dict>
<dict>
<key>Key</key>
<string>video_preferred_size_preference</string>
<key>Title</key>
@ -61,6 +81,56 @@
<integer>1</integer>
<integer>2</integer>
</array>
<key>DefaultValue</key>
<integer>1</integer>
</dict>
<dict>
<key>Key</key>
<string>video_preferred_fps_preference</string>
<key>Title</key>
<string>Preferred FPS</string>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Titles</key>
<array>
<string>No preference</string>
<string>5</string>
<string>10</string>
<string>15</string>
<string>20</string>
<string>25</string>
<string>30</string>
</array>
<key>Values</key>
<array>
<integer>0</integer>
<integer>5</integer>
<integer>10</integer>
<integer>15</integer>
<integer>20</integer>
<integer>25</integer>
<integer>30</integer>
</array>
<key>DefaultValue</key>
<string>0</string>
</dict>
<dict>
<key>Key</key>
<string>download_bandwidth_preference</string>
<key>Title</key>
<string>Bandwidth limit in kbits/s</string>
<key>Type</key>
<string>PSTextFieldSpecifier</string>
<key>AutocapitalizationType</key>
<string>None</string>
<key>AutocorrectionType</key>
<string>No</string>
<key>KeyboardType</key>
<string>NumberPad</string>
<key>DefaultValue</key>
<integer>380</integer>
<key>IASKTextAlignment</key>
<string>IASKUITextAlignmentRight</string>
</dict>
<dict>
<key>Title</key>

View file

@ -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 = "<group>"; };
15017E6F1773578400784ACB /* libxml2.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libxml2.a; path = "liblinphone-sdk/apple-darwin/lib/libxml2.a"; sourceTree = "<group>"; };
152F22331B15E83B008C0621 /* libilbcrfc3951.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libilbcrfc3951.a; path = "liblinphone-sdk/apple-darwin/lib/libilbcrfc3951.a"; sourceTree = "<group>"; };
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 = "<group>"; };
@ -1023,14 +1018,6 @@
631C4FB519D2C3A6004BFE77 /* UIDigitButtonLongVoiceMail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIDigitButtonLongVoiceMail.h; sourceTree = "<group>"; };
631C4FB619D2C3A6004BFE77 /* UIDigitButtonLongVoiceMail.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIDigitButtonLongVoiceMail.m; sourceTree = "<group>"; };
633E388219FFB0F400936D1C /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
6359DE7C1ADEB54200EA15C0 /* InAppProductsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InAppProductsViewController.h; sourceTree = "<group>"; };
6359DE7D1ADEB54200EA15C0 /* InAppProductsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InAppProductsViewController.m; sourceTree = "<group>"; };
6359DE7E1ADEB54200EA15C0 /* InAppProductsViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = InAppProductsViewController.xib; sourceTree = "<group>"; };
6359DE811ADEB64100EA15C0 /* InAppProductsCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InAppProductsCell.h; sourceTree = "<group>"; };
6359DE821ADEB64100EA15C0 /* InAppProductsCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InAppProductsCell.m; sourceTree = "<group>"; };
6359DE831ADEB64100EA15C0 /* InAppProductsCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = InAppProductsCell.xib; sourceTree = "<group>"; };
6359DE891ADF9EB900EA15C0 /* InAppProductsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InAppProductsTableViewController.h; sourceTree = "<group>"; };
6359DE8A1ADF9EB900EA15C0 /* InAppProductsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InAppProductsTableViewController.m; sourceTree = "<group>"; };
636316D21A1DEBCB0009B839 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/AboutViewController.xib; sourceTree = "<group>"; };
636316D51A1DEC650009B839 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/SettingsViewController.xib; sourceTree = "<group>"; };
636316D81A1DECC90009B839 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PhoneMainView.xib; sourceTree = "<group>"; };
@ -1038,6 +1025,8 @@
636316DB1A1DEDD80009B839 /* ru */ = {isa = PBXFileReference; fileEncoding = 2483028224; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/HistoryDetailsViewController.strings; sourceTree = "<group>"; };
636316DC1A1DEECB0009B839 /* UIButtonShrinkable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIButtonShrinkable.h; sourceTree = "<group>"; };
636316DD1A1DEF2F0009B839 /* UIButtonShrinkable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIButtonShrinkable.m; sourceTree = "<group>"; };
6371579F1B283FE200C91677 /* FileTransferDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileTransferDelegate.h; path = Utils/FileTransferDelegate.h; sourceTree = "<group>"; };
637157A01B283FE200C91677 /* FileTransferDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FileTransferDelegate.m; path = Utils/FileTransferDelegate.m; sourceTree = "<group>"; };
639CEAFE1A1DF4D9004DE38F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UIStateBar.xib; sourceTree = "<group>"; };
639CEB011A1DF4E4004DE38F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UIHistoryCell.xib; sourceTree = "<group>"; };
639CEB041A1DF4EB004DE38F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UICompositeViewController.xib; sourceTree = "<group>"; };
@ -1257,8 +1246,6 @@
D36FB2D31589EF7C0036F6F2 /* UIPauseButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIPauseButton.h; sourceTree = "<group>"; };
D36FB2D41589EF7C0036F6F2 /* UIPauseButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIPauseButton.m; sourceTree = "<group>"; };
D37295DA158B3C9600D2C0C7 /* video_off_disabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = video_off_disabled.png; path = Resources/video_off_disabled.png; sourceTree = "<group>"; };
D374D3FB16071762003D25FF /* ImageSharing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageSharing.h; sourceTree = "<group>"; };
D374D3FC16071762003D25FF /* ImageSharing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImageSharing.m; sourceTree = "<group>"; };
D377BBF915A19DA6002B696B /* video_on_disabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = video_on_disabled.png; path = Resources/video_on_disabled.png; sourceTree = "<group>"; };
D378906215AC373B00BD776C /* ContactDetailsLabelViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactDetailsLabelViewController.h; sourceTree = "<group>"; };
D378906315AC373B00BD776C /* ContactDetailsLabelViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactDetailsLabelViewController.m; sourceTree = "<group>"; };
@ -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 */,

View file

@ -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 = "<group>"; };
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()

@ -1 +1 @@
Subproject commit 611762072933bf7bcbac9848bfead5a367a22ded
Subproject commit 7780031ed6742e6653c3718ed506c851d129f86f

View file

@ -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() {}

Binary file not shown.

View file

@ -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:

View file

@ -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

@ -1 +1 @@
Subproject commit cf6ad6e18ce9707e8236a6ab2c0fd789bdb9287d
Subproject commit 3955daa45fa1f0eeb13b041560f78cfa7450968b

@ -1 +1 @@
Subproject commit bc20f11963878a1f32511de59b05490093e5c9b8
Subproject commit a6bb1eb6dab5541cdded6a1f0326539234954c5d

@ -1 +1 @@
Subproject commit ad1d7c12c9b459660b34d63408b144bf5890f3b6
Subproject commit b843685bd8e03b047bc85239397bd1961ff9a9a0

@ -1 +1 @@
Subproject commit 172e97a83aa2a868fd3dbbd6e7d57ad7d55f3054
Subproject commit 40c29ef7736feb11af1e34f587788e49fa18b5c8

@ -1 +1 @@
Subproject commit 06504344a367c033598a9dcaa6ff8387269e5a9a
Subproject commit dd9dd3e81719972232d9d4df7bc5e7c5282722bb