blob: 04b2e213ce5619dc89dd1089eb664e44d8632582 [file] [log] [blame]
alisionfde875f2013-05-28 17:01:54 -04001/*
Alexandre Lisionc1024c02014-01-06 11:12:53 -05002 * Copyright (C) 2004-2014 Savoir-Faire Linux Inc.
alisionfde875f2013-05-28 17:01:54 -04003 *
4 * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * Additional permission under GNU GPL version 3 section 7:
21 *
22 * If you modify this program, or any covered work, by linking or
23 * combining it with the OpenSSL project's OpenSSL library (or a
24 * modified version of that library), containing parts covered by the
25 * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
26 * grants you additional permission to convey the resulting work.
27 * Corresponding Source for a non-source form of such a combination
28 * shall include the source code for the parts of OpenSSL used as well
29 * as that of the covered work.
30 */
31
Alexandre Lision064e1e02013-10-01 16:18:42 -040032package org.sflphone.fragments;
alision84813a12013-05-27 17:40:39 -040033
Alexandre Lision2b237922013-09-09 16:23:02 -040034import java.util.ArrayList;
Alexandre Lision31f46fc2013-09-26 11:19:54 -040035import java.util.Locale;
Alexandre Lision2b237922013-09-09 16:23:02 -040036
Alexandre Lisiona3c4f5f2014-01-07 17:22:22 -050037import android.content.BroadcastReceiver;
38import android.content.IntentFilter;
39import android.net.wifi.WifiInfo;
40import android.net.wifi.WifiManager;
Alexandre Lision064e1e02013-10-01 16:18:42 -040041import org.sflphone.R;
42import org.sflphone.model.Attractor;
43import org.sflphone.model.Bubble;
Alexandre Lision40954dc2013-10-09 15:24:03 -040044import org.sflphone.model.BubbleContact;
Alexandre Lision064e1e02013-10-01 16:18:42 -040045import org.sflphone.model.BubbleModel;
Alexandre Lision40954dc2013-10-09 15:24:03 -040046import org.sflphone.model.BubbleUser;
Alexandre Lision064e1e02013-10-01 16:18:42 -040047import org.sflphone.model.BubblesView;
Alexandre Lision68855472013-10-10 16:20:46 -040048import org.sflphone.model.CallContact;
Alexandre Lision064e1e02013-10-01 16:18:42 -040049import org.sflphone.model.Conference;
50import org.sflphone.model.SipCall;
51import org.sflphone.service.ISipService;
52
alision84813a12013-05-27 17:40:39 -040053import android.app.Activity;
54import android.app.Fragment;
Alexandre Lision2b237922013-09-09 16:23:02 -040055import android.app.FragmentManager;
Alexandre Lisionf1850c02013-09-23 14:19:34 -040056import android.content.Context;
Alexandre Lision2b237922013-09-09 16:23:02 -040057import android.content.Intent;
alision84813a12013-05-27 17:40:39 -040058import android.graphics.Bitmap;
Adrien Béraud0c9bd8f2013-05-30 16:16:57 +100059import android.graphics.BitmapFactory;
alision84813a12013-05-27 17:40:39 -040060import android.graphics.PointF;
61import android.os.Bundle;
Alexandre Lisionf02190d2013-12-12 17:26:12 -050062import android.os.PowerManager;
alision84813a12013-05-27 17:40:39 -040063import android.os.RemoteException;
Alexandre Lisionf02190d2013-12-12 17:26:12 -050064import android.os.PowerManager.WakeLock;
alision84813a12013-05-27 17:40:39 -040065import android.util.Log;
Alexandre Lision64dc8c02013-09-25 15:32:25 -040066import android.view.KeyEvent;
alision84813a12013-05-27 17:40:39 -040067import android.view.LayoutInflater;
Alexandre Lisiond588bff2013-10-08 12:43:01 -040068import android.view.Menu;
69import android.view.MenuInflater;
70import android.view.MenuItem;
Adrien Béraud13cde0b2013-05-30 20:27:20 +100071import android.view.SurfaceHolder;
72import android.view.SurfaceHolder.Callback;
alision84813a12013-05-27 17:40:39 -040073import android.view.View;
Alexandre Lision84208a32013-09-25 13:18:37 -040074import android.view.View.OnClickListener;
alision84813a12013-05-27 17:40:39 -040075import android.view.ViewGroup;
Alexandre Lision84208a32013-09-25 13:18:37 -040076import android.view.inputmethod.InputMethodManager;
Alexandre Lision35577132013-12-06 15:21:15 -050077import android.widget.CompoundButton;
78import android.widget.CompoundButton.OnCheckedChangeListener;
Alexandre Lision84208a32013-09-25 13:18:37 -040079import android.widget.ImageButton;
Alexandre Lision3c6b7102013-09-16 16:56:46 -040080import android.widget.TextView;
Alexandre Lision35577132013-12-06 15:21:15 -050081import android.widget.ToggleButton;
alision84813a12013-05-27 17:40:39 -040082
Alexandre Lisionfda4d1d2013-10-25 15:29:53 -040083public class CallFragment extends Fragment implements Callback {
alision84813a12013-05-27 17:40:39 -040084
alision1005ba12013-06-19 13:52:44 -040085 static final String TAG = "CallFragment";
alision84813a12013-05-27 17:40:39 -040086
alisionf57d8a62013-07-02 09:37:12 -040087 float BUBBLE_SIZE = 75;
alision1005ba12013-06-19 13:52:44 -040088 static final float ATTRACTOR_SIZE = 40;
alision84813a12013-05-27 17:40:39 -040089
Alexandre Lision2b237922013-09-09 16:23:02 -040090 public static final int REQUEST_TRANSFER = 10;
91
alisiondf1dac92013-06-27 17:35:53 -040092 private Conference conf;
alision84813a12013-05-27 17:40:39 -040093
Alexandre Lision3c6b7102013-09-16 16:56:46 -040094 private TextView callStatusTxt;
Alexandre Lision35577132013-12-06 15:21:15 -050095 private ToggleButton speakers;
Alexandre Lisionb8add812013-10-24 11:42:42 -040096
Alexandre Lisionf02190d2013-12-12 17:26:12 -050097 private PowerManager powerManager;
98 // Screen wake lock for incoming call
99 private WakeLock wakeLock;
100
alision1005ba12013-06-19 13:52:44 -0400101 private BubblesView view;
102 private BubbleModel model;
alision84813a12013-05-27 17:40:39 -0400103
Alexandre Lision68855472013-10-10 16:20:46 -0400104 public Callbacks mCallbacks = sDummyCallbacks;
Alexandre Lisiona764c682013-09-09 10:02:07 -0400105 boolean accepted = false;
alision1005ba12013-06-19 13:52:44 -0400106 private Bitmap call_icon;
alision85704182013-05-29 15:23:03 -0400107
Alexandre Lision0eb02032013-09-27 16:32:40 -0400108 TransferDFragment editName;
Alexandre Lisiona3c4f5f2014-01-07 17:22:22 -0500109 private WifiManager wifiManager;
110 private BroadcastReceiver wifiReceiver = new BroadcastReceiver() {
111
112 @Override
113 public void onReceive(Context context, Intent intent) {
114 WifiInfo info = wifiManager.getConnectionInfo();
115 Log.i(TAG, "Level of wifi " +info.getRssi());
116 }
117
118 };
Alexandre Lisionf1850c02013-09-23 14:19:34 -0400119
alision1005ba12013-06-19 13:52:44 -0400120 @Override
121 public void onCreate(Bundle savedBundle) {
122 super.onCreate(savedBundle);
Alexandre Lisiondafe9512013-10-28 16:31:41 -0400123 conf = new Conference((Conference) getArguments().getParcelable("conference"));
alisiondf1dac92013-06-27 17:35:53 -0400124 model = new BubbleModel(getResources().getDisplayMetrics().density);
alision729b0a22013-07-02 11:57:33 -0400125 BUBBLE_SIZE = getResources().getDimension(R.dimen.bubble_size);
Alexandre Lisiona764c682013-09-09 10:02:07 -0400126 Log.e(TAG, "BUBBLE_SIZE " + BUBBLE_SIZE);
Alexandre Lisiond588bff2013-10-08 12:43:01 -0400127 this.setHasOptionsMenu(true);
alision729b0a22013-07-02 11:57:33 -0400128
Alexandre Lisionf02190d2013-12-12 17:26:12 -0500129 powerManager = (PowerManager) getActivity().getSystemService(Context.POWER_SERVICE);
130 wakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE,
131 "org.sflphone.onIncomingCall");
132 wakeLock.setReferenceCounted(false);
133
134 Log.d(TAG, "Acquire wake up lock");
135 if (wakeLock != null && !wakeLock.isHeld()) {
136 wakeLock.acquire();
137 }
Alexandre Lisiona3c4f5f2014-01-07 17:22:22 -0500138 }
Alexandre Lisionf02190d2013-12-12 17:26:12 -0500139
Alexandre Lisiona3c4f5f2014-01-07 17:22:22 -0500140 private void initializeWiFiListener(){
141 Log.i(TAG, "executing initializeWiFiListener");
142
143 String connectivity_context = Context.WIFI_SERVICE;
144 wifiManager = (WifiManager) getActivity().getSystemService(connectivity_context);
145
146 if(!wifiManager.isWifiEnabled()){
147 if(wifiManager.getWifiState() != WifiManager.WIFI_STATE_ENABLING){
148 wifiManager.setWifiEnabled(true);
149 }
150 }
151
152 getActivity().registerReceiver(wifiReceiver, new IntentFilter(WifiManager.RSSI_CHANGED_ACTION));
alision1005ba12013-06-19 13:52:44 -0400153 }
alision85992112013-05-29 12:18:08 -0400154
alision1005ba12013-06-19 13:52:44 -0400155 /**
156 * A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity.
157 */
158 private static Callbacks sDummyCallbacks = new Callbacks() {
alision85704182013-05-29 15:23:03 -0400159
alision1005ba12013-06-19 13:52:44 -0400160 @Override
161 public ISipService getService() {
162 return null;
163 }
alisiondf1dac92013-06-27 17:35:53 -0400164
Alexandre Lisionccf0c932013-10-10 16:24:41 -0400165 @Override
Alexandre Lisiondafe9512013-10-28 16:31:41 -0400166 public void terminateCall() {
Alexandre Lisionccf0c932013-10-10 16:24:41 -0400167 }
Alexandre Lision0c384512013-09-17 17:15:57 -0400168
169 @Override
Adrien Béraude78d06f2013-09-19 13:33:44 +1000170 public void startTimer() {
Alexandre Lision0c384512013-09-17 17:15:57 -0400171 }
Alexandre Lision68855472013-10-10 16:20:46 -0400172
173 @Override
Alexandre Lisionb8add812013-10-24 11:42:42 -0400174 public void slideChatScreen() {
Alexandre Lision68855472013-10-10 16:20:46 -0400175 }
alision1005ba12013-06-19 13:52:44 -0400176 };
alision907bde72013-06-20 14:40:37 -0400177
alision1005ba12013-06-19 13:52:44 -0400178 /**
179 * The Activity calling this fragment has to implement this interface
180 *
181 */
182 public interface Callbacks {
alision85992112013-05-29 12:18:08 -0400183
alision1005ba12013-06-19 13:52:44 -0400184 public ISipService getService();
alision85704182013-05-29 15:23:03 -0400185
Alexandre Lision0c384512013-09-17 17:15:57 -0400186 public void startTimer();
Alexandre Lision68855472013-10-10 16:20:46 -0400187
188 public void slideChatScreen();
Alexandre Lisionb8add812013-10-24 11:42:42 -0400189
Alexandre Lisiondafe9512013-10-28 16:31:41 -0400190 public void terminateCall();
alision1005ba12013-06-19 13:52:44 -0400191 }
alision85992112013-05-29 12:18:08 -0400192
alision1005ba12013-06-19 13:52:44 -0400193 @Override
194 public void onAttach(Activity activity) {
195 super.onAttach(activity);
alision85992112013-05-29 12:18:08 -0400196
alision1005ba12013-06-19 13:52:44 -0400197 if (!(activity instanceof Callbacks)) {
198 throw new IllegalStateException("Activity must implement fragment's callbacks.");
199 }
alision85992112013-05-29 12:18:08 -0400200
alision1005ba12013-06-19 13:52:44 -0400201 // rootView.requestDisallowInterceptTouchEvent(true);
alision85992112013-05-29 12:18:08 -0400202
alision1005ba12013-06-19 13:52:44 -0400203 mCallbacks = (Callbacks) activity;
Alexandre Lisionb8add812013-10-24 11:42:42 -0400204 // myself = SipCall.SipCallBuilder.buildMyselfCall(activity.getContentResolver(), "Me");
Adrien Béraude78d06f2013-09-19 13:33:44 +1000205
alision1005ba12013-06-19 13:52:44 -0400206 }
Alexandre Lisionb8add812013-10-24 11:42:42 -0400207
Alexandre Lisiond588bff2013-10-08 12:43:01 -0400208 @Override
209 public void onCreateOptionsMenu(Menu m, MenuInflater inf) {
210 super.onCreateOptionsMenu(m, inf);
Alexandre Lision68855472013-10-10 16:20:46 -0400211 inf.inflate(R.menu.ac_call, m);
Alexandre Lisiond588bff2013-10-08 12:43:01 -0400212 }
213
214 @Override
215 public boolean onOptionsItemSelected(MenuItem item) {
216 super.onOptionsItemSelected(item);
Alexandre Lision666b3772013-10-28 17:42:48 -0400217 switch (item.getItemId()) {
218 case R.id.menuitem_chat:
219 mCallbacks.slideChatScreen();
220 break;
221 }
Alexandre Lisiond588bff2013-10-08 12:43:01 -0400222
223 return true;
224 }
alision85992112013-05-29 12:18:08 -0400225
alision1005ba12013-06-19 13:52:44 -0400226 @Override
227 public void onDetach() {
228 super.onDetach();
229 mCallbacks = sDummyCallbacks;
alision1005ba12013-06-19 13:52:44 -0400230 }
alision907bde72013-06-20 14:40:37 -0400231
alision1005ba12013-06-19 13:52:44 -0400232 @Override
alision907bde72013-06-20 14:40:37 -0400233 public void onStop() {
alision1005ba12013-06-19 13:52:44 -0400234 super.onStop();
235 }
alision85992112013-05-29 12:18:08 -0400236
alision1005ba12013-06-19 13:52:44 -0400237 @Override
Alexandre Lisionf1850c02013-09-23 14:19:34 -0400238 public void onResume() {
239 super.onResume();
Alexandre Lisiona3c4f5f2014-01-07 17:22:22 -0500240 initializeWiFiListener();
Alexandre Lisionf1850c02013-09-23 14:19:34 -0400241 }
242
243 @Override
244 public void onPause() {
245 super.onPause();
Alexandre Lisiona3c4f5f2014-01-07 17:22:22 -0500246 getActivity().unregisterReceiver(wifiReceiver);
Alexandre Lisionf02190d2013-12-12 17:26:12 -0500247 if (wakeLock != null && wakeLock.isHeld()) {
248 wakeLock.release();
249 }
250
Alexandre Lisionf1850c02013-09-23 14:19:34 -0400251 }
252
253 @Override
Alexandre Lision2b237922013-09-09 16:23:02 -0400254 public void onActivityResult(int requestCode, int resultCode, Intent data) {
255 super.onActivityResult(requestCode, resultCode, data);
256 SipCall transfer = null;
257 if (requestCode == REQUEST_TRANSFER) {
258 switch (resultCode) {
Adrien Béraude78d06f2013-09-19 13:33:44 +1000259 case TransferDFragment.RESULT_TRANSFER_CONF:
Alexandre Lision2b237922013-09-09 16:23:02 -0400260 Conference c = data.getParcelableExtra("target");
261 transfer = data.getParcelableExtra("transfer");
262 try {
263
264 mCallbacks.getService().attendedTransfer(transfer.getCallId(), c.getParticipants().get(0).getCallId());
265
266 } catch (RemoteException e) {
Alexandre Lision2b237922013-09-09 16:23:02 -0400267 e.printStackTrace();
268 }
Alexandre Lision2b237922013-09-09 16:23:02 -0400269 break;
270
Adrien Béraude78d06f2013-09-19 13:33:44 +1000271 case TransferDFragment.RESULT_TRANSFER_NUMBER:
Alexandre Lision2b237922013-09-09 16:23:02 -0400272 String to = data.getStringExtra("to_number");
273 transfer = data.getParcelableExtra("transfer");
274 try {
Alexandre Lision2b237922013-09-09 16:23:02 -0400275 mCallbacks.getService().transfer(transfer.getCallId(), to);
276 mCallbacks.getService().hangUp(transfer.getCallId());
277 } catch (RemoteException e) {
Alexandre Lision2b237922013-09-09 16:23:02 -0400278 e.printStackTrace();
279 }
280 break;
Adrien Béraud97512842013-09-19 13:37:19 +1000281 case Activity.RESULT_CANCELED:
Alexandre Lision2b237922013-09-09 16:23:02 -0400282 default:
Adrien Béraude78d06f2013-09-19 13:33:44 +1000283 model.clear();
284 initNormalStateDisplay();
Alexandre Lision2b237922013-09-09 16:23:02 -0400285 break;
286 }
287 }
288 }
289
290 @Override
alision1005ba12013-06-19 13:52:44 -0400291 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Alexandre Lision84208a32013-09-25 13:18:37 -0400292 final ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.frag_call, container, false);
alision85992112013-05-29 12:18:08 -0400293
alision1005ba12013-06-19 13:52:44 -0400294 view = (BubblesView) rootView.findViewById(R.id.main_view);
alision34673e62013-06-25 14:40:07 -0400295 view.setFragment(this);
alision1005ba12013-06-19 13:52:44 -0400296 view.setModel(model);
297 view.getHolder().addCallback(this);
alision84813a12013-05-27 17:40:39 -0400298
Alexandre Lision3c6b7102013-09-16 16:56:46 -0400299 callStatusTxt = (TextView) rootView.findViewById(R.id.call_status_txt);
Alexandre Lision68855472013-10-10 16:20:46 -0400300 call_icon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_action_call);
Alexandre Lisioncb2345c2013-12-09 15:39:13 -0500301
Alexandre Lisionbaeeb212013-12-09 12:54:47 -0500302 speakers = (ToggleButton) rootView.findViewById(R.id.speaker_toggle);
Alexandre Lisioncb2345c2013-12-09 15:39:13 -0500303
Alexandre Lision35577132013-12-06 15:21:15 -0500304 speakers.setOnCheckedChangeListener(new OnCheckedChangeListener() {
Alexandre Lisioncb2345c2013-12-09 15:39:13 -0500305
Alexandre Lision35577132013-12-06 15:21:15 -0500306 @Override
307 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
308 try {
309 mCallbacks.getService().toggleSpeakerPhone(isChecked);
310 } catch (RemoteException e) {
311 e.printStackTrace();
312 }
Alexandre Lisioncb2345c2013-12-09 15:39:13 -0500313
Alexandre Lision35577132013-12-06 15:21:15 -0500314 }
315 });
alision84813a12013-05-27 17:40:39 -0400316
Alexandre Lision84208a32013-09-25 13:18:37 -0400317 ((ImageButton) rootView.findViewById(R.id.dialpad_btn)).setOnClickListener(new OnClickListener() {
318
319 @Override
320 public void onClick(View v) {
321 InputMethodManager lManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
322 lManager.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_IMPLICIT_ONLY);
323 }
324 });
325
alision1005ba12013-06-19 13:52:44 -0400326 return rootView;
327 }
Alexandre Lisionc30e8412013-09-26 15:12:59 -0400328
alision1005ba12013-06-19 13:52:44 -0400329 private void initNormalStateDisplay() {
330 Log.i(TAG, "Start normal display");
alision84813a12013-05-27 17:40:39 -0400331
Alexandre Lision0c384512013-09-17 17:15:57 -0400332 mCallbacks.startTimer();
alision84813a12013-05-27 17:40:39 -0400333
Alexandre Lisionee2494d2013-10-09 17:14:00 -0400334 getBubbleForUser(conf, model.width / 2, model.height / 2);
alision907bde72013-06-20 14:40:37 -0400335
alisiondf1dac92013-06-27 17:35:53 -0400336 int angle_part = 360 / conf.getParticipants().size();
alision806e18e2013-06-21 15:30:17 -0400337 double dX = 0;
338 double dY = 0;
alision465ceba2013-07-04 09:24:30 -0400339 int radiusCalls = (int) (model.width / 2 - BUBBLE_SIZE);
alisiondf1dac92013-06-27 17:35:53 -0400340 for (int i = 0; i < conf.getParticipants().size(); ++i) {
341
342 if (conf.getParticipants().get(i) == null) {
alisiondf1dac92013-06-27 17:35:53 -0400343 continue;
344 }
alision34673e62013-06-25 14:40:07 -0400345 dX = Math.cos(Math.toRadians(angle_part * i - 90)) * radiusCalls;
346 dY = Math.sin(Math.toRadians(angle_part * i - 90)) * radiusCalls;
alisiondf1dac92013-06-27 17:35:53 -0400347 getBubbleFor(conf.getParticipants().get(i), (int) (model.width / 2 + dX), (int) (model.height / 2 + dY));
alision806e18e2013-06-21 15:30:17 -0400348 }
alision1005ba12013-06-19 13:52:44 -0400349
350 model.clearAttractors();
alision1005ba12013-06-19 13:52:44 -0400351 }
alision85704182013-05-29 15:23:03 -0400352
alision1005ba12013-06-19 13:52:44 -0400353 private void initIncomingCallDisplay() {
354 Log.i(TAG, "Start incoming display");
alision84813a12013-05-27 17:40:39 -0400355
Alexandre Lision0c384512013-09-17 17:15:57 -0400356 mCallbacks.startTimer();
alision84813a12013-05-27 17:40:39 -0400357
Alexandre Lision23628c12013-09-24 11:17:05 -0400358 int radiusCalls = (int) (model.width / 2 - BUBBLE_SIZE);
Alexandre Lisionee2494d2013-10-09 17:14:00 -0400359 getBubbleForUser(conf, model.width / 2, model.height / 2 + radiusCalls);
Alexandre Lision23628c12013-09-24 11:17:05 -0400360 getBubbleFor(conf.getParticipants().get(0), model.width / 2, model.height / 2 - radiusCalls);
alision85704182013-05-29 15:23:03 -0400361
alision1005ba12013-06-19 13:52:44 -0400362 model.clearAttractors();
Alexandre Lision23628c12013-09-24 11:17:05 -0400363 model.addAttractor(new Attractor(new PointF(model.width / 2, model.height / 2), ATTRACTOR_SIZE, new Attractor.Callback() {
alision1005ba12013-06-19 13:52:44 -0400364 @Override
365 public boolean onBubbleSucked(Bubble b) {
Alexandre Lisiona764c682013-09-09 10:02:07 -0400366
367 if (!accepted) {
Alexandre Lision68855472013-10-10 16:20:46 -0400368 try {
369 mCallbacks.getService().accept(b.getCallID());
370 } catch (RemoteException e) {
371 e.printStackTrace();
372 }
Alexandre Lisiona764c682013-09-09 10:02:07 -0400373 accepted = true;
374 }
alision1005ba12013-06-19 13:52:44 -0400375 return false;
376 }
377 }, call_icon));
Alexandre Lisioncb2345c2013-12-09 15:39:13 -0500378
379 if (conf.getParticipants().get(0).getAccount().isAutoanswerEnabled()) {
Alexandre Lision332f4912013-11-12 13:04:32 -0500380 try {
381 mCallbacks.getService().accept(conf.getParticipants().get(0).getCallId());
382 } catch (RemoteException e) {
383 e.printStackTrace();
384 }
385 }
alision1005ba12013-06-19 13:52:44 -0400386 }
alision85704182013-05-29 15:23:03 -0400387
alision1005ba12013-06-19 13:52:44 -0400388 private void initOutGoingCallDisplay() {
389 Log.i(TAG, "Start outgoing display");
alision85704182013-05-29 15:23:03 -0400390
Alexandre Lision0c384512013-09-17 17:15:57 -0400391 mCallbacks.startTimer();
alision85704182013-05-29 15:23:03 -0400392
Alexandre Lisionee2494d2013-10-09 17:14:00 -0400393 getBubbleForUser(conf, model.width / 2, model.height / 2);
alision85704182013-05-29 15:23:03 -0400394
alisiondf1dac92013-06-27 17:35:53 -0400395 // TODO off-thread image loading
396 int angle_part = 360 / conf.getParticipants().size();
397 double dX = 0;
398 double dY = 0;
Adrien Béraude78d06f2013-09-19 13:33:44 +1000399 int radiusCalls = (int) (model.width / 2 - BUBBLE_SIZE);
alisiondf1dac92013-06-27 17:35:53 -0400400 for (int i = 0; i < conf.getParticipants().size(); ++i) {
401 dX = Math.cos(Math.toRadians(angle_part * i - 90)) * radiusCalls;
402 dY = Math.sin(Math.toRadians(angle_part * i - 90)) * radiusCalls;
403 getBubbleFor(conf.getParticipants().get(i), (int) (model.width / 2 + dX), (int) (model.height / 2 + dY));
404 }
alision907bde72013-06-20 14:40:37 -0400405
alision1005ba12013-06-19 13:52:44 -0400406 model.clearAttractors();
alision1005ba12013-06-19 13:52:44 -0400407 }
alision85704182013-05-29 15:23:03 -0400408
alision1005ba12013-06-19 13:52:44 -0400409 /**
410 * Retrieves or create a bubble for a given contact. If the bubble exists, it is moved to the new location.
411 *
alision806e18e2013-06-21 15:30:17 -0400412 * @param call
413 * The call associated to a contact
alision1005ba12013-06-19 13:52:44 -0400414 * @param x
415 * Initial or new x position.
416 * @param y
417 * Initial or new y position.
418 * @return Bubble corresponding to the contact.
419 */
alision806e18e2013-06-21 15:30:17 -0400420 private Bubble getBubbleFor(SipCall call, float x, float y) {
Alexandre Lisionee2494d2013-10-09 17:14:00 -0400421 Bubble contact_bubble = model.getBubble(call.getCallId());
alision1005ba12013-06-19 13:52:44 -0400422 if (contact_bubble != null) {
Alexandre Lisionb8add812013-10-24 11:42:42 -0400423 ((BubbleContact) contact_bubble).setCall(call);
alision1005ba12013-06-19 13:52:44 -0400424 contact_bubble.attractor.set(x, y);
425 return contact_bubble;
426 }
alision84813a12013-05-27 17:40:39 -0400427
Alexandre Lision40954dc2013-10-09 15:24:03 -0400428 contact_bubble = new BubbleContact(getActivity(), call, x, y, BUBBLE_SIZE);
429
430 model.addBubble(contact_bubble);
431 return contact_bubble;
432 }
Alexandre Lisionb8add812013-10-24 11:42:42 -0400433
Alexandre Lisionee2494d2013-10-09 17:14:00 -0400434 private Bubble getBubbleForUser(Conference conf, float x, float y) {
Alexandre Lisiond5686032013-10-29 11:09:21 -0400435 Bubble contact_bubble = model.getUser();
Alexandre Lision40954dc2013-10-09 15:24:03 -0400436 if (contact_bubble != null) {
437 contact_bubble.attractor.set(x, y);
Alexandre Lisionb8add812013-10-24 11:42:42 -0400438 ((BubbleUser) contact_bubble).setConference(conf);
Alexandre Lisioncb2345c2013-12-09 15:39:13 -0500439
Alexandre Lision40954dc2013-10-09 15:24:03 -0400440 return contact_bubble;
441 }
442
Alexandre Lisioncb2345c2013-12-09 15:39:13 -0500443 contact_bubble = new BubbleUser(getActivity(), CallContact.ContactBuilder.buildUserContact(getActivity().getContentResolver()), conf, x, y,
444 BUBBLE_SIZE * 1.3f);
alision84813a12013-05-27 17:40:39 -0400445
Alexandre Lisionc9fca9e2013-11-08 15:21:18 -0500446 try {
447 ((BubbleUser) contact_bubble).setMute(mCallbacks.getService().isCaptureMuted());
448 } catch (RemoteException e) {
449 e.printStackTrace();
Alexandre Lisioncb2345c2013-12-09 15:39:13 -0500450 } catch (NullPointerException e1) {
Alexandre Lisionc9fca9e2013-11-08 15:21:18 -0500451 e1.printStackTrace();
452 }
alision1005ba12013-06-19 13:52:44 -0400453 model.addBubble(contact_bubble);
alision1005ba12013-06-19 13:52:44 -0400454 return contact_bubble;
455 }
Adrien Béraud0c9bd8f2013-05-30 16:16:57 +1000456
alision1005ba12013-06-19 13:52:44 -0400457 public void changeCallState(String callID, String newState) {
Alexandre Lisione4b95842013-11-12 10:36:51 -0500458 Log.i(TAG, "Call :" + callID + " " + newState);
alisiondf1dac92013-06-27 17:35:53 -0400459 if (newState.contentEquals("FAILURE")) {
460 try {
461 mCallbacks.getService().hangUp(callID);
462 } catch (RemoteException e) {
463 e.printStackTrace();
alision806e18e2013-06-21 15:30:17 -0400464 }
alision1005ba12013-06-19 13:52:44 -0400465 }
Alexandre Lisioncb2345c2013-12-09 15:39:13 -0500466 if (conf == null) {
Alexandre Lisione4b95842013-11-12 10:36:51 -0500467 return;
468 }
alisiondf1dac92013-06-27 17:35:53 -0400469 for (int i = 0; i < conf.getParticipants().size(); ++i) {
alisiondf1dac92013-06-27 17:35:53 -0400470 if (callID.equals(conf.getParticipants().get(i).getCallId())) {
471 if (newState.contentEquals("HUNGUP")) {
alisiondf1dac92013-06-27 17:35:53 -0400472 model.removeBubble(conf.getParticipants().get(i));
473 conf.getParticipants().remove(i);
474 } else {
475 conf.getParticipants().get(i).setCallState(newState);
476 }
477 }
478 }
479
Alexandre Lision4fb22622013-10-21 16:26:33 -0400480 if (conf.isOnGoing()) {
alisiondf1dac92013-06-27 17:35:53 -0400481 initNormalStateDisplay();
Alexandre Lision4fb22622013-10-21 16:26:33 -0400482 }
alisiondf1dac92013-06-27 17:35:53 -0400483
Alexandre Lisionccf0c932013-10-10 16:24:41 -0400484 if (conf.getParticipants().size() == 0) {
Alexandre Lisione4b95842013-11-12 10:36:51 -0500485 callStatusTxt.setText(newState);
Alexandre Lisiondafe9512013-10-28 16:31:41 -0400486 mCallbacks.terminateCall();
Alexandre Lisionccf0c932013-10-10 16:24:41 -0400487 }
alision1005ba12013-06-19 13:52:44 -0400488 }
alision84813a12013-05-27 17:40:39 -0400489
alision1005ba12013-06-19 13:52:44 -0400490 public boolean draggingBubble() {
491 return view == null ? false : view.isDraggingBubble();
492 }
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000493
alision1005ba12013-06-19 13:52:44 -0400494 @Override
495 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Adrien Béraud13cde0b2013-05-30 20:27:20 +1000496
alisiondf1dac92013-06-27 17:35:53 -0400497 if (conf.getParticipants().size() == 1) {
alisiondf1dac92013-06-27 17:35:53 -0400498 if (conf.getParticipants().get(0).isIncoming() && conf.getParticipants().get(0).isRinging()) {
alision806e18e2013-06-21 15:30:17 -0400499 initIncomingCallDisplay();
500 } else {
alisiondf1dac92013-06-27 17:35:53 -0400501 if (conf.getParticipants().get(0).isRinging()) {
alision1005ba12013-06-19 13:52:44 -0400502 initOutGoingCallDisplay();
503 }
alision806e18e2013-06-21 15:30:17 -0400504 try {
alisiondf1dac92013-06-27 17:35:53 -0400505 if (conf.getParticipants().get(0).isOutGoing()
Alexandre Lisiona9ee4eb2014-01-15 16:20:35 -0500506 && mCallbacks.getService().getConference(conf.getId()) == null) {
alisiondf1dac92013-06-27 17:35:53 -0400507 mCallbacks.getService().placeCall(conf.getParticipants().get(0));
alision806e18e2013-06-21 15:30:17 -0400508 initOutGoingCallDisplay();
alisiondf1dac92013-06-27 17:35:53 -0400509 } else if (conf.getParticipants().get(0).isOutGoing() && conf.getParticipants().get(0).isRinging()) {
alision806e18e2013-06-21 15:30:17 -0400510 initOutGoingCallDisplay();
511 }
512 } catch (RemoteException e) {
513 Log.e(TAG, e.toString());
514 }
alision1005ba12013-06-19 13:52:44 -0400515 }
alisiondf1dac92013-06-27 17:35:53 -0400516 if (conf.getParticipants().get(0).isOngoing()) {
alision806e18e2013-06-21 15:30:17 -0400517 initNormalStateDisplay();
518 }
alisiondf1dac92013-06-27 17:35:53 -0400519 } else if (conf.getParticipants().size() > 1) {
alision1005ba12013-06-19 13:52:44 -0400520 initNormalStateDisplay();
521 }
alision1005ba12013-06-19 13:52:44 -0400522 }
Adrien Béraud13cde0b2013-05-30 20:27:20 +1000523
Alexandre Lision40954dc2013-10-09 15:24:03 -0400524 public void makeTransfer(BubbleContact contact) {
Alexandre Lision2b237922013-09-09 16:23:02 -0400525 FragmentManager fm = getFragmentManager();
Alexandre Lision0eb02032013-09-27 16:32:40 -0400526 editName = TransferDFragment.newInstance();
Alexandre Lision2b237922013-09-09 16:23:02 -0400527 Bundle b = new Bundle();
Alexandre Lision6ae652d2013-09-26 16:39:20 -0400528 try {
Alexandre Lisionb8add812013-10-24 11:42:42 -0400529 b.putParcelableArrayList("calls", (ArrayList<Conference>) mCallbacks.getService().getConcurrentCalls());
Alexandre Lision6ae652d2013-09-26 16:39:20 -0400530 b.putParcelable("call_selected", contact.associated_call);
531 editName.setArguments(b);
532 editName.setTargetFragment(this, REQUEST_TRANSFER);
533 editName.show(fm, "");
534 } catch (RemoteException e) {
535 Log.e(TAG, e.toString());
536 }
537
Alexandre Lision2b237922013-09-09 16:23:02 -0400538 }
539
alision1005ba12013-06-19 13:52:44 -0400540 @Override
541 public void surfaceCreated(SurfaceHolder holder) {
Alexandre Lisionc30e8412013-09-26 15:12:59 -0400542
alision1005ba12013-06-19 13:52:44 -0400543 }
Adrien Béraud13cde0b2013-05-30 20:27:20 +1000544
alision1005ba12013-06-19 13:52:44 -0400545 @Override
546 public void surfaceDestroyed(SurfaceHolder holder) {
Alexandre Lision84208a32013-09-25 13:18:37 -0400547 // check that soft input is hidden
548 InputMethodManager lManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
549 lManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
Alexandre Lisionb8add812013-10-24 11:42:42 -0400550 if (editName != null && editName.isVisible()) {
Alexandre Lision0eb02032013-09-27 16:32:40 -0400551 editName.dismiss();
552 }
alision1005ba12013-06-19 13:52:44 -0400553 }
Adrien Béraud13cde0b2013-05-30 20:27:20 +1000554
alisione38001f2013-06-04 14:14:39 -0400555 public BubblesView getBubbleView() {
556 return view;
alision1005ba12013-06-19 13:52:44 -0400557 }
Alexandre Lision0c384512013-09-17 17:15:57 -0400558
559 public void updateTime() {
Alexandre Lision945e4612014-01-15 17:40:31 -0500560 long duration = System.currentTimeMillis() / 1000 - this.conf.getParticipants().get(0).getTimestampStart_();
Alexandre Lisioncb2345c2013-12-09 15:39:13 -0500561 if (conf.isOnGoing())
Alexandre Lisione4b95842013-11-12 10:36:51 -0500562 callStatusTxt.setText(String.format("%d:%02d:%02d", duration / 3600, duration % 3600 / 60, duration % 60));
Alexandre Lisionf1850c02013-09-23 14:19:34 -0400563 }
564
Alexandre Lision0edf18c2013-09-23 17:35:50 -0400565 public Conference getConference() {
566 return conf;
567 }
Alexandre Lision64dc8c02013-09-25 15:32:25 -0400568
569 public void onKeyUp(int keyCode, KeyEvent event) {
570 try {
Alexandre Lisionb8add812013-10-24 11:42:42 -0400571
Alexandre Lisionfda4d1d2013-10-25 15:29:53 -0400572 switch (keyCode) {
573 case KeyEvent.KEYCODE_VOLUME_DOWN:
574 case KeyEvent.KEYCODE_VOLUME_UP:
575 break;
576 default:
577 String toSend = Character.toString(event.getDisplayLabel());
578 toSend.toUpperCase(Locale.getDefault());
579 Log.d(TAG, "toSend " + toSend);
580 mCallbacks.getService().playDtmf(toSend);
581 break;
582 }
Alexandre Lision64dc8c02013-09-25 15:32:25 -0400583 } catch (RemoteException e) {
584 e.printStackTrace();
Alexandre Lision3e1e06f2014-02-10 12:13:25 -0500585 } catch (NullPointerException e) {
586 e.printStackTrace();
Alexandre Lision64dc8c02013-09-25 15:32:25 -0400587 }
588 }
alision84813a12013-05-27 17:40:39 -0400589}