Delegating GUI state change actions to GUI listener
+ *
+ *
+ * @author Guillaume Beraudo
+ *
+ */
+public final class LinphoneService extends Service implements LinphoneServiceListener {
+ /* Listener needs to be implemented in the Service as it calls
+ * setLatestEventInfo and startActivity() which needs a context.
+ */
+
+ private Handler mHandler = new Handler();
+ private static LinphoneService instance;
- private static LinphoneService theLinphone;
- private LinphoneCore mLinphoneCore;
- private SharedPreferences mPref;
- Timer mTimer = new Timer("Linphone scheduler");
-
- NotificationManager mNotificationManager;
- Notification mNotification;
- PendingIntent mNofificationContentIntent;
- final static int NOTIFICATION_ID=1;
- final String NOTIFICATION_TITLE = "Linphone";
-
- final int IC_LEVEL_OFFLINE=3;
- final int IC_LEVEL_ORANGE=0;
- final int IC_LEVEL_GREEN=1;
- final int IC_LEVEL_RED=2;
+ static boolean isReady() { return (instance!=null); }
- MediaPlayer mRingerPlayer;
- LinphoneCall.State mCurrentCallState;
- Vibrator mVibrator;
- private AudioManager mAudioManager;
- private BroadcastReceiver mKeepAliveMgrReceiver = new KeepAliveManager();
- private BroadcastReceiver mOutgoingCallReceiver = null;
-
- private Handler mHandler = new Handler() ;
- static boolean isready() {
- return (theLinphone!=null);
- }
+ /**
+ * @throws RuntimeException service not instantiated
+ */
static LinphoneService instance() {
- if (theLinphone == null) {
- throw new RuntimeException("LinphoneActivity not instanciated yet");
- } else {
- return theLinphone;
- }
+ if (isReady()) return instance;
+
+ throw new RuntimeException("LinphoneService not instantiated yet");
}
+
+ private NotificationManager mNotificationMgr;
+ private final static int NOTIF_ID=1;
+
+ private Notification mNotif;
+ private PendingIntent mNotifContentIntent;
+ private String notificationTitle;
+
+
+ private static final int IC_LEVEL_ORANGE=0;
+ /*private static final int IC_LEVEL_GREEN=1;
+ private static final int IC_LEVEL_RED=2;*/
+ private static final int IC_LEVEL_OFFLINE=3;
+
+
+
+
+
@Override
public void onCreate() {
super.onCreate();
- theLinphone = this;
+ instance = this;
+ notificationTitle = getString(R.string.app_name);
+
// Dump some debugging information to the logs
Hacks.dumpDeviceInformation();
- mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- mNotification = new Notification(R.drawable.status_level
- , ""
- , System.currentTimeMillis());
- mNotification.iconLevel=IC_LEVEL_ORANGE;
- mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
- Intent notificationIntent = new Intent(this, LinphoneActivity.class);
- mNofificationContentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
- mNotification.setLatestEventInfo(this, NOTIFICATION_TITLE,"", mNofificationContentIntent);
- mNotificationManager.notify(NOTIFICATION_ID, mNotification);
- mPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
- mAudioManager = ((AudioManager)getSystemService(Context.AUDIO_SERVICE));
- mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
- try {
- copyAssetsFromPackage();
+ mNotificationMgr = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
+ mNotif = new Notification(R.drawable.status_level, "", System.currentTimeMillis());
+ mNotif.iconLevel=IC_LEVEL_ORANGE;
+ mNotif.flags |= Notification.FLAG_ONGOING_EVENT;
- mLinphoneCore = LinphoneCoreFactory.instance().createLinphoneCore( this
- , LINPHONE_RC
- , LINPHONE_FACTORY_RC
- , null);
-
- mLinphoneCore.setPlaybackGain(3);
- mLinphoneCore.setRing(null);
-
- try {
- initFromConf();
- } catch (LinphoneException e) {
- Log.w(TAG, "no config ready yet");
- }
- TimerTask lTask = new TimerTask() {
- @Override
- public void run() {
- mLinphoneCore.iterate();
- }
-
- };
-
- mTimer.scheduleAtFixedRate(lTask, 0, 100);
- IntentFilter lFilter = new IntentFilter(Intent.ACTION_SCREEN_ON);
- lFilter.addAction(Intent.ACTION_SCREEN_OFF);
- registerReceiver(mKeepAliveMgrReceiver, lFilter);
-
-
-
- }
- catch (Exception e) {
- Log.e(TAG,"Cannot start linphone",e);
- }
-
-
- }
-
-
-
-
-
- private void copyAssetsFromPackage() throws IOException {
- copyIfNotExist(R.raw.oldphone_mono,RING_SND);
- copyIfNotExist(R.raw.ringback,RINGBACK_SND);
- copyFromPackage(R.raw.linphonerc, new File(LINPHONE_FACTORY_RC).getName());
- }
- private void copyIfNotExist(int ressourceId,String target) throws IOException {
- File lFileToCopy = new File(target);
- if (!lFileToCopy.exists()) {
- copyFromPackage(ressourceId,lFileToCopy.getName());
- }
-
- }
- private void copyFromPackage(int ressourceId,String target) throws IOException{
- FileOutputStream lOutputStream = openFileOutput (target, 0);
- InputStream lInputStream = getResources().openRawResource(ressourceId);
- int readByte;
- byte[] buff = new byte[8048];
- while (( readByte = lInputStream.read(buff))!=-1) {
- lOutputStream.write(buff,0, readByte);
- }
- lOutputStream.flush();
- lOutputStream.close();
- lInputStream.close();
-
- }
- public void authInfoRequested(LinphoneCore lc, String realm, String username) {
-
- }
- public void byeReceived(LinphoneCore lc, String from) {
- // TODO Auto-generated method stub
-
- }
- public void displayMessage(LinphoneCore lc, String message) {
- // TODO Auto-generated method stub
-
- }
- public void displayStatus(final LinphoneCore lc, final String message) {
- Log.i(TAG, message);
- if (DialerActivity.getDialer()!=null) {
- mHandler.post(new Runnable() {
- public void run() {
- if (DialerActivity.getDialer()!=null)
- DialerActivity.getDialer().displayStatus(lc,message);
- }
-
- });
-
- }
- }
- public void displayWarning(LinphoneCore lc, String message) {
- // TODO Auto-generated method stub
-
- }
- public void globalState(final LinphoneCore lc, final LinphoneCore.GlobalState state, final String message) {
- Log.i(TAG, "new state ["+state+"]");
- if (state == GlobalState.GlobalOn) {
- mNotification.iconLevel=IC_LEVEL_OFFLINE;
- mNotification.when=System.currentTimeMillis();
- mNotification.setLatestEventInfo(this
- , NOTIFICATION_TITLE
- ,getString(R.string.notification_started)
- , mNofificationContentIntent);
- mNotificationManager.notify(NOTIFICATION_ID, mNotification);
- if (DialerActivity.getDialer()!=null) {
- mHandler.post(new Runnable() {
- public void run() {
- DialerActivity.getDialer().globalState(lc,state,message);
- }
- });
- }
-
- }
- }
- public void registrationState(final LinphoneCore lc, final LinphoneProxyConfig cfg,final LinphoneCore.RegistrationState state,final String smessage) {
- Log.i(TAG, "new state ["+state+"]");
- if (state == LinphoneCore.RegistrationState.RegistrationOk && lc.getDefaultProxyConfig().isRegistered()) {
- mNotification.iconLevel=IC_LEVEL_ORANGE;
- mNotification.when=System.currentTimeMillis();
- mNotification.setLatestEventInfo(this
- , NOTIFICATION_TITLE
- ,String.format(getString(R.string.notification_registered),lc.getDefaultProxyConfig().getIdentity())
- , mNofificationContentIntent);
- mNotificationManager.notify(NOTIFICATION_ID, mNotification);
- }
- if (state == LinphoneCore.RegistrationState.RegistrationFailed ) {
- mNotification.iconLevel=IC_LEVEL_OFFLINE;
- mNotification.when=System.currentTimeMillis();
- mNotification.setLatestEventInfo(this
- , NOTIFICATION_TITLE
- ,String.format(getString(R.string.notification_register_failure),lc.getDefaultProxyConfig().getIdentity())
- , mNofificationContentIntent);
- mNotificationManager.notify(NOTIFICATION_ID, mNotification);
- }
- mHandler.post(new Runnable() {
- public void run() {
- if (DialerActivity.getDialer()!=null) DialerActivity.getDialer().registrationState(lc,cfg,state,smessage);
- }
- });
- }
- public void callState(final LinphoneCore lc,final LinphoneCall call, final State state, final String message) {
- Log.i(TAG, "new state ["+state+"]");
- if (state == LinphoneCall.State.IncomingReceived && !call.equals(mLinphoneCore.getCurrentCall())) {
- if (call.getReplacedCall()==null){
- //no multicall support, just decline
- mLinphoneCore.terminateCall(call);
- }//otherwise it will be accepted automatically.
-
- return;
- }
- mHandler.post(new Runnable() {
- public void run() {
- if (DialerActivity.getDialer()!=null) DialerActivity.getDialer().callState(lc,call,state,message);
- }
- });
- if (state == LinphoneCall.State.IncomingReceived) {
- //wakeup linphone
- Intent lIntent = new Intent();
- lIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- lIntent.setClass(this, LinphoneActivity.class);
- startActivity(lIntent);
- startRinging();
- }
- if (mCurrentCallState == LinphoneCall.State.IncomingReceived) {
- //previous state was ringing, so stop ringing
- stopRinging();
- //routeAudioToReceiver();
- }
- mCurrentCallState=state;
- }
- public void show(LinphoneCore lc) {
- // TODO Auto-generated method stub
-
- }
-
-
- private void enableDisableAudioCodec(String codec, int rate, int key) throws LinphoneCoreException {
- PayloadType pt = mLinphoneCore.findPayloadType(codec, rate);
- if (pt !=null) {
- boolean enable= mPref.getBoolean(getString(key),false);
- mLinphoneCore.enablePayloadType(pt, enable);
- }
- }
-
- private void enableDisableVideoCodecs(PayloadType videoCodec) throws LinphoneCoreException {
- String mime = videoCodec.getMime();
- int key;
-
- if ("MP4V-ES".equals(mime)) {
- key = R.string.pref_video_codec_mpeg4_key;
- } else if ("H264".equals(mime)) {
- key = R.string.pref_video_codec_h264_key;
- } else if ("H263-1998".equals(mime)) {
- key = R.string.pref_video_codec_h263_key;
- } else {
- Log.e(TAG, "Unhandled video codec " + mime);
- mLinphoneCore.enablePayloadType(videoCodec, false);
- return;
- }
-
- boolean enable= mPref.getBoolean(getString(key),false);
- mLinphoneCore.enablePayloadType(videoCodec, enable);
- }
-
- public void initFromConf() throws LinphoneConfigException, LinphoneException {
- //traces
- boolean lIsDebug = mPref.getBoolean(getString(R.string.pref_debug_key), false);
- LinphoneCoreFactory.instance().setDebugMode(lIsDebug);
-
- try {
- // Configure audio codecs
- enableDisableAudioCodec("speex", 32000, R.string.pref_codec_speex32_key);
- enableDisableAudioCodec("speex", 16000, R.string.pref_codec_speex16_key);
- enableDisableAudioCodec("speex", 8000, R.string.pref_codec_speex8_key);
- enableDisableAudioCodec("iLBC", 8000, R.string.pref_codec_ilbc_key);
- enableDisableAudioCodec("GSM", 8000, R.string.pref_codec_gsm_key);
- enableDisableAudioCodec("PCMU", 8000, R.string.pref_codec_pcmu_key);
- enableDisableAudioCodec("PCMA", 8000, R.string.pref_codec_pcma_key);
-
- // Configure video codecs
- for (PayloadType videoCodec : mLinphoneCore.listVideoCodecs()) {
- enableDisableVideoCodecs(videoCodec);
- }
- if (!mPref.getString(getString(R.string.pref_handle_outcall_key), OutgoingCallReceiver.key_on_demand).equalsIgnoreCase(OutgoingCallReceiver.key_off)){
- IntentFilter lFilter = new IntentFilter(Intent.ACTION_SCREEN_ON);
- lFilter.setPriority(0);
- lFilter.addAction(Intent.ACTION_NEW_OUTGOING_CALL);
- if (mOutgoingCallReceiver == null) {
- mOutgoingCallReceiver = new OutgoingCallReceiver();
- }
- registerReceiver(mOutgoingCallReceiver,lFilter);
- } else if (mOutgoingCallReceiver!=null) {
- unregisterReceiver(mOutgoingCallReceiver);
- mOutgoingCallReceiver=null;
- }
-
- mLinphoneCore.enableEchoCancellation(mPref.getBoolean(getString(R.string.pref_echo_cancellation_key),false));
- } catch (LinphoneCoreException e) {
- throw new LinphoneConfigException(getString(R.string.wrong_settings),e);
- }
- boolean isVideoEnabled = mPref.getBoolean(getString(R.string.pref_video_enable_key),false);
- mLinphoneCore.enableVideo(isVideoEnabled, isVideoEnabled);
- //1 read proxy config from preferences
- String lUserName = mPref.getString(getString(R.string.pref_username_key), null);
- if (lUserName == null || lUserName.length()==0) {
- throw new LinphoneConfigException(getString(R.string.wrong_username));
- }
-
- String lPasswd = mPref.getString(getString(R.string.pref_passwd_key), null);
- if (lPasswd == null || lPasswd.length()==0) {
- throw new LinphoneConfigException(getString(R.string.wrong_passwd));
- }
-
- String lDomain = mPref.getString(getString(R.string.pref_domain_key), null);
- if (lDomain == null || lDomain.length()==0) {
- throw new LinphoneConfigException(getString(R.string.wrong_domain));
- }
-
- String lStun = mPref.getString(getString(R.string.pref_stun_server_key), null);
-
- //stun server
- mLinphoneCore.setStunServer(lStun);
- mLinphoneCore.setFirewallPolicy((lStun!=null && lStun.length()>0) ? FirewallPolicy.UseStun : FirewallPolicy.NoFirewall);
-
- //auth
- mLinphoneCore.clearAuthInfos();
- LinphoneAuthInfo lAuthInfo = LinphoneCoreFactory.instance().createAuthInfo(lUserName, lPasswd,null);
- mLinphoneCore.addAuthInfo(lAuthInfo);
-
-
- //proxy
- mLinphoneCore.clearProxyConfigs();
- String lProxy = mPref.getString(getString(R.string.pref_proxy_key),null);
- if (lProxy == null || lProxy.length() == 0) {
- lProxy = "sip:"+lDomain;
- }
- if (!lProxy.startsWith("sip:")) {
- lProxy = "sip:"+lProxy;
- }
- //get Default proxy if any
- LinphoneProxyConfig lDefaultProxyConfig = mLinphoneCore.getDefaultProxyConfig();
- String lIdentity = "sip:"+lUserName+"@"+lDomain;
- try {
- if (lDefaultProxyConfig == null) {
- lDefaultProxyConfig = LinphoneCoreFactory.instance().createProxyConfig(lIdentity, lProxy, null,true);
- mLinphoneCore.addProxyConfig(lDefaultProxyConfig);
- mLinphoneCore.setDefaultProxyConfig(lDefaultProxyConfig);
-
- } else {
- lDefaultProxyConfig.edit();
- lDefaultProxyConfig.setIdentity(lIdentity);
- lDefaultProxyConfig.setProxy(lProxy);
- lDefaultProxyConfig.enableRegister(true);
- lDefaultProxyConfig.done();
- }
- lDefaultProxyConfig = mLinphoneCore.getDefaultProxyConfig();
-
- if (lDefaultProxyConfig !=null) {
- //prefix
- String lPrefix = mPref.getString(getString(R.string.pref_prefix_key), null);
- if (lPrefix != null) {
- lDefaultProxyConfig.setDialPrefix(lPrefix);
- }
- //escape +
- lDefaultProxyConfig.setDialEscapePlus(mPref.getBoolean(getString(R.string.pref_escape_plus_key),false));
- //outbound proxy
- if (mPref.getBoolean(getString(R.string.pref_enable_outbound_proxy_key), false)) {
- lDefaultProxyConfig.setRoute(lProxy);
- } else {
- lDefaultProxyConfig.setRoute(null);
- }
-
- }
- //init network state
- ConnectivityManager lConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo lInfo = lConnectivityManager.getActiveNetworkInfo();
- mLinphoneCore.setNetworkReachable( lInfo !=null? lConnectivityManager.getActiveNetworkInfo().getState() ==NetworkInfo.State.CONNECTED:false);
-
- } catch (LinphoneCoreException e) {
- throw new LinphoneConfigException(getString(R.string.wrong_settings),e);
- }
- }
+ Intent notifIntent = new Intent(this, LinphoneActivity.class);
+ mNotifContentIntent = PendingIntent.getActivity(this, 0, notifIntent, 0);
+ mNotif.setLatestEventInfo(this, notificationTitle,"", mNotifContentIntent);
+ mNotificationMgr.notify(NOTIF_ID, mNotif);
-
-
-
- protected LinphoneCore getLinphoneCore() {
- return mLinphoneCore;
+
+ LinphoneManager.createAndStart(this, this);
}
+
+
+
+ private void sendNotification(int level, int textId) {
+ mNotif.iconLevel = level;
+ mNotif.when=System.currentTimeMillis();
+ String text = getString(textId);
+ if (text.contains("%s")) {
+ String id = LinphoneManager.getLc().getDefaultProxyConfig().getIdentity();
+ text = String.format(text, id);
+ }
+
+ mNotif.setLatestEventInfo(this, notificationTitle, text, mNotifContentIntent);
+ mNotificationMgr.notify(NOTIF_ID, mNotif);
+ }
+
+
+
+
@Override
public IBinder onBind(Intent intent) {
return null;
@@ -467,78 +143,136 @@ public class LinphoneService extends Service implements LinphoneCoreListener {
@Override
public void onDestroy() {
super.onDestroy();
- mTimer.cancel();
- mLinphoneCore.destroy();
- theLinphone=null;
- mNotificationManager.cancel(NOTIFICATION_ID);
- unregisterReceiver(mKeepAliveMgrReceiver);
- if (mOutgoingCallReceiver != null) unregisterReceiver(mOutgoingCallReceiver);
- }
- public void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf,
- String url) {
- // TODO Auto-generated method stub
-
- }
- public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {
- // TODO Auto-generated method stub
-
- }
- public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,
- LinphoneAddress from, String message) {
- // TODO Auto-generated method stub
-
+ LinphoneManager.destroy(this);
+
+ mNotificationMgr.cancel(NOTIF_ID);
+
+ instance=null;
}
- public static LinphoneCore getLc() {
- return instance().getLinphoneCore();
+
+ private static final LinphoneGuiListener guiListener() {
+ return DialerActivity.instance();
}
- private synchronized void startRinging() {
- try {
- if (mAudioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER) && mVibrator !=null) {
- long[] patern = {0,1000,1000};
- mVibrator.vibrate(patern, 1);
- }
- if (mRingerPlayer == null) {
- mRingerPlayer = new MediaPlayer();
- mRingerPlayer.setAudioStreamType(AudioManager.STREAM_RING);
- mRingerPlayer.setDataSource(getApplicationContext(), RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE));
- mRingerPlayer.prepare();
- mRingerPlayer.setLooping(true);
- mRingerPlayer.start();
- } else {
- Log.w(LinphoneService.TAG,"already ringing");
- }
- } catch (Exception e) {
- Log.e(LinphoneService.TAG, "cannot handle incoming call",e);
- }
+
+
+
+
- }
- private synchronized void stopRinging() {
- if (mRingerPlayer !=null) {
- mRingerPlayer.stop();
- mRingerPlayer.release();
- mRingerPlayer=null;
- }
- if (mVibrator!=null) {
- mVibrator.cancel();
- }
- }
- public void ecCalibrationStatus(final LinphoneCore lc,final EcCalibratorStatus status, final int delay_ms,
- final Object data) {
- final CheckBoxPreference pref = (CheckBoxPreference) data;
+ public void onDisplayStatus(final String message) {
mHandler.post(new Runnable() {
public void run() {
- if (status == EcCalibratorStatus.Done) {
- pref.setSummary(String.format(getString(R.string.ec_calibrated), delay_ms));
- pref.setChecked(true);
-
- } else if (status == EcCalibratorStatus.Failed) {
- pref.setSummary(R.string.failed);
- pref.setChecked(false);
- }
+ if (guiListener() != null) guiListener().onDisplayStatus(message);
}
});
}
+
+ public void onGlobalStateChanged(final GlobalState state, final String message) {
+ if (state == GlobalState.GlobalOn) {
+ sendNotification(IC_LEVEL_OFFLINE, R.string.notification_started);
+
+ mHandler.post(new Runnable() {
+ public void run() {
+ if (guiListener() != null)
+ guiListener().onGlobalStateChangedToOn(message);
+ }
+ });
+ }
+ }
+
+
+ public void onRegistrationStateChanged(final RegistrationState state,
+ final String message) {
+ if (state == RegistrationState.RegistrationOk && LinphoneManager.getLc().getDefaultProxyConfig().isRegistered()) {
+ sendNotification(IC_LEVEL_ORANGE, R.string.notification_registered);
+ }
+
+ if (state == RegistrationState.RegistrationFailed) {
+ sendNotification(IC_LEVEL_OFFLINE, R.string.notification_register_failure);
+ }
+
+ if (state == RegistrationState.RegistrationOk || state == RegistrationState.RegistrationFailed) {
+ mHandler.post(new Runnable() {
+ public void run() {
+ if (LinphoneActivity.isInstanciated())
+ LinphoneActivity.instance().onRegistrationStateChanged(state, message);
+ }
+ });
+ }
+ }
+
+
+ public void onCallStateChanged(final LinphoneCall call, final State state, final String message) {
+ if (state == LinphoneCall.State.IncomingReceived) {
+ //wakeup linphone
+ startActivity(new Intent()
+ .setClass(this, LinphoneActivity.class)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ } else if (state == LinphoneCall.State.StreamsRunning) {
+ if (LinphoneActivity.isInstanciated()
+ && getResources().getBoolean(R.bool.use_video_activity)
+ && LinphoneManager.getLc().getCurrentCall().getCurrentParamsCopy().getVideoEnabled()) {
+ LinphoneActivity.instance().startVideoActivity();
+ }
+ }
+
+ mHandler.post(new Runnable() {
+ public void run() {
+ if (guiListener() != null)
+ guiListener().onCallStateChanged(call, state, message);
+ }
+ });
+ }
+
+
+
+ public interface LinphoneGuiListener extends NewOutgoingCallUiListener {
+ void onDisplayStatus(String message);
+ void onGlobalStateChangedToOn(String message);
+// void onRegistrationStateChanged(RegistrationState state, String message);
+ void onCallStateChanged(LinphoneCall call, State state, String message);
+ }
+
+
+ public void onRingerPlayerCreated(MediaPlayer mRingerPlayer) {
+ final Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
+ try {
+ mRingerPlayer.setDataSource(getApplicationContext(), ringtoneUri);
+ } catch (IOException e) {
+ Log.e(LinphoneManager.TAG, "cannot set ringtone", e);
+ }
+ }
+
+ public void tryingNewOutgoingCallButAlreadyInCall() {
+ mHandler.post(new Runnable() {
+ public void run() {
+ if (guiListener() != null)
+ guiListener().onAlreadyInCall();
+ }
+ });
+ }
+
+ public void tryingNewOutgoingCallButCannotGetCallParameters() {
+ mHandler.post(new Runnable() {
+ public void run() {
+ if (guiListener() != null)
+ guiListener().onCannotGetCallParameters();
+ }
+ });
+ }
+
+ public void tryingNewOutgoingCallButWrongDestinationAddress() {
+ mHandler.post(new Runnable() {
+ public void run() {
+ if (guiListener() != null)
+ guiListener().onWrongDestinationAddress();
+ }
+ });
+ }
+
+ public void onAlreadyInVideoCall() {
+ LinphoneActivity.instance().startVideoActivity();
+ }
}
diff --git a/src/org/linphone/NetworkManager.java b/src/org/linphone/NetworkManager.java
index b5b598c75..877fa72be 100644
--- a/src/org/linphone/NetworkManager.java
+++ b/src/org/linphone/NetworkManager.java
@@ -27,27 +27,34 @@ import android.util.Log;
+/**
+ *
+ * Intercept network state changes and update linphone core through LinphoneManager.
+ *
+ */
public class NetworkManager extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- NetworkInfo lNetworkInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
- Log.i(LinphoneService.TAG, "Network info ["+lNetworkInfo+"]");
+ NetworkInfo lNetworkInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
+ Log.i(LinphoneManager.TAG, "Network info ["+lNetworkInfo+"]");
Boolean lNoConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,false);
- if (!LinphoneService.isready()) {
- Log.i(LinphoneService.TAG, "Linphone service not ready");
+
+
+ if (!LinphoneService.isReady()) {
+ Log.i(LinphoneManager.TAG, "Network broadcast received while Linphone service not ready");
return;
}
- if (lNoConnectivity| ((lNetworkInfo.getState() == NetworkInfo.State.DISCONNECTED) /*&& !lIsFailOver*/)) {
- LinphoneService.instance().getLinphoneCore().setNetworkReachable(false);
+
+
+ if (lNoConnectivity | ((lNetworkInfo.getState() == NetworkInfo.State.DISCONNECTED) /*&& !lIsFailOver*/)) {
+ LinphoneManager.getLc().setNetworkReachable(false);
} else if (lNetworkInfo.getState() == NetworkInfo.State.CONNECTED){
- LinphoneService.instance().getLinphoneCore().setNetworkReachable(true);
+ LinphoneManager.getLc().setNetworkReachable(true);
} else {
- //unhandled event
+ // Other unhandled events
}
-
-
}
}
diff --git a/src/org/linphone/OutgoingCallReceiver.java b/src/org/linphone/OutgoingCallReceiver.java
deleted file mode 100644
index eab2e8db4..000000000
--- a/src/org/linphone/OutgoingCallReceiver.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-OutgoingCallReceiver.java
-Copyright (C) 2010 Belledonne Communications, 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.
-*/
-package org.linphone;
-
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.preference.PreferenceManager;
-
-public class OutgoingCallReceiver extends BroadcastReceiver {
- public static String TAG = ";0000000";
- public static String key_off="off";
- public static String key_on_demand="ask_for_outcall_interception";
- public static String key_always="alway_intercept_out_call";
- @Override
- public void onReceive(Context context, Intent intent) {
- String to = intent.getStringExtra("android.intent.extra.PHONE_NUMBER");
- //do not catch ussd codes
- if (to==null || to.contains("#"))
- return;
- if (!to.contains(TAG)) {
- if (LinphoneService.isready() && LinphoneService.instance().getLinphoneCore().getDefaultProxyConfig()==null) {
- //just return
- return;
- }
- setResult(Activity.RESULT_OK,null, null);
- Intent lIntent = new Intent();
- // 1 check config
- if (PreferenceManager.getDefaultSharedPreferences(context).getString(context.getString(R.string.pref_handle_outcall_key),key_on_demand).equals(key_always)) {
- //start linphone directly
- lIntent.setClass(context, LinphoneActivity.class);
- } else {
- //start activity chooser
- lIntent.setAction(Intent.ACTION_CALL);
- }
-
- lIntent.setData(Uri.parse("tel://"+to+TAG));
- lIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(lIntent);
-
- } else {
- setResult(Activity.RESULT_OK,to.replace(TAG, ""),null);
- }
- }
-
-}
diff --git a/src/org/linphone/VideoCallActivity.java b/src/org/linphone/VideoCallActivity.java
index e7549e0b1..3d6714ce1 100644
--- a/src/org/linphone/VideoCallActivity.java
+++ b/src/org/linphone/VideoCallActivity.java
@@ -20,10 +20,10 @@ package org.linphone;
-import org.linphone.core.AndroidCameraRecordManager;
import org.linphone.core.LinphoneCore;
import org.linphone.core.Version;
import org.linphone.core.VideoSize;
+import org.linphone.core.video.AndroidCameraRecordManager;
import android.app.Activity;
import android.content.Context;
@@ -38,6 +38,11 @@ import android.view.MenuItem;
import android.view.SurfaceView;
import android.view.ViewGroup.LayoutParams;
+/**
+ * For Android SDK >=
+ * @author Guillaume Beraudo
+ *
+ */
public class VideoCallActivity extends Activity {
private SurfaceView mVideoView;
private SurfaceView mVideoCaptureView;
@@ -46,7 +51,6 @@ public class VideoCallActivity extends Activity {
public static boolean launched = false;
private WakeLock mWakeLock;
private static final int capturePreviewLargestDimension = 150;
-// private static final float similarRatio = 0.1f;
private int previousPhoneOrientation;
private int phoneOrientation;
@@ -57,9 +61,9 @@ public class VideoCallActivity extends Activity {
setContentView(R.layout.videocall);
mVideoView = (SurfaceView) findViewById(R.id.video_surface);
- LinphoneCore lc = LinphoneService.getLc();
+ LinphoneCore lc = LinphoneManager.getLc();
lc.setVideoWindow(mVideoView);
-
+
mVideoCaptureView = (SurfaceView) findViewById(R.id.video_capture_surface);
previousPhoneOrientation = AndroidCameraRecordManager.getInstance().getPhoneOrientation();
@@ -68,12 +72,12 @@ public class VideoCallActivity extends Activity {
recordManager.setSurfaceView(mVideoCaptureView, phoneOrientation);
mVideoCaptureView.setZOrderOnTop(true);
- if (!recordManager.isMuted()) sendStaticImage(false);
+ if (!recordManager.isMuted()) LinphoneManager.getInstance().sendStaticImage(false);
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE,"Linphone");
mWakeLock.acquire();
- if (Version.sdkBelow(8)) {
+ if (Version.sdkStrictlyBelow(8)) {
// Force to display in portrait orientation for old devices
// as they do not support surfaceView rotation
setRequestedOrientation(recordManager.isCameraOrientationPortrait() ?
@@ -81,23 +85,17 @@ public class VideoCallActivity extends Activity {
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
- // Base capture frame on streamed dimensions and orientation.
- resizeCapturePreview(mVideoCaptureView, lc.getPreferredVideoSize());
+ resizeCapturePreview(mVideoCaptureView);
}
- private void updateCallIfOrientationChanged() {
- if (Version.sdkAbove(8) && previousPhoneOrientation != phoneOrientation) {
- CallManager.getInstance().updateCall();
- // camera will be restarted when mediastreamer chain is recreated and setParameters is called
-
- // Base capture frame on streamed dimensions and orientation.
- resizeCapturePreview(mVideoCaptureView, LinphoneService.getLc().getPreferredVideoSize());
- }
- }
@Override
protected void onResume() {
- updateCallIfOrientationChanged();
+ // Update call if orientation changed
+ if (Version.sdkAboveOrEqual(8) && previousPhoneOrientation != phoneOrientation) {
+ CallManager.getInstance().updateCall();
+ resizeCapturePreview(mVideoCaptureView);
+ }
super.onResume();
}
@@ -110,6 +108,7 @@ public class VideoCallActivity extends Activity {
}
}
+
private void rewriteChangeResolutionItem(MenuItem item) {
if (BandwidthManager.getInstance().isUserRestriction()) {
item.setTitle(getString(R.string.menu_videocall_change_resolution_when_low_resolution));
@@ -134,23 +133,18 @@ public class VideoCallActivity extends Activity {
return true;
}
- private void sendStaticImage(boolean send) {
- LinphoneCore lc = LinphoneService.getLc();
- if (lc.isIncall()) {
- lc.getCurrentCall().enableCamera(!send);
- }
- }
+
/**
+ * Base capture frame on streamed dimensions and orientation.
* @param sv capture surface view to resize the layout
* @param vs video size from which to calculate the dimensions
*/
- private void resizeCapturePreview(SurfaceView sv, VideoSize vs) {
+ private void resizeCapturePreview(SurfaceView sv) {
LayoutParams lp = sv.getLayoutParams();
- float newRatio = ratioWidthHeight(vs);
+ VideoSize vs = LinphoneManager.getLc().getPreferredVideoSize();
- // float previewRatio = (float) lp.width / lp.height;
-// if (Math.abs((newRatio-previewRatio)/newRatio) < similarRatio) return;
+ float newRatio = (float) vs.width / vs.height;
if (vs.isPortrait()) {
lp.height = capturePreviewLargestDimension;
@@ -162,50 +156,40 @@ public class VideoCallActivity extends Activity {
sv.setLayoutParams(lp);
}
-
+
+
+
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.videocall_menu_back_to_dialer:
- if (!recordManager.isMuted()) sendStaticImage(true);
+ if (!recordManager.isMuted())
+ LinphoneManager.getInstance().sendStaticImage(true);
finish();
break;
case R.id.videocall_menu_change_resolution:
- BandwidthManager manager = BandwidthManager.getInstance();
- manager.setUserRestriction(!manager.isUserRestriction());
- sendStaticImage(recordManager.isMuted());
+ LinphoneManager.getInstance().changeResolution();
rewriteChangeResolutionItem(item);
-
- // Resize preview frame
- VideoSize newVideoSize = LinphoneService.getLc().getPreferredVideoSize();
- resizeCapturePreview(mVideoCaptureView, newVideoSize);
+ resizeCapturePreview(mVideoCaptureView);
break;
case R.id.videocall_menu_terminate_call:
- LinphoneCore lc = LinphoneService.getLc();
- if (lc.isIncall()) {
- lc.terminateCall(lc.getCurrentCall());
- }
+ LinphoneManager.getInstance().terminateCall();
finish();
break;
case R.id.videocall_menu_toggle_camera:
- sendStaticImage(recordManager.toggleMute());
+ LinphoneManager.getInstance().toggleCameraMuting();
rewriteToggleCameraItem(item);
break;
case R.id.videocall_menu_switch_camera:
- recordManager.stopVideoRecording();
- recordManager.toggleUseFrontCamera();
- CallManager.getInstance().updateCall();
- // camera will be restarted when mediastreamer chain is recreated and setParameters is called
-
- // Base capture frame on streamed dimensions and orientation.
- resizeCapturePreview(mVideoCaptureView, LinphoneService.getLc().getPreferredVideoSize());
+ LinphoneManager.getInstance().switchCamera();
+ resizeCapturePreview(mVideoCaptureView);
break;
default:
- Log.e(LinphoneService.TAG, "Unknown menu item ["+item+"]");
+ Log.e(LinphoneManager.TAG, "Unknown menu item ["+item+"]");
break;
}
- return false;
+ return true;
}
@@ -218,13 +202,10 @@ public class VideoCallActivity extends Activity {
@Override
protected void onPause() {
Log.d(tag, "onPause VideoCallActivity");
+ LinphoneManager.getInstance().sendStaticImage(true);
if (mWakeLock.isHeld()) mWakeLock.release();
super.onPause();
}
- public float ratioWidthHeight(VideoSize vs) {
- return (float) vs.width / vs.height;
- }
-
}
diff --git a/src/org/linphone/core/AndroidCameraRecord5Impl.java b/src/org/linphone/core/AndroidCameraRecord5Impl.java
deleted file mode 100644
index 18e487d12..000000000
--- a/src/org/linphone/core/AndroidCameraRecord5Impl.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-AndroidCameraRecordImplAPI5.java
-Copyright (C) 2010 Belledonne Communications, 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.
-*/
-package org.linphone.core;
-
-import java.util.List;
-
-import android.hardware.Camera;
-import android.hardware.Camera.Parameters;
-import android.hardware.Camera.Size;
-import android.util.Log;
-
-
-public class AndroidCameraRecord5Impl extends AndroidCameraRecordImpl {
-
- public AndroidCameraRecord5Impl(RecorderParams parameters) {
- super(parameters);
- }
-
- @Override
- protected void onSettingCameraParameters(Parameters parameters) {
- super.onSettingCameraParameters(parameters);
-
- if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
- Log.w(tag, "Auto Focus supported by camera device");
- parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
- } else {
- Log.w(tag, "Auto Focus not supported by camera device");
- if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_INFINITY)) {
- Log.w(tag, "Infinity Focus supported by camera device");
- parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
- } else {
- Log.w(tag, "Infinity Focus not supported by camera device");
- }
- }
- }
-
- public static List oneShotSupportedVideoSizes() {
- Camera camera = Camera.open();
- List supportedVideoSizes =camera.getParameters().getSupportedPreviewSizes();
- camera.release();
- return supportedVideoSizes;
- }
-
- @Override
- protected List getSupportedPreviewSizes(Parameters parameters) {
- return parameters.getSupportedPreviewSizes();
- }
-}
diff --git a/src/org/linphone/core/AndroidVideoWindowImpl.java b/src/org/linphone/core/AndroidVideoWindowImpl.java
index ec7eb2cbb..243afb472 100644
--- a/src/org/linphone/core/AndroidVideoWindowImpl.java
+++ b/src/org/linphone/core/AndroidVideoWindowImpl.java
@@ -34,11 +34,11 @@ public class AndroidVideoWindowImpl {
mSurface=holder.getSurface();
}
if (mListener!=null) mListener.onSurfaceReady(AndroidVideoWindowImpl.this);
- Log.w("Linphone", "Video display surface changed");
+ Log.w(TAG, "Video display surface changed");
}
public void surfaceCreated(SurfaceHolder holder) {
- Log.w("Linphone", "Video display surface created");
+ Log.w(TAG, "Video display surface created");
}
public void surfaceDestroyed(SurfaceHolder holder) {
@@ -48,7 +48,7 @@ public class AndroidVideoWindowImpl {
}
if (mListener!=null)
mListener.onSurfaceDestroyed(AndroidVideoWindowImpl.this);
- Log.d("Linphone", "Video display surface destroyed");
+ Log.d(TAG, "Video display surface destroyed");
}
});
}
diff --git a/src/org/linphone/Hacks.java b/src/org/linphone/core/Hacks.java
similarity index 84%
rename from src/org/linphone/Hacks.java
rename to src/org/linphone/core/Hacks.java
index 0c6809048..d90588130 100644
--- a/src/org/linphone/Hacks.java
+++ b/src/org/linphone/core/Hacks.java
@@ -16,16 +16,28 @@ 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.
*/
-package org.linphone;
+package org.linphone.core;
+
+import org.linphone.LinphoneManager;
import android.media.AudioManager;
import android.os.Build;
import android.util.Log;
-public class Hacks {
+public final class Hacks {
+
+ private Hacks() {}
public static boolean isGalaxyS() {
- return Build.DEVICE.startsWith("GT-I9000") || Build.DEVICE.startsWith("GT-P1000");
+ return Build.DEVICE.startsWith("GT-I9000");
+ }
+
+ public static boolean isGalaxySOrTab() {
+ return isGalaxyS() || isGalaxyTab();
+ }
+
+ public static boolean isGalaxyTab() {
+ return Build.DEVICE.startsWith("GT-P1000");
}
/* private static final boolean log(final String msg) {
@@ -68,6 +80,6 @@ public class Hacks {
//sb.append("MANUFACTURER=").append(Build.MANUFACTURER).append("\n");
sb.append("SDK=").append(Build.VERSION.SDK);
- Log.d("Linphone", sb.toString());
+ Log.d(LinphoneManager.TAG, sb.toString());
}
}
diff --git a/src/org/linphone/core/LinphoneCallImpl.java b/src/org/linphone/core/LinphoneCallImpl.java
index a7104ffef..b60d92fda 100644
--- a/src/org/linphone/core/LinphoneCallImpl.java
+++ b/src/org/linphone/core/LinphoneCallImpl.java
@@ -36,6 +36,7 @@ class LinphoneCallImpl implements LinphoneCall {
private native void enableEchoLimiter(long nativePtr,boolean enable);
private native boolean isEchoLimiterEnabled(long nativePtr);
private native long getReplacedCall(long nativePtr);
+ private native int getDuration(long nativePtr);
protected LinphoneCallImpl(long aNativePtr) {
nativePtr = aNativePtr;
@@ -96,5 +97,9 @@ class LinphoneCallImpl implements LinphoneCall {
}
return null;
}
+
+ public int getDuration() {
+ return getDuration(nativePtr);
+ }
}
diff --git a/src/org/linphone/core/LinphoneCoreImpl.java b/src/org/linphone/core/LinphoneCoreImpl.java
index 1a9fc67a7..8be2008f3 100644
--- a/src/org/linphone/core/LinphoneCoreImpl.java
+++ b/src/org/linphone/core/LinphoneCoreImpl.java
@@ -91,7 +91,8 @@ class LinphoneCoreImpl implements LinphoneCore {
private native void enableKeepAlive(long nativePtr,boolean enable);
private native boolean isKeepAliveEnabled(long nativePtr);
private native int startEchoCalibration(long nativePtr,Object data);
-
+ private native int getSignalingTransportPort(long nativePtr, int code);
+ private native void setSignalingTransportPorts(long nativePtr, int udp, int tcp, int tls);
LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig,File factoryConfig,Object userdata) throws IOException {
mListener=listener;
@@ -285,10 +286,6 @@ class LinphoneCoreImpl implements LinphoneCore {
public void setPlayLevel(int level) {
// TODO Auto-generated method stub
- }
- public void setSignalingTransport(Transport aTransport) {
- // TODO Auto-generated method stub
-
}
public void enableSpeaker(boolean value) {
// TODO Auto-generated method stub
@@ -439,4 +436,19 @@ class LinphoneCoreImpl implements LinphoneCore {
public void startEchoCalibration(Object data) throws LinphoneCoreException {
startEchoCalibration(nativePtr, data);
}
+
+ public Transports getSignalingTransportPorts() {
+ Transports transports = new Transports();
+ transports.udp = getSignalingTransportPort(nativePtr, 0);
+ transports.tcp = getSignalingTransportPort(nativePtr, 1);
+ transports.tls = getSignalingTransportPort(nativePtr, 3);
+ // See C struct LCSipTransports in linphonecore.h
+ // Code is the index in the structure
+ return transports;
+ }
+ public void setSignalingTransportPorts(Transports transports) {
+ setSignalingTransportPorts(nativePtr, transports.udp, transports.tcp, transports.tls);
+ }
+
+
}
diff --git a/src/org/linphone/core/Version.java b/src/org/linphone/core/Version.java
index 2b938dbea..65d5370d6 100644
--- a/src/org/linphone/core/Version.java
+++ b/src/org/linphone/core/Version.java
@@ -30,12 +30,25 @@ public class Version {
8 : Integer.parseInt(Build.VERSION.SDK); // Force versions above 9 to 8
// 7; // 2.1
- public static final boolean sdkAbove(int value) {
+ public static final boolean sdkAboveOrEqual(int value) {
return buildVersion >= value;
}
- public static final boolean sdkBelow(int value) {
+ public static final boolean sdkStrictlyBelow(int value) {
return buildVersion < value;
}
+ public static int sdk() {
+ return buildVersion;
+ }
+
+ public static boolean isArmv7() {
+ try {
+ return sdkAboveOrEqual(4)
+ && Build.class.getField("CPU_ABI").get(null).toString().startsWith("armeabi-v7");
+ } catch (Throwable e) {}
+ return false;
+ }
+
+
}
\ No newline at end of file
diff --git a/src/org/linphone/core/tutorials/AndroidTutorialNotifier.java b/src/org/linphone/core/tutorials/AndroidTutorialNotifier.java
index 01e0555e2..7721f7dc1 100644
--- a/src/org/linphone/core/tutorials/AndroidTutorialNotifier.java
+++ b/src/org/linphone/core/tutorials/AndroidTutorialNotifier.java
@@ -23,11 +23,12 @@ import android.widget.TextView;
/**
* Write notifications to a TextView widget.
+ * This is an helper class, not a test activity.
*
* @author Guillaume Beraudo
*
*/
-public class AndroidTutorialNotifier extends TutorialNotifier {
+class AndroidTutorialNotifier extends TutorialNotifier {
private Handler mHandler;
private TextView outputTextView;
diff --git a/src/org/linphone/core/tutorials/JavaCameraRecordImpl.java b/src/org/linphone/core/tutorials/JavaCameraRecordImpl.java
index 33cc6b22e..341bd28cc 100644
--- a/src/org/linphone/core/tutorials/JavaCameraRecordImpl.java
+++ b/src/org/linphone/core/tutorials/JavaCameraRecordImpl.java
@@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core.tutorials;
-import org.linphone.core.AndroidCameraRecord;
+import org.linphone.core.video.AndroidCameraRecord;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
@@ -26,7 +26,13 @@ import android.hardware.Camera.Size;
import android.util.Log;
import android.widget.TextView;
-public class JavaCameraRecordImpl extends AndroidCameraRecord implements PreviewCallback {
+/**
+ * This is an helper class, not a test activity.
+ *
+ * @author Guillaume Beraudo
+ *
+ */
+class JavaCameraRecordImpl extends AndroidCameraRecord implements PreviewCallback {
private TextView debug;
private long count = 0;
@@ -53,7 +59,7 @@ public class JavaCameraRecordImpl extends AndroidCameraRecord implements Preview
Size s = camera.getParameters().getPreviewSize();
int expectedBuffLength = s.width * s.height * 3 /2;
if (expectedBuffLength != data.length) {
- Log.e("Linphone", "onPreviewFrame called with bad buffer length " + data.length
+ Log.e(tag, "onPreviewFrame called with bad buffer length " + data.length
+ " whereas expected is " + expectedBuffLength + " don't calling putImage");
return;
}
diff --git a/src/org/linphone/core/tutorials/TestVideoActivity.java b/src/org/linphone/core/tutorials/TestVideoActivity.java
index 6bbdab517..ce3a9185b 100644
--- a/src/org/linphone/core/tutorials/TestVideoActivity.java
+++ b/src/org/linphone/core/tutorials/TestVideoActivity.java
@@ -21,8 +21,8 @@ package org.linphone.core.tutorials;
import java.util.Stack;
import org.linphone.R;
-import org.linphone.core.AndroidCameraRecord;
import org.linphone.core.VideoSize;
+import org.linphone.core.video.AndroidCameraRecord;
import android.app.Activity;
import android.os.Bundle;
diff --git a/src/org/linphone/core/AndroidCameraConf.java b/src/org/linphone/core/video/AndroidCameraConf.java
similarity index 85%
rename from src/org/linphone/core/AndroidCameraConf.java
rename to src/org/linphone/core/video/AndroidCameraConf.java
index 523f249b0..a86e45787 100644
--- a/src/org/linphone/core/AndroidCameraConf.java
+++ b/src/org/linphone/core/video/AndroidCameraConf.java
@@ -16,18 +16,18 @@ 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.
*/
-package org.linphone.core;
+package org.linphone.core.video;
-import org.linphone.Hacks;
+import org.linphone.core.Hacks;
import android.util.Log;
-public class AndroidCameraConf {
+class AndroidCameraConf {
private static final String tag = "Linphone";
public void findFrontAndRearCameraIds(int[] frontCameraId, int[] rearCameraId, int[] cameraId) {
Log.i(tag, "Detecting cameras");
- if (Hacks.isGalaxyS()) {
+ if (Hacks.isGalaxySOrTab()) {
Log.d(tag, "Hack Galaxy S : has 2 cameras front=2; rear=1");
frontCameraId[0] = 2;
rearCameraId[0] = 1;
@@ -39,19 +39,20 @@ public class AndroidCameraConf {
}
public int getNumberOfCameras() {
+ Log.i(tag, "Detecting the number of cameras");
// Use hacks to guess the number of cameras
- if (Hacks.isGalaxyS()) {
+ if (Hacks.isGalaxySOrTab()) {
Log.d(tag, "Hack Galaxy S : has 2 cameras");
return 2;
} else
return 1;
}
-
+
public int getCameraOrientation(int cameraId) {
// Use hacks to guess orientation of the camera
- if (cameraId == 2 && Hacks.isGalaxyS()) {
+ if (cameraId == 2 && Hacks.isGalaxySOrTab()) {
Log.d(tag, "Hack Galaxy S : rear camera id=2 ; mounted landscape");
// mounted in landscape for a portrait phone orientation
return 90;
@@ -64,7 +65,7 @@ public class AndroidCameraConf {
public boolean isFrontCamera(int cameraId) {
// Use hacks to guess facing of the camera
- if (cameraId == 2 && Hacks.isGalaxyS()) {
+ if (cameraId == 2 && Hacks.isGalaxySOrTab()) {
Log.d(tag, "Hack Galaxy S : front camera has id=2");
return true;
}
diff --git a/src/org/linphone/core/AndroidCameraConf9.java b/src/org/linphone/core/video/AndroidCameraConf9.java
similarity index 94%
rename from src/org/linphone/core/AndroidCameraConf9.java
rename to src/org/linphone/core/video/AndroidCameraConf9.java
index 07e49bab0..4c3713b83 100644
--- a/src/org/linphone/core/AndroidCameraConf9.java
+++ b/src/org/linphone/core/video/AndroidCameraConf9.java
@@ -16,11 +16,11 @@ 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.
*/
-package org.linphone.core;
+package org.linphone.core.video;
import android.hardware.Camera;
-public class AndroidCameraConf9 extends AndroidCameraConf {
+class AndroidCameraConf9 extends AndroidCameraConf {
public void findFrontAndRearCameraIds9(Integer frontCameraId, Integer rearCameraId, Integer cameraId) {
for (int id=0; id < getNumberOfCameras(); id++) {
diff --git a/src/org/linphone/core/AndroidCameraRecord.java b/src/org/linphone/core/video/AndroidCameraRecord.java
similarity index 99%
rename from src/org/linphone/core/AndroidCameraRecord.java
rename to src/org/linphone/core/video/AndroidCameraRecord.java
index 6feafc322..64af664f5 100644
--- a/src/org/linphone/core/AndroidCameraRecord.java
+++ b/src/org/linphone/core/video/AndroidCameraRecord.java
@@ -16,7 +16,7 @@ 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.
*/
-package org.linphone.core;
+package org.linphone.core.video;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/src/org/linphone/core/AndroidCameraRecord8Impl.java b/src/org/linphone/core/video/AndroidCameraRecord8.java
similarity index 86%
rename from src/org/linphone/core/AndroidCameraRecord8Impl.java
rename to src/org/linphone/core/video/AndroidCameraRecord8.java
index 490d9ad97..ef8425d7e 100644
--- a/src/org/linphone/core/AndroidCameraRecord8Impl.java
+++ b/src/org/linphone/core/video/AndroidCameraRecord8.java
@@ -16,7 +16,7 @@ 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.
*/
-package org.linphone.core;
+package org.linphone.core.video;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
@@ -30,17 +30,17 @@ import android.util.Log;
* @author Guillaume Beraudo
*
*/
-public class AndroidCameraRecord8Impl extends AndroidCameraRecord5Impl {
+class AndroidCameraRecord8 extends AndroidCameraRecordImpl {
- public AndroidCameraRecord8Impl(RecorderParams parameters) {
+ public AndroidCameraRecord8(RecorderParams parameters) {
super(parameters);
}
@Override
protected void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb) {
if (cb != null) {
- Log.d("Linphone", "Setting optimized callback with buffer (Android >= 8). Remember to manage the pool of buffers!!!");
+ Log.d(tag, "Setting optimized callback with buffer (Android >= 8). Remember to manage the pool of buffers!!!");
}
camera.setPreviewCallbackWithBuffer(cb);
}
diff --git a/src/org/linphone/core/AndroidCameraRecord9Impl.java b/src/org/linphone/core/video/AndroidCameraRecord9.java
similarity index 86%
rename from src/org/linphone/core/AndroidCameraRecord9Impl.java
rename to src/org/linphone/core/video/AndroidCameraRecord9.java
index 0ddb283d2..d81e8103e 100644
--- a/src/org/linphone/core/AndroidCameraRecord9Impl.java
+++ b/src/org/linphone/core/video/AndroidCameraRecord9.java
@@ -16,7 +16,7 @@ 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.
*/
-package org.linphone.core;
+package org.linphone.core.video;
import android.hardware.Camera;
@@ -26,10 +26,10 @@ import android.hardware.Camera;
* @author Guillaume Beraudo
*
*/
-public class AndroidCameraRecord9Impl extends AndroidCameraRecord8Impl {
+class AndroidCameraRecord9 extends AndroidCameraRecord8 {
- public AndroidCameraRecord9Impl(RecorderParams parameters) {
+ public AndroidCameraRecord9(RecorderParams parameters) {
super(parameters);
}
diff --git a/src/org/linphone/core/AndroidCameraRecordImpl.java b/src/org/linphone/core/video/AndroidCameraRecordImpl.java
similarity index 60%
rename from src/org/linphone/core/AndroidCameraRecordImpl.java
rename to src/org/linphone/core/video/AndroidCameraRecordImpl.java
index f1a4f4844..84c22a0e4 100644
--- a/src/org/linphone/core/AndroidCameraRecordImpl.java
+++ b/src/org/linphone/core/video/AndroidCameraRecordImpl.java
@@ -16,19 +16,24 @@ 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.
*/
-package org.linphone.core;
+package org.linphone.core.video;
+
+import java.util.List;
import android.hardware.Camera;
+import android.hardware.Camera.Parameters;
import android.hardware.Camera.PreviewCallback;
+import android.hardware.Camera.Size;
import android.util.Log;
/**
* Record from Android camera.
+ * Android >= 5 (2.0) version.
*
* @author Guillaume Beraudo
*
*/
-public class AndroidCameraRecordImpl extends AndroidCameraRecord implements PreviewCallback {
+class AndroidCameraRecordImpl extends AndroidCameraRecord implements PreviewCallback {
private long filterCtxPtr;
private double timeElapsedBetweenFrames = 0;
@@ -51,17 +56,17 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
public void onPreviewFrame(byte[] data, Camera camera) {
if (data == null) {
- Log.e("Linphone", "onPreviewFrame Called with null buffer");
+ Log.e(tag, "onPreviewFrame Called with null buffer");
return;
}
if (filterCtxPtr == 0l) {
- Log.e("Linphone", "onPreviewFrame Called with no filterCtxPtr set");
+ Log.e(tag, "onPreviewFrame Called with no filterCtxPtr set");
return;
}
int expectedBuffLength = getExpectedBufferLength();
if (expectedBuffLength != data.length) {
- Log.e("Linphone", "onPreviewFrame called with bad buffer length " + data.length
+ Log.e(tag, "onPreviewFrame called with bad buffer length " + data.length
+ " whereas expected is " + expectedBuffLength + " don't calling putImage");
return;
}
@@ -75,7 +80,7 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
double currentTimeElapsed = 0.8 * (curTime - lastFrameTime) / 1000 + 0.2 * timeElapsedBetweenFrames;
if (currentTimeElapsed < expectedTimeBetweenFrames) {
-// Log.d("Linphone", "Clipping frame " + Math.round(1 / currentTimeElapsed) + " > " + fps);
+// Log.d(tag, "Clipping frame " + Math.round(1 / currentTimeElapsed) + " > " + fps);
return;
}
lastFrameTime = curTime;
@@ -85,7 +90,35 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
putImage(filterCtxPtr, data, rotation);
}
+ @Override
+ protected void onSettingCameraParameters(Parameters parameters) {
+ super.onSettingCameraParameters(parameters);
+ if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
+ Log.w(tag, "Auto Focus supported by camera device");
+ parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
+ } else {
+ Log.w(tag, "Auto Focus not supported by camera device");
+ if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_INFINITY)) {
+ Log.w(tag, "Infinity Focus supported by camera device");
+ parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
+ } else {
+ Log.w(tag, "Infinity Focus not supported by camera device");
+ }
+ }
+ }
+
+ public static List oneShotSupportedVideoSizes() {
+ Camera camera = Camera.open();
+ List supportedVideoSizes =camera.getParameters().getSupportedPreviewSizes();
+ camera.release();
+ return supportedVideoSizes;
+ }
+
+ @Override
+ protected List getSupportedPreviewSizes(Parameters parameters) {
+ return parameters.getSupportedPreviewSizes();
+ }
@Override
protected void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb) {
diff --git a/src/org/linphone/core/AndroidCameraRecordManager.java b/src/org/linphone/core/video/AndroidCameraRecordManager.java
similarity index 87%
rename from src/org/linphone/core/AndroidCameraRecordManager.java
rename to src/org/linphone/core/video/AndroidCameraRecordManager.java
index 2ca3d70aa..bf64b615a 100644
--- a/src/org/linphone/core/AndroidCameraRecordManager.java
+++ b/src/org/linphone/core/video/AndroidCameraRecordManager.java
@@ -16,11 +16,12 @@ 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.
*/
-package org.linphone.core;
+package org.linphone.core.video;
import java.util.List;
-import org.linphone.core.AndroidCameraRecord.RecorderParams;
+import org.linphone.core.Version;
+import org.linphone.core.video.AndroidCameraRecord.RecorderParams;
import android.hardware.Camera.Size;
import android.util.Log;
@@ -67,7 +68,7 @@ public class AndroidCameraRecordManager {
// singleton
private AndroidCameraRecordManager() {
- cc = Version.sdkAbove(9) ? new AndroidCameraConf9() : new AndroidCameraConf();
+ cc = Version.sdkAboveOrEqual(9) ? new AndroidCameraConf9() : new AndroidCameraConf();
int[] fId = {-1};int[] rId = {-1};int[] cId = {-1};
cc.findFrontAndRearCameraIds(fId, rId, cId);
@@ -144,14 +145,19 @@ public class AndroidCameraRecordManager {
});
}
- public void setMuted(boolean muteState) {
- if (muteState == muted) return;
+ /**
+ * @param muteState
+ * @return true if mute state changed
+ */
+ public boolean setMuted(boolean muteState) {
+ if (muteState == muted) return false;
muted = muteState;
if (muted) {
stopVideoRecording();
} else {
tryToStartVideoRecording();
}
+ return true;
}
public boolean toggleMute() {
setMuted(!muted);
@@ -172,14 +178,14 @@ public class AndroidCameraRecordManager {
parameters.rotation = bufferRotationForCorrectImageOrientation();
parameters.surfaceView = surfaceView;
- if (Version.sdkAbove(9)) {
- recorder = new AndroidCameraRecord9Impl(parameters);
- } else if (Version.sdkAbove(8)) {
- recorder = new AndroidCameraRecord8Impl(parameters);
- } else if (Version.sdkAbove(5)) {
- recorder = new AndroidCameraRecord5Impl(parameters);
- } else {
+ if (Version.sdkAboveOrEqual(9)) {
+ recorder = new AndroidCameraRecord9(parameters);
+ } else if (Version.sdkAboveOrEqual(8)) {
+ recorder = new AndroidCameraRecord8(parameters);
+ } else if (Version.sdkAboveOrEqual(5)) {
recorder = new AndroidCameraRecordImpl(parameters);
+ } else {
+ throw new RuntimeException("SDK version unsupported " + Version.sdk());
}
recorder.startPreview();
@@ -208,8 +214,8 @@ public class AndroidCameraRecordManager {
if (supportedVideoSizes != null) return supportedVideoSizes;
}
- if (Version.sdkAbove(5)) {
- supportedVideoSizes = AndroidCameraRecord5Impl.oneShotSupportedVideoSizes();
+ if (Version.sdkAboveOrEqual(5)) {
+ supportedVideoSizes = AndroidCameraRecordImpl.oneShotSupportedVideoSizes();
}
// eventually null
@@ -253,7 +259,7 @@ public class AndroidCameraRecordManager {
private int bufferRotationForCorrectImageOrientation() {
final int cameraOrientation = cc.getCameraOrientation(cameraId);
- final int rotation = Version.sdkAbove(8) ?
+ final int rotation = Version.sdkAboveOrEqual(8) ?
(360 - cameraOrientation + 90 - phoneOrientation) % 360
: 0;
Log.d(tag, "Capture video buffer will need a rotation of " + rotation
diff --git a/src/org/linphone/ui/AddVideoButton.java b/src/org/linphone/ui/AddVideoButton.java
new file mode 100644
index 000000000..b3cad9c8c
--- /dev/null
+++ b/src/org/linphone/ui/AddVideoButton.java
@@ -0,0 +1,43 @@
+/*
+AddVideoButton.java
+Copyright (C) 2010 Belledonne Communications, 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.
+ */
+package org.linphone.ui;
+
+import org.linphone.LinphoneManager;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ImageButton;
+
+/**
+ * @author Guillaume Beraudo
+ *
+ */
+public class AddVideoButton extends ImageButton implements OnClickListener {
+
+ public AddVideoButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setOnClickListener(this);
+ }
+
+ public void onClick(View v) {
+ LinphoneManager.getInstance().addVideo();
+ }
+}
diff --git a/src/org/linphone/ui/AddressAware.java b/src/org/linphone/ui/AddressAware.java
new file mode 100644
index 000000000..00c73079f
--- /dev/null
+++ b/src/org/linphone/ui/AddressAware.java
@@ -0,0 +1,31 @@
+/*
+AddressAwareWidget.java
+Copyright (C) 2011 Belledonne Communications, 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.
+*/
+package org.linphone.ui;
+
+
+
+/**
+ * @author Guillaume Beraudo
+ *
+ */
+public interface AddressAware {
+
+ void setAddressWidget(AddressText address);
+
+}
diff --git a/src/org/linphone/ui/AddressText.java b/src/org/linphone/ui/AddressText.java
new file mode 100644
index 000000000..5c4b98f91
--- /dev/null
+++ b/src/org/linphone/ui/AddressText.java
@@ -0,0 +1,64 @@
+/*
+AddressView.java
+Copyright (C) 2010 Belledonne Communications, 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.
+*/
+package org.linphone.ui;
+
+import org.linphone.LinphoneManager.AddressType;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.EditText;
+
+/**
+ * @author Guillaume Beraudo
+ *
+ */
+public class AddressText extends EditText implements AddressType {
+
+ private String displayedName;
+
+ public AddressText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public void clearDisplayedName() {
+ displayedName = "";
+ }
+
+ public String getDisplayedName() {
+ return displayedName;
+ }
+
+ public void setContactAddress(String uri, String displayedName) {
+ setText(uri);
+ this.displayedName = displayedName;
+ }
+
+ public void setDisplayedName(String displayedName) {
+ this.displayedName = displayedName;
+ }
+
+ @Override
+ protected void onTextChanged(CharSequence text, int start, int before,
+ int after) {
+ clearDisplayedName();
+ super.onTextChanged(text, start, before, after);
+ }
+
+
+}
diff --git a/src/org/linphone/ui/CallButton.java b/src/org/linphone/ui/CallButton.java
new file mode 100644
index 000000000..f0223f0f7
--- /dev/null
+++ b/src/org/linphone/ui/CallButton.java
@@ -0,0 +1,73 @@
+/*
+CallButton.java
+Copyright (C) 2010 Belledonne Communications, 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.
+ */
+package org.linphone.ui;
+
+import org.linphone.LinphoneManager;
+import org.linphone.R;
+import org.linphone.core.LinphoneCoreException;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ImageButton;
+import android.widget.Toast;
+
+/**
+ * @author Guillaume Beraudo
+ *
+ */
+public class CallButton extends ImageButton implements OnClickListener, AddressAware {
+
+ private AddressText mAddress;
+ public void setAddressWidget(AddressText a) {mAddress = a;}
+
+ private OnClickListener externalClickListener;
+ public void setExternalClickListener(OnClickListener e) {externalClickListener = e;}
+
+ public CallButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setOnClickListener(this);
+ }
+
+ public void onClick(View v) {
+ try {
+ if (!LinphoneManager.getInstance().acceptCallIfIncomingPending()) {
+ if (mAddress.getText().length() >0) {
+ LinphoneManager.getInstance().newOutgoingCall(mAddress);
+ }
+ }
+ } catch (LinphoneCoreException e) {
+ LinphoneManager.getInstance().terminateCall();
+ onWrongDestinationAddress();
+ };
+
+ if (externalClickListener != null) externalClickListener.onClick(v);
+ }
+
+
+ protected void onWrongDestinationAddress() {
+ Toast toast = Toast.makeText(getContext()
+ ,String.format(getResources().getString(R.string.warning_wrong_destination_address),mAddress.getText().toString())
+ ,Toast.LENGTH_LONG);
+ toast.show();
+ }
+
+
+}
diff --git a/src/org/linphone/ui/Digit.java b/src/org/linphone/ui/Digit.java
new file mode 100644
index 000000000..902657045
--- /dev/null
+++ b/src/org/linphone/ui/Digit.java
@@ -0,0 +1,132 @@
+/*
+Digit.java
+Copyright (C) 2010 Belledonne Communications, 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.
+*/
+package org.linphone.ui;
+
+import org.linphone.LinphoneManager;
+import org.linphone.core.LinphoneCore;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.Button;
+
+public class Digit extends Button implements AddressAware {
+
+ private AddressText mAddress;
+
+
+ @Override
+ protected void onTextChanged(CharSequence text, int start, int before,
+ int after) {
+ super.onTextChanged(text, start, before, after);
+
+ if (text == null || text.length() < 1) return;
+
+ DialKeyListener lListener = new DialKeyListener();
+ setOnClickListener(lListener);
+ setOnTouchListener(lListener);
+
+ if ("0+".equals(text)) {
+ setOnLongClickListener(lListener);
+
+ }
+ }
+
+
+ public Digit(Context context, AttributeSet attrs, int style) {
+ super(context, attrs, style);
+ setLongClickable(true);
+ }
+
+ public Digit(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setLongClickable(true);
+
+ }
+
+ public Digit(Context context) {
+ super(context);
+ setLongClickable(true);
+ }
+
+
+
+
+ private class DialKeyListener implements OnClickListener, OnTouchListener, OnLongClickListener {
+ final CharSequence mKeyCode;
+ boolean mIsDtmfStarted=false;
+
+ DialKeyListener() {
+ mKeyCode = Digit.this.getText().subSequence(0, 1);
+ }
+
+ public void onClick(View v) {
+ LinphoneCore lc = LinphoneManager.getLc();
+ lc.stopDtmf();
+ mIsDtmfStarted =false;
+
+ if (lc.isIncall()) {
+ lc.sendDtmf(mKeyCode.charAt(0));
+ } else if (mAddress != null) {
+ int lBegin = mAddress.getSelectionStart();
+ if (lBegin == -1) {
+ lBegin = mAddress.length();
+ }
+ if (lBegin >=0) {
+ mAddress.getEditableText().insert(lBegin,mKeyCode);
+ }
+ }
+ }
+
+ public boolean onTouch(View v, MotionEvent event) {
+ LinphoneCore lc = LinphoneManager.getLc();
+ if (event.getAction() == MotionEvent.ACTION_DOWN && mIsDtmfStarted ==false) {
+ LinphoneManager.getInstance().playDtmf(getContext().getContentResolver(), mKeyCode.charAt(0));
+ mIsDtmfStarted=true;
+ } else {
+ if (event.getAction() == MotionEvent.ACTION_UP)
+ lc.stopDtmf();
+ mIsDtmfStarted =false;
+ }
+ return false;
+ }
+
+ public boolean onLongClick(View v) {
+ // Called if "0+" dtmf
+ LinphoneCore lc = LinphoneManager.getLc();
+ lc.stopDtmf();
+
+ if (mAddress == null) return true;
+
+ int lBegin = mAddress.getSelectionStart();
+ if (lBegin == -1) {
+ lBegin = mAddress.getEditableText().length();
+ }
+ if (lBegin >=0) {
+ mAddress.getEditableText().insert(lBegin,"+");
+ }
+ return true;
+ }
+ };
+
+ public void setAddressWidget(AddressText address) {
+ mAddress = address;
+ }
+}
diff --git a/src/org/linphone/ui/EraseButton.java b/src/org/linphone/ui/EraseButton.java
new file mode 100644
index 000000000..8e253e765
--- /dev/null
+++ b/src/org/linphone/ui/EraseButton.java
@@ -0,0 +1,59 @@
+/*
+EraseButton.java
+Copyright (C) 2010 Belledonne Communications, 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.
+ */
+package org.linphone.ui;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnLongClickListener;
+import android.widget.Button;
+
+public class EraseButton extends Button implements OnClickListener, OnLongClickListener{
+
+ private AddressText address;
+
+ public EraseButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setOnClickListener(this);
+ setOnLongClickListener(this);
+ }
+
+ public void onClick(View v) {
+ if (address.getText().length() >0) {
+ int lBegin = address.getSelectionStart();
+ if (lBegin == -1) {
+ lBegin = address.getEditableText().length()-1;
+ }
+ if (lBegin >0) {
+ address.getEditableText().delete(lBegin-1,lBegin);
+ }
+ }
+ }
+
+ public boolean onLongClick(View v) {
+ address.getEditableText().clear();
+ return true;
+ }
+
+ public void setAddressView(AddressText view) {
+ address = view;
+ }
+
+}
diff --git a/src/org/linphone/ui/HangCallButton.java b/src/org/linphone/ui/HangCallButton.java
new file mode 100644
index 000000000..706df35ec
--- /dev/null
+++ b/src/org/linphone/ui/HangCallButton.java
@@ -0,0 +1,46 @@
+/*
+HangCallButton.java
+Copyright (C) 2010 Belledonne Communications, 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.
+ */
+package org.linphone.ui;
+
+import org.linphone.LinphoneManager;
+import org.linphone.core.LinphoneCore;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ImageButton;
+
+public class HangCallButton extends ImageButton implements OnClickListener {
+
+ private OnClickListener externalClickListener;
+ public void setExternalClickListener(OnClickListener e) {externalClickListener = e;}
+
+ public HangCallButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setOnClickListener(this);
+ }
+
+ public void onClick(View v) {
+ LinphoneCore lc = LinphoneManager.getLc();
+ lc.terminateCall(lc.getCurrentCall());
+
+ if (externalClickListener != null) externalClickListener.onClick(v);
+ }
+}
diff --git a/src/org/linphone/ui/IncallTimer.java b/src/org/linphone/ui/IncallTimer.java
new file mode 100644
index 000000000..80992fa60
--- /dev/null
+++ b/src/org/linphone/ui/IncallTimer.java
@@ -0,0 +1,93 @@
+/*
+IncallTimer.java
+Copyright (C) 2011 Belledonne Communications, 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.
+*/
+package org.linphone.ui;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+/**
+ * Widget displaying a time
+ * @author Guillaume Beraudo
+ *
+ */
+public class IncallTimer extends TextView {
+
+ public IncallTimer(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public IncallTimer(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public IncallTimer(Context context) {
+ super(context);
+ }
+
+
+ @Override
+ public void setText(CharSequence text, BufferType type) {
+ try {
+ int seconds = Integer.parseInt(text.toString());
+ super.setText(formatTime(seconds), type);
+ } catch (Throwable e) {
+ super.setText(text, type);
+ }
+ }
+
+ protected String formatTime(final int seconds) {
+ String time = String.format("%02d : %02d",
+ (seconds / 60) % 60,
+ seconds % 60);
+
+ int hours = seconds / 3600;
+ if (hours != 0) {
+ return hours + " - " + time;
+ } else {
+ return time;
+ }
+ }
+
+
+ /**
+ * Format time as "days - hh : mm : ss".
+ * @param seconds
+ * @return formated string
+ */
+ /*protected String formatTime(final int seconds) {
+ int value = seconds;
+ StringBuilder sb = new StringBuilder();
+
+ for (int base : Arrays.asList(60, 60, 24)) {
+ if (value == 0) break;
+
+ int remainder = value % base;
+ value /= base;
+
+ if (sb.length() != 0) sb.insert(0, " : ");
+ sb.insert(0, remainder < 10 ? "0" + remainder : remainder);
+ }
+
+ if (value != 0) sb.insert(0, value + " - ");
+
+ return sb.toString();
+ }
+ */
+}
diff --git a/src/org/linphone/ui/MuteMicButton.java b/src/org/linphone/ui/MuteMicButton.java
new file mode 100644
index 000000000..c364d1eab
--- /dev/null
+++ b/src/org/linphone/ui/MuteMicButton.java
@@ -0,0 +1,55 @@
+/*
+SpeakerButton.java
+Copyright (C) 2010 Belledonne Communications, 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.
+ */
+package org.linphone.ui;
+
+import org.linphone.LinphoneManager;
+import org.linphone.ui.ToggleImageButton.OnCheckedChangeListener;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+/**
+ * @author Guillaume Beraudo
+ *
+ */
+public class MuteMicButton extends ToggleImageButton implements OnCheckedChangeListener {
+
+ public MuteMicButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setOnCheckedChangeListener(this);
+ }
+
+
+ public boolean isMicMuted() {
+ return isChecked();
+ }
+
+ public void setMicMuted(boolean state) {
+ setChecked(state);
+ }
+
+
+ public void onCheckedChanged(ToggleImageButton button, boolean checked) {
+ if (checked) {
+ LinphoneManager.getLc().muteMic(true);
+ } else {
+ LinphoneManager.getLc().muteMic(false);
+ }
+ }
+}
diff --git a/src/org/linphone/ui/Numpad.java b/src/org/linphone/ui/Numpad.java
new file mode 100644
index 000000000..5a0a19e1d
--- /dev/null
+++ b/src/org/linphone/ui/Numpad.java
@@ -0,0 +1,68 @@
+/*
+NumpadView.java
+Copyright (C) 2010 Belledonne Communications, 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.
+*/
+package org.linphone.ui;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.linphone.R;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+/**
+ * @author Guillaume Beraudo
+ *
+ */
+public class Numpad extends LinearLayout implements AddressAware {
+
+ public Numpad(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ LayoutInflater.from(context).inflate(R.layout.numpad, this);
+ setLongClickable(true);
+ }
+
+ public void setAddressWidget(AddressText address) {
+ for (AddressAware v : retrieveChildren(this)) {
+ v.setAddressWidget(address);
+ }
+ }
+
+
+ private Collection retrieveChildren(ViewGroup viewGroup) {
+ final Collection views = new ArrayList();
+
+ for (int i = 0; i < viewGroup.getChildCount(); i++) {
+ View v = viewGroup.getChildAt(i);
+ if (v instanceof ViewGroup) {
+ views.addAll(retrieveChildren((ViewGroup) v));
+ } else {
+ if (v instanceof AddressAware)
+ views.add((AddressAware) v);
+ }
+ }
+
+ return views;
+ }
+
+}
diff --git a/src/org/linphone/ui/SpeakerButton.java b/src/org/linphone/ui/SpeakerButton.java
new file mode 100644
index 000000000..f15ec6782
--- /dev/null
+++ b/src/org/linphone/ui/SpeakerButton.java
@@ -0,0 +1,57 @@
+/*
+SpeakerButton.java
+Copyright (C) 2010 Belledonne Communications, 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.
+*/
+package org.linphone.ui;
+
+import org.linphone.LinphoneManager;
+import org.linphone.ui.ToggleImageButton.OnCheckedChangeListener;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+/**
+ * @author Guillaume Beraudo
+ *
+ */
+public class SpeakerButton extends ToggleImageButton implements OnCheckedChangeListener {
+
+ public SpeakerButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setOnCheckedChangeListener(this);
+ }
+
+
+ public boolean isSpeakerOn() {
+ return isChecked();
+ }
+
+ public void setSpeakerOn(boolean state) {
+ setChecked(state);
+ }
+
+
+ public void onCheckedChanged(ToggleImageButton button, boolean checked) {
+ if (checked) {
+ LinphoneManager.getInstance().routeAudioToSpeaker();
+ } else {
+ LinphoneManager.getInstance().routeAudioToReceiver();
+ }
+ }
+
+
+}
diff --git a/src/org/linphone/component/ToggleImageButton.java b/src/org/linphone/ui/ToggleImageButton.java
similarity index 92%
rename from src/org/linphone/component/ToggleImageButton.java
rename to src/org/linphone/ui/ToggleImageButton.java
index 8cfa1e917..d4e61006d 100644
--- a/src/org/linphone/component/ToggleImageButton.java
+++ b/src/org/linphone/ui/ToggleImageButton.java
@@ -16,7 +16,7 @@ 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.
*/
-package org.linphone.component;
+package org.linphone.ui;
import android.content.Context;
@@ -36,7 +36,8 @@ import android.widget.ImageButton;
*
*/
public class ToggleImageButton extends ImageButton implements OnClickListener {
- private static final String namespace = null;
+// private static final String ns = "http://schemas.android.com/apk/res/linphone";
+ private static final String ns = null;
private boolean checked;
private Drawable stateChecked;
private Drawable stateUnChecked;
@@ -44,8 +45,8 @@ public class ToggleImageButton extends ImageButton implements OnClickListener {
public ToggleImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
- stateChecked = getResources().getDrawable(attrs.getAttributeResourceValue(namespace, "checked", -1));
- stateUnChecked = getResources().getDrawable(attrs.getAttributeResourceValue(namespace, "unchecked", -1));
+ stateChecked = getResources().getDrawable(attrs.getAttributeResourceValue(ns, "checked", -1));
+ stateUnChecked = getResources().getDrawable(attrs.getAttributeResourceValue(ns, "unchecked", -1));
setBackgroundColor(Color.TRANSPARENT);
setOnClickListener(this);
diff --git a/submodules/linphone b/submodules/linphone
index aff1134b3..2e35f52d3 160000
--- a/submodules/linphone
+++ b/submodules/linphone
@@ -1 +1 @@
-Subproject commit aff1134b38c23eccadc4ee40c7cba7b10b6d04ef
+Subproject commit 2e35f52d35dc6f2e22ffa85130ad233172a5f488