diff --git a/app/build.gradle b/app/build.gradle
index 34e72448..546e7429 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -6,7 +6,7 @@ android {
defaultConfig {
applicationId = 'com.tutpro.baresip'
minSdkVersion 21
- targetSdkVersion 23
+ targetSdkVersion 25
versionCode = 1
versionName = '1.0'
ndk {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 30576d9c..05aa1799 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -36,7 +36,7 @@
-
-
-
-
-
+
#
#
-;auth_user=foo;auth_pass=xxx;outbound="sip:192.168.43.98:5060;transport=tcp";ptime=20;audio_codecs=OPUS/48000/2,speex/16000,speex/8000;video_codecs="";regint=600;pubint=0;sipnat=outbound
+;auth_user=foo;auth_pass=xxx;outbound="sip:192.168.43.98:5060;transport=tcp";ptime=20;audio_codecs=OPUS/48000/2,speex/16000,speex/8000,PCMU,PCMA;video_codecs="";regint=600;pubint=0;sipnat=outbound
diff --git a/app/src/main/assets/config b/app/src/main/assets/config
index f501c607..fddee23c 100644
--- a/app/src/main/assets/config
+++ b/app/src/main/assets/config
@@ -19,27 +19,27 @@ call_max_calls 4
# Audio
audio_player opensles,nil
audio_source opensles,nil
-audio_alert opensles,nil
-audio_srate 8000-48000
+audio_alert opensles,nil
+audio_srate 8000-48000
audio_channels 1-2
#ausrc_srate 48000
#auplay_srate 48000
#ausrc_channels 0
#auplay_channels 0
-audio_level no
+audio_level no
# Video
#video_source v4l2,/dev/video0
#video_display x11,nil
-video_size 352x288
+video_size 352x288
video_bitrate 500000
-video_fps 25
+video_fps 25
video_fullscreen yes
# AVT - Audio/Video Transport
rtp_tos 184
#rtp_ports 10000-20000
-#rtp_bandwidth 512-1024 # [kbit/s]
+#rtp_bandwidth 512-1024 # [kbit/s]
rtcp_enable yes
rtcp_mux no
jitter_buffer_delay 5-10 # frames
@@ -176,13 +176,13 @@ speex_complexity 7 # 0-10
speex_enhancement 0 # 0-1
speex_mode_nb 3 # 1-6
speex_mode_wb 6 # 1-6
-speex_vbr 0 # Variable Bit Rate 0-1
-speex_vad 0 # Voice Activity Detection 0-1
+speex_vbr 0 # Variable Bit Rate 0-1
+speex_vad 0 # Voice Activity Detection 0-1
speex_agc_level 8000
# Opus codec parameters
opus_bitrate 28000 # 6000-510000
-opus_cbr no
+opus_cbr no
opus_inbandfec yes
# Selfview
@@ -192,7 +192,7 @@ opus_inbandfec yes
# ICE
ice_turn no
ice_debug no
-ice_nomination regular # {regular,aggressive}
+ice_nomination regular # {regular,aggressive}
ice_mode full # {full,lite}
# Menu
diff --git a/app/src/main/assets/contacts b/app/src/main/assets/contacts
index d884f5f1..00ff0e92 100644
--- a/app/src/main/assets/contacts
+++ b/app/src/main/assets/contacts
@@ -1,17 +1,20 @@
#
# SIP contacts
#
-# Displayname ;addr-params
+# "display-name" ;addr-params
+#
+# display-name:
+# needs to be at least two characters long
#
# addr-params:
# ;presence={none,p2p}
# ;access={allow,block}
#
+# Peer contacts
"Echo Server"
#"user" ;presence=p2p
-
# Access rules
#"Catch All" ;access=block
#"Good Friend" ;access=allow
diff --git a/app/src/main/cpp/baresip.c b/app/src/main/cpp/baresip.c
index fae31b7b..797aaa4f 100644
--- a/app/src/main/cpp/baresip.c
+++ b/app/src/main/cpp/baresip.c
@@ -456,3 +456,31 @@ Java_com_tutpro_baresip_MainActivity_ua_1hangup(JNIEnv *env, jobject thiz,
(*env)->ReleaseStringUTFChars(env, reason, native_reason);
return;
}
+
+JNIEXPORT void JNICALL
+Java_com_tutpro_baresip_MainActivity_contacts_1remove(JNIEnv *env, jobject thiz) {
+ struct le *le;
+ le = list_head(contact_list(baresip_contacts()));
+ while ((le = list_head(contact_list(baresip_contacts())))) {
+ struct contact *c = le->data;
+ contact_remove(baresip_contacts(), c);
+ }
+ return;
+}
+
+JNIEXPORT void JNICALL
+Java_com_tutpro_baresip_MainActivity_contact_1add(JNIEnv *env, jobject thiz,
+ jstring javaContact) {
+ struct pl pl_addr;
+ const struct list *lst;
+ struct le *le;
+ const char *native_contact = (*env)->GetStringUTFChars(env, javaContact, 0);
+ pl_set_str(&pl_addr, native_contact);
+ if (contact_add(baresip_contacts(), NULL, &pl_addr) != 0) {
+ LOGE("failed to add contact %s\n", native_contact);
+ } else {
+ LOGD("added contact %s\n", native_contact);
+ }
+ return;
+}
+
diff --git a/app/src/main/java/com/tutpro/baresip/AccountSpinnerAdapter.java b/app/src/main/java/com/tutpro/baresip/AccountSpinnerAdapter.java
index 7a5d8436..c5cf72bc 100644
--- a/app/src/main/java/com/tutpro/baresip/AccountSpinnerAdapter.java
+++ b/app/src/main/java/com/tutpro/baresip/AccountSpinnerAdapter.java
@@ -38,6 +38,7 @@ public class AccountSpinnerAdapter extends ArrayAdapter {
View row = inflater.inflate(R.layout.account_spinner, parent, false);
TextView textView = (TextView) row.findViewById(R.id.spinnerText);
textView.setText(aors.get(position));
+ textView.setTextSize(17);
ImageView imageView = (ImageView) row.findViewById(R.id.spinnerImage);
imageView.setImageResource(images.get(position));
return row;
diff --git a/app/src/main/java/com/tutpro/baresip/Contact.java b/app/src/main/java/com/tutpro/baresip/Contact.java
new file mode 100644
index 00000000..c42d11b6
--- /dev/null
+++ b/app/src/main/java/com/tutpro/baresip/Contact.java
@@ -0,0 +1,20 @@
+package com.tutpro.baresip;
+
+public class Contact {
+
+ private String name, uri;
+
+ public Contact(String name, String uri) {
+ this.name = name;
+ this.uri = uri;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getURI() {
+ return uri;
+ }
+
+}
diff --git a/app/src/main/java/com/tutpro/baresip/EditContactsActivity.java b/app/src/main/java/com/tutpro/baresip/EditContactsActivity.java
index f9868e91..d27d12a4 100644
--- a/app/src/main/java/com/tutpro/baresip/EditContactsActivity.java
+++ b/app/src/main/java/com/tutpro/baresip/EditContactsActivity.java
@@ -8,53 +8,28 @@ import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.TextView;
+
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.OutputStreamWriter;
+import java.util.ArrayList;
public class EditContactsActivity extends AppCompatActivity {
private EditText editText;
- private String path;
- private File file;
+ static public ArrayList Contacts = new java.util.ArrayList<>();
+ static public ArrayList Names = new java.util.ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_contacts);
-
editText = (EditText)findViewById(R.id.editText);
- path = getApplicationContext().getFilesDir().getAbsolutePath() +
- "/contacts";
- file = new File(path);
- String content;
-
- if (!file.exists()) {
- Log.e("Baresip", "Failed to find contacts file");
- content = "No contacts";
- } else {
- Log.e("Baresip", "Found contacts file");
- int length = (int)file.length();
- byte[] bytes = new byte[length];
- try {
- FileInputStream in = new FileInputStream(file);
- try {
- in.read(bytes);
- } finally {
- in.close();
- }
- content = new String(bytes);
- } catch (java.io.IOException e) {
- Log.e("Baresip", "Failed to read contacts file: " + e.toString());
- content = "Failed to read account file";
- }
- }
-
- Log.d("Baresip", "Content length is: " + content.length());
-
+ String path = getApplicationContext().getFilesDir().getAbsolutePath() + "/contacts";
+ File file = new File(path);
+ String content = Utils.getFileContents(file);
+ Log.d("Baresip", "Contacts length is: " + content.length());
editText.setTextSize(TypedValue.COMPLEX_UNIT_PX,
getResources().getDimension(R.dimen.textsize));
editText.setText(content, TextView.BufferType.EDITABLE);
@@ -71,34 +46,71 @@ public class EditContactsActivity extends AppCompatActivity {
Intent i = new Intent(this, MainActivity.class);
switch (item.getItemId()) {
case R.id.save:
- try {
- FileOutputStream fOut =
- new FileOutputStream(file.getAbsoluteFile(), false);
- OutputStreamWriter fWriter = new OutputStreamWriter(fOut);
- String res = editText.getText().toString();
- try {
- fWriter.write(res);
- fWriter.close();
- fOut.close();
- } catch (java.io.IOException e) {
- Log.e("Baresip", "Failed to write contacts file: " +
- e.toString());
- }
- } catch (java.io.FileNotFoundException e) {
- Log.e("Baresip", "Failed to find contacts file: " +
- e.toString());
- }
+ String path = getApplicationContext().getFilesDir().getAbsolutePath() + "/contacts";
+ File file = new File(path);
+ Utils.putFileContents(file, editText.getText().toString());
Log.d("Baresip", "Updated contacts file");
+ MainActivity.contacts_remove();
+ updateContactsAndNames();
+ // MainActivity.CalleeAdapter.notifyDataSetChanged();
+ MainActivity.CalleeAdapter = new ArrayAdapter
+ (this,android.R.layout.select_dialog_item, Names);
+ MainActivity.callee.setThreshold(2);
+ MainActivity.callee.setAdapter(MainActivity.CalleeAdapter);
i.putExtra("action", "save");
- startActivity(i);
+ setResult(RESULT_OK, i);
+ finish();
return true;
case R.id.cancel:
i.putExtra("action", "cancel");
- startActivity(i);
+ setResult(RESULT_OK, i);
+ finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
+
+ static public void updateContactsAndNames() {
+ String path = MainActivity.mainActivityContext.getFilesDir().getAbsolutePath() + "/contacts";
+ File file = new File(path);
+ String[] lines = Utils.getFileContents(file).split("\n");
+ String name, uri;
+ Contacts.clear();
+ Names.clear();
+ for (String line : lines) {
+ line.trim();
+ if (line.startsWith("#") || line.length() == 0) continue;
+ String[] parts = line.split("\"");
+ if (parts.length != 3) {
+ Log.e("Baresip", "Invalid contacts line: " + line);
+ continue;
+ }
+ name = parts[1];
+ if (name.length() < 2) {
+ Log.e("Baresip", "Too short contact display name: " + name);
+ continue;
+ }
+ uri = parts[2].trim();
+ if (!uri.startsWith("<") || !uri.contains(">")) {
+ Log.e("Baresip", "Invalid contact uri: " + uri);
+ continue;
+ }
+ MainActivity.contact_add("\"" + name + "\" " + uri);
+ if (uri.indexOf(";access") > 0) continue;
+ uri = uri.substring(1, uri.indexOf(">"));
+ Log.d("Baresip", "Adding contact name/uri: " + name + "/" + uri);
+ Contacts.add(new Contact(name, uri));
+ Names.add(name);
+ }
+ }
+
+ static public String findContactURI(String name) {
+ for (Contact c : Contacts) {
+ if (c.getName().equals(name)) return c.getURI();
+ }
+ return name;
+ }
+
}
diff --git a/app/src/main/java/com/tutpro/baresip/MainActivity.java b/app/src/main/java/com/tutpro/baresip/MainActivity.java
index 9a6948bb..f3812740 100644
--- a/app/src/main/java/com/tutpro/baresip/MainActivity.java
+++ b/app/src/main/java/com/tutpro/baresip/MainActivity.java
@@ -1,13 +1,18 @@
package com.tutpro.baresip;
+import android.Manifest;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.graphics.Color;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.*;
import android.widget.RelativeLayout.LayoutParams;
+import android.widget.AutoCompleteTextView;
import android.view.*;
import android.util.Log;
import java.util.*;
@@ -18,17 +23,19 @@ public class MainActivity extends AppCompatActivity {
static Context mainActivityContext;
static Boolean running = false;
- static List accountList = new ArrayList<>();
- static EditText callee;
+ static AutoCompleteTextView callee;
static RelativeLayout layout;
static Button callButton;
static ArrayList Accounts = new ArrayList<>();
static ArrayList AoRs = new ArrayList<>();
static ArrayList Images = new ArrayList<>();
static AccountSpinnerAdapter AccountAdapter = null;
+ static ArrayAdapter CalleeAdapter = null;
static ArrayList In = new ArrayList<>();
static ArrayList Out = new ArrayList<>();
+ private static final int RECORD_AUDIO_PERMISSION = 1;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -73,8 +80,8 @@ public class MainActivity extends AppCompatActivity {
}
});
- String[] assets = {"config", "accounts", "busy.wav", "callwaiting.wav", "error.wav",
- "message.wav", "notfound.wav", "ring.wav", "ringback.wav"};
+ String[] assets = {"accounts", "contacts", "config", "busy.wav", "callwaiting.wav",
+ "error.wav", "message.wav", "notfound.wav", "ring.wav", "ringback.wav"};
final String path = mainActivityContext.getFilesDir().getPath();
Log.d("Baresip", "path is: " + path);
File file;
@@ -93,9 +100,18 @@ public class MainActivity extends AppCompatActivity {
if (!file.exists()) {
Log.d("Baresip", "Copying asset " + a);
copyAsset(a, path + "/" + a);
+ } else {
+ Log.d("Baresip", "Asset " + a + " already copied");
}
}
+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
+ != PackageManager.PERMISSION_GRANTED) {
+ Log.d("Baresip", "Baresip does not have RECORD_AUDIO permission");
+ ActivityCompat.requestPermissions(this,
+ new String[]{Manifest.permission.RECORD_AUDIO}, RECORD_AUDIO_PERMISSION);
+ }
+
if (!running) {
Log.i("Baresip", "Starting Baresip with path " + path);
new Thread(new Runnable() {
@@ -108,7 +124,12 @@ public class MainActivity extends AppCompatActivity {
layout = (RelativeLayout) findViewById(R.id.mainActivityLayout);
- callee = (EditText)findViewById(R.id.callee);
+ callee = (AutoCompleteTextView)findViewById(R.id.callee);
+ EditContactsActivity.updateContactsAndNames();
+ CalleeAdapter = new ArrayAdapter
+ (this,android.R.layout.select_dialog_item, EditContactsActivity.Names);
+ callee.setThreshold(2);
+ callee.setAdapter(CalleeAdapter);
callButton = (Button)findViewById(R.id.callButton);
callButton.setText("Call");
@@ -117,7 +138,8 @@ public class MainActivity extends AppCompatActivity {
public void onClick(View v) {
String ua = ua_current();
if (callButton.getText().toString().equals("Call")) {
- String uri = ((EditText) findViewById(R.id.callee)).getText().toString();
+ String callee = ((EditText) findViewById(R.id.callee)).getText().toString();
+ String uri = EditContactsActivity.findContactURI(callee);
if (!uri.startsWith("sip:")) uri = "sip:" + uri;
if (!uri.contains("@")) {
String aor = ua_aor(ua);
@@ -152,6 +174,24 @@ public class MainActivity extends AppCompatActivity {
}
}
+ @Override
+ public void onRequestPermissionsResult(int requestCode,
+ String permissions[], int[] grantResults) {
+ switch (requestCode) {
+ case RECORD_AUDIO_PERMISSION: {
+ if (grantResults.length > 0
+ && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ Log.d("Baresip", "RECORD_AUDIO permission granted");
+ } else {
+ Log.d("Baresip", "RECORD_AUDIO permission NOT granted");
+ }
+ return;
+ }
+ default:
+ Log.e("Baresip", "Unknown permissions request code: " + requestCode);
+ }
+ }
+
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
@@ -166,14 +206,15 @@ public class MainActivity extends AppCompatActivity {
startActivity(new Intent(MainActivity.this,
EditAccountsActivity.class));
return true;
+ case R.id.contacts:
+ startActivity(new Intent(MainActivity.this,
+ EditContactsActivity.class));
+
+ return true;
case R.id.config:
startActivity(new Intent(MainActivity.this,
EditConfigActivity.class));
return true;
- //case R.id.contacts:
- // startActivity(new Intent(MainActivity.this,
- // EditContactsActivity.class));
- //return true;
case R.id.about:
startActivity(new Intent(MainActivity.this,
AboutActivity.class));
@@ -414,6 +455,7 @@ public class MainActivity extends AppCompatActivity {
final String peer_uri = call_peeruri(call);
Log.d("Baresip", "Incoming call " + ua + "/" + call + "/" +
peer_uri);
+
final Call new_call = new Call(ua, call, peer_uri, "Answer");
In.add(new_call);
Log.d("Baresip", "Current UA is " + ua_current());
@@ -485,13 +527,14 @@ public class MainActivity extends AppCompatActivity {
public native String ua_aor(String ua);
public native Boolean ua_isregistered(long ua_ptr);
public native String ua_call(String ua);
- public native String ua_prev_call(String ua);
public native String call_peeruri(String call);
public native String ua_current();
public static native void ua_current_set(String s);
public native String ua_connect(String s);
public native void ua_answer(String ua, String call);
public native void ua_hangup(String ua, String call, int code, String reason);
+ static public native void contacts_remove();
+ static public native void contact_add(String contact);
static {
System.loadLibrary("baresip");
diff --git a/app/src/main/java/com/tutpro/baresip/Utils.java b/app/src/main/java/com/tutpro/baresip/Utils.java
new file mode 100644
index 00000000..e78505fc
--- /dev/null
+++ b/app/src/main/java/com/tutpro/baresip/Utils.java
@@ -0,0 +1,55 @@
+package com.tutpro.baresip;
+
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+
+public class Utils {
+
+ static public String getFileContents(File file) {
+ if (!file.exists()) {
+ Log.e("Baresip", "Failed to find file: " + file.getPath());
+ return "";
+ } else {
+ Log.e("Baresip", "Found file: " + file.getPath());
+ int length = (int) file.length();
+ byte[] bytes = new byte[length];
+ try {
+ FileInputStream in = new FileInputStream(file);
+ try {
+ in.read(bytes);
+ } finally {
+ in.close();
+ }
+ return new String(bytes);
+ } catch (java.io.IOException e) {
+ Log.e("Baresip", "Failed to read file: " + file.getPath() + ": " +
+ e.toString());
+ return "";
+ }
+ }
+ }
+
+ static public void putFileContents(File file, String contents) {
+ try {
+ FileOutputStream fOut =
+ new FileOutputStream(file.getAbsoluteFile(), false);
+ OutputStreamWriter fWriter = new OutputStreamWriter(fOut);
+ try {
+ fWriter.write(contents);
+ fWriter.close();
+ fOut.close();
+ } catch (java.io.IOException e) {
+ Log.e("Baresip", "Failed to put contents to file: " +
+ e.toString());
+ }
+ } catch (java.io.FileNotFoundException e) {
+ Log.e("Baresip", "Failed to find contents file: " +
+ e.toString());
+ }
+ }
+
+}
diff --git a/app/src/main/res/layout/activity_edit_contacts.xml b/app/src/main/res/layout/activity_edit_contacts.xml
index a556e598..7efb1bc1 100644
--- a/app/src/main/res/layout/activity_edit_contacts.xml
+++ b/app/src/main/res/layout/activity_edit_contacts.xml
@@ -12,7 +12,7 @@
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 6eb0b84c..85665a4b 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,7 +1,7 @@
-
-
-
+
+