blob: 41c802b2a8b5420253c5fefd9e8bd380642daa01 [file] [log] [blame]
Alexandre Savard14323be2012-10-24 10:02:13 -04001/*
2 * Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
3 *
4 * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
Adrien Béraud71b2f812013-04-26 18:51:02 +10005 * Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
alisionfde875f2013-05-28 17:01:54 -04006 * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
Alexandre Savard14323be2012-10-24 10:02:13 -04007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 * Additional permission under GNU GPL version 3 section 7:
23 *
24 * If you modify this program, or any covered work, by linking or
25 * combining it with the OpenSSL project's OpenSSL library (or a
26 * modified version of that library), containing parts covered by the
27 * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
28 * grants you additional permission to convey the resulting work.
29 * Corresponding Source for a non-source form of such a combination
30 * shall include the source code for the parts of OpenSSL used as well
31 * as that of the covered work.
32 */
33
34package com.savoirfairelinux.sflphone.client;
35
alision85704182013-05-29 15:23:03 -040036import java.util.HashMap;
Adrien Béraud33268882013-05-18 03:41:15 +100037import java.util.concurrent.ExecutorService;
38import java.util.concurrent.Executors;
39
Alexandre Savard14323be2012-10-24 10:02:13 -040040import android.app.Activity;
Alexandre Savard6d54bbc2012-10-24 11:04:23 -040041import android.content.ComponentName;
alision17052d42013-04-22 10:39:38 -040042import android.content.Context;
Alexandre Savard6d54bbc2012-10-24 11:04:23 -040043import android.content.Intent;
alision84813a12013-05-27 17:40:39 -040044import android.content.IntentFilter;
Alexandre Savard6d54bbc2012-10-24 11:04:23 -040045import android.content.ServiceConnection;
Alexandre Savard14323be2012-10-24 10:02:13 -040046import android.os.Bundle;
alision85992112013-05-29 12:18:08 -040047import android.os.Environment;
Alexandre Savard6d54bbc2012-10-24 11:04:23 -040048import android.os.IBinder;
alision85992112013-05-29 12:18:08 -040049import android.os.RemoteException;
alisionfde875f2013-05-28 17:01:54 -040050import android.support.v4.widget.SlidingPaneLayout;
Alexandre Savard6d54bbc2012-10-24 11:04:23 -040051import android.util.Log;
alisionfde875f2013-05-28 17:01:54 -040052import android.view.View;
Adrien Béraud33268882013-05-18 03:41:15 +100053import android.widget.Toast;
Alexandre Savard14323be2012-10-24 10:02:13 -040054
55import com.savoirfairelinux.sflphone.R;
alision84813a12013-05-27 17:40:39 -040056import com.savoirfairelinux.sflphone.client.receiver.CallReceiver;
57import com.savoirfairelinux.sflphone.fragments.CallFragment;
alisionfde875f2013-05-28 17:01:54 -040058import com.savoirfairelinux.sflphone.fragments.CallListFragment;
alision84813a12013-05-27 17:40:39 -040059import com.savoirfairelinux.sflphone.interfaces.CallInterface;
alisiond45da712013-05-30 09:18:49 -040060import com.savoirfairelinux.sflphone.model.CallContact;
alisionf76de3b2013-04-16 15:35:22 -040061import com.savoirfairelinux.sflphone.model.SipCall;
alision85992112013-05-29 12:18:08 -040062import com.savoirfairelinux.sflphone.model.SipCall.state;
alision84813a12013-05-27 17:40:39 -040063import com.savoirfairelinux.sflphone.service.CallManagerCallBack;
Alexandre Savard6d54bbc2012-10-24 11:04:23 -040064import com.savoirfairelinux.sflphone.service.ISipService;
65import com.savoirfairelinux.sflphone.service.SipService;
Adrien Béraudc9c424d2013-05-30 17:47:35 +100066import com.savoirfairelinux.sflphone.views.CallPaneLayout;
Alexandre Savard14323be2012-10-24 10:02:13 -040067
alisionfde875f2013-05-28 17:01:54 -040068public class CallActivity extends Activity implements CallInterface, CallFragment.Callbacks, CallListFragment.Callbacks {
Adrien Béraudc9c424d2013-05-30 17:47:35 +100069 static final String TAG = "CallActivity";
70 private ISipService service;
alision84813a12013-05-27 17:40:39 -040071
Adrien Béraudc9c424d2013-05-30 17:47:35 +100072 private String pendingAction = null;
Adrien Béraud33268882013-05-18 03:41:15 +100073
Adrien Béraudc9c424d2013-05-30 17:47:35 +100074 private ExecutorService infos_fetcher = Executors.newCachedThreadPool();
75 CallReceiver receiver;
alision85992112013-05-29 12:18:08 -040076
Adrien Béraudc9c424d2013-05-30 17:47:35 +100077 CallPaneLayout slidingPaneLayout;
Adrien Béraud33268882013-05-18 03:41:15 +100078
Adrien Béraudc9c424d2013-05-30 17:47:35 +100079 CallListFragment mCallsFragment;
80 CallFragment mCurrentCallFragment;
Alexandre Savard4f42ade2012-10-24 18:03:31 -040081
Adrien Béraudc9c424d2013-05-30 17:47:35 +100082 @Override
83 protected void onCreate(Bundle savedInstanceState) {
84 super.onCreate(savedInstanceState);
85 setContentView(R.layout.activity_call_layout);
Alexandre Savard4f42ade2012-10-24 18:03:31 -040086
Adrien Béraudc9c424d2013-05-30 17:47:35 +100087 receiver = new CallReceiver(this);
Adrien Béraud33268882013-05-18 03:41:15 +100088
Adrien Béraudc9c424d2013-05-30 17:47:35 +100089 mCallsFragment = new CallListFragment();
Adrien Béraud33268882013-05-18 03:41:15 +100090
Adrien Béraudc9c424d2013-05-30 17:47:35 +100091 getFragmentManager().beginTransaction().replace(R.id.calllist_pane, mCallsFragment).commit();
alision85992112013-05-29 12:18:08 -040092
Adrien Béraudc9c424d2013-05-30 17:47:35 +100093 slidingPaneLayout = (CallPaneLayout) findViewById(R.id.slidingpanelayout);
Adrien Béraud13cde0b2013-05-30 20:27:20 +100094 //slidingPaneLayout.
Adrien Béraudc9c424d2013-05-30 17:47:35 +100095 // slidingPaneLayout.requestDisallowInterceptTouchEvent(disallowIntercept)
96 slidingPaneLayout.setPanelSlideListener(new SlidingPaneLayout.PanelSlideListener() {
alision84813a12013-05-27 17:40:39 -040097
Adrien Béraudc9c424d2013-05-30 17:47:35 +100098 @Override
99 public void onPanelSlide(View view, float offSet) {
100 }
alisionfde875f2013-05-28 17:01:54 -0400101
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000102 @Override
103 public void onPanelOpened(View view) {
alisionfde875f2013-05-28 17:01:54 -0400104
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000105 switch (view.getId()) {
106 case R.id.calllist_pane:
107 // getFragmentManager().findFragmentById(R.id.calllist_pane).setHasOptionsMenu(true);
108 // getFragmentManager().findFragmentById(R.id.ongoingcall_pane).setHasOptionsMenu(false);
109 break;
110 default:
111 break;
112 }
113 }
alisionfde875f2013-05-28 17:01:54 -0400114
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000115 @Override
116 public void onPanelClosed(View view) {
alisionfde875f2013-05-28 17:01:54 -0400117
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000118 switch (view.getId()) {
119 case R.id.ongoingcall_pane:
120 // getFragmentManager().findFragmentById(R.id.calllist_pane).setHasOptionsMenu(false);
121 // getFragmentManager().findFragmentById(R.id.ongoingcall_pane).setHasOptionsMenu(true);
122 break;
123 default:
124 break;
125 }
126 }
127 });
alisionfde875f2013-05-28 17:01:54 -0400128
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000129 Bundle b = getIntent().getExtras();
Adrien Béraud33268882013-05-18 03:41:15 +1000130
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000131 Intent intent = new Intent(this, SipService.class);
alisiond45da712013-05-30 09:18:49 -0400132
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000133 // setCallStateDisplay(mCall.getCallStateString());
alisiond45da712013-05-30 09:18:49 -0400134
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000135 bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
alisiond45da712013-05-30 09:18:49 -0400136
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000137 }
Alexandre Savard6d54bbc2012-10-24 11:04:23 -0400138
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000139 /* activity gets back to the foreground and user input */
140 @Override
141 protected void onResume() {
142 Log.i(TAG, "onResume");
143 IntentFilter intentFilter = new IntentFilter();
144 intentFilter.addAction(CallManagerCallBack.INCOMING_CALL);
145 intentFilter.addAction(CallManagerCallBack.INCOMING_TEXT);
146 intentFilter.addAction(CallManagerCallBack.CALL_STATE_CHANGED);
147 registerReceiver(receiver, intentFilter);
148 super.onResume();
149 }
Alexandre Savard6d54bbc2012-10-24 11:04:23 -0400150
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000151 /* activity no more in foreground */
152 @Override
153 protected void onPause() {
154 super.onPause();
155 unregisterReceiver(receiver);
156 }
Adrien Béraud6bbce912013-05-24 00:48:13 +1000157
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000158 @Override
159 protected void onDestroy() {
160 // Log.i(TAG, "Destroying Call Activity for call " + mCall.getCallId());
161 // LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
162 unbindService(mConnection);
Adrien Béraud33268882013-05-18 03:41:15 +1000163
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000164 super.onDestroy();
165 }
Adrien Béraud33268882013-05-18 03:41:15 +1000166
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000167 /** Defines callbacks for service binding, passed to bindService() */
168 private ServiceConnection mConnection = new ServiceConnection() {
169 @Override
170 public void onServiceConnected(ComponentName className, IBinder binder) {
171 service = ISipService.Stub.asInterface(binder);
172 Log.i(TAG, "Placing call");
173 mCurrentCallFragment = new CallFragment();
174 mCurrentCallFragment.setArguments(getIntent().getExtras());
175 slidingPaneLayout.curFragment = mCurrentCallFragment;
176 getIntent().getExtras();
177 // SipCall info = getIntent().getExtras().getParcelable("CallInfo");
178 // mCallPagerAdapter.addCall(info.mCallID, newCall);
179 getFragmentManager().beginTransaction().replace(R.id.ongoingcall_pane, mCurrentCallFragment).commit();
Adrien Béraud33268882013-05-18 03:41:15 +1000180
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000181 }
Alexandre Savard6d54bbc2012-10-24 11:04:23 -0400182
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000183 @Override
184 public void onServiceDisconnected(ComponentName arg0) {
185 }
186 };
alisiond8c83882013-05-17 17:00:42 -0400187
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000188 @Override
189 public void incomingCall(Intent call) {
190 Toast.makeText(this, "New Call incoming", Toast.LENGTH_LONG).show();
Adrien Béraud6bbce912013-05-24 00:48:13 +1000191
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000192 mCallsFragment.update();
Adrien Béraud6bbce912013-05-24 00:48:13 +1000193
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000194 }
Alexandre Savarde41f5212012-10-26 14:23:50 -0400195
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000196 @Override
197 public void callStateChanged(Intent callState) {
Alexandre Savarddf544262012-10-25 14:24:08 -0400198
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000199 Bundle b = callState.getBundleExtra("com.savoirfairelinux.sflphone.service.newstate");
200 processCallStateChangedSignal(b.getString("CallID"), b.getString("State"));
alision84813a12013-05-27 17:40:39 -0400201
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000202 }
alision84813a12013-05-27 17:40:39 -0400203
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000204 public void processCallStateChangedSignal(String callID, String newState) {
205 /*
206 * Bundle bundle = intent.getBundleExtra("com.savoirfairelinux.sflphone.service.newstate"); String callID = bundle.getString("CallID"); String
207 * newState = bundle.getString("State");
208 */
209 // CallFragment fr = mCurrentCallFragment;
alision84813a12013-05-27 17:40:39 -0400210
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000211 mCallsFragment.update();
alision84813a12013-05-27 17:40:39 -0400212
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000213 mCurrentCallFragment.changeCallState(callID, newState);
alision84813a12013-05-27 17:40:39 -0400214
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000215 HashMap<String, SipCall> map;
216 try {
217 map = (HashMap<String, SipCall>) service.getCallList();
218 if(map.size() == 0){
219 finish();
220 }
221 } catch (RemoteException e) {
222 Log.e(TAG, e.toString());
223 }
alision84813a12013-05-27 17:40:39 -0400224
Adrien Béraud29556042013-04-26 17:35:43 +1000225
alision84813a12013-05-27 17:40:39 -0400226
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000227 // if (newState.equals("INCOMING")) {
228 // fr.changeCallState(SipCall.state.CALL_STATE_INCOMING);
229 //
230 // } else if (newState.equals("RINGING")) {
231 // fr.changeCallState(SipCall.state.CALL_STATE_RINGING);
232 //
233 // } else if (newState.equals("CURRENT")) {
234 // fr.changeCallState(SipCall.state.CALL_STATE_CURRENT);
235 //
236 // } else if (newState.equals("HUNGUP")) {
237 // // mCallPagerAdapter.remove(callID);
238 // // if (mCallPagerAdapter.getCount() == 0) {
239 // // finish();
240 // // }
241 //
242 // } else if (newState.equals("BUSY")) {
243 // // mCallPagerAdapter.remove(callID);
244 // // if (mCallPagerAdapter.getCount() == 0) {
245 // // finish();
246 // // }
247 //
248 // } else if (newState.equals("FAILURE")) {
249 // // mCallPagerAdapter.remove(callID);
250 // // if (mCallPagerAdapter.getCount() == 0) {
251 // // finish();
252 // // }
253 //
254 // } else if (newState.equals("HOLD")) {
255 // fr.changeCallState(SipCall.state.CALL_STATE_HOLD);
256 //
257 // } else if (newState.equals("UNHOLD")) {
258 // fr.changeCallState(SipCall.state.CALL_STATE_CURRENT);
259 //
260 // } else {
261 // fr.changeCallState(SipCall.state.CALL_STATE_NONE);
262 //
263 // }
Adrien Béraudc99b8432013-04-25 16:27:46 +1000264
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000265 Log.w(TAG, "processCallStateChangedSignal " + newState);
Adrien Béraud29556042013-04-26 17:35:43 +1000266
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000267 }
Adrien Béraud71b2f812013-04-26 18:51:02 +1000268
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000269 @Override
270 public void incomingText(Intent msg) {
271 Toast.makeText(this, "New Call incoming", Toast.LENGTH_LONG).show();
Adrien Béraud29556042013-04-26 17:35:43 +1000272
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000273 // TODO link text message to associate call and display it at the right place
Adrien Béraud71b2f812013-04-26 18:51:02 +1000274
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000275 }
alision7f18fc82013-05-01 09:37:33 -0400276
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000277 @Override
278 public ISipService getService() {
279 return service;
280 }
alision04a00182013-05-10 17:05:29 -0400281
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000282 @Override
283 public void onCallSelected(SipCall call) {
284 mCurrentCallFragment = new CallFragment();
285 Bundle b = new Bundle();
286 b.putParcelable("CallInfo", call);
287 mCurrentCallFragment.setArguments(b);
288 getFragmentManager().beginTransaction().replace(R.id.ongoingcall_pane, mCurrentCallFragment).commit();
alision85992112013-05-29 12:18:08 -0400289
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000290 slidingPaneLayout.curFragment = mCurrentCallFragment;
291 slidingPaneLayout.openPane();
alision85992112013-05-29 12:18:08 -0400292
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000293 }
alision85992112013-05-29 12:18:08 -0400294
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000295 @Override
296 public void callContact(SipCall call) {
297 try {
298 service.placeCall(call);
299 } catch (RemoteException e) {
300 Log.e(TAG, "Cannot call service method", e);
301 }
alision85992112013-05-29 12:18:08 -0400302
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000303 }
alision85992112013-05-29 12:18:08 -0400304
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000305 @Override
306 public void onCallAccepted(SipCall call) {
307 int callState = call.getCallStateInt();
308 if (callState != state.CALL_STATE_RINGING && callState != state.CALL_STATE_NONE) {
309 return;
310 }
alision85992112013-05-29 12:18:08 -0400311
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000312 try {
313 service.accept(call.getCallId());
314 } catch (RemoteException e) {
315 Log.e(TAG, "Cannot call service method", e);
316 }
alision85992112013-05-29 12:18:08 -0400317
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000318 }
alision85992112013-05-29 12:18:08 -0400319
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000320 @Override
321 public void onCallRejected(SipCall call) {
322 try {
323 if (call.getCallStateInt() == state.CALL_STATE_RINGING) {
324 service.refuse(call.getCallId());
325 return;
326 }
327 } catch (RemoteException e) {
328 Log.e(TAG, "Cannot call service method", e);
329 }
330 }
alision85992112013-05-29 12:18:08 -0400331
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000332 @Override
333 public void onCallEnded(SipCall call) {
334 try {
335 if (call.getCallStateInt() == state.CALL_STATE_NONE || call.getCallStateInt() == state.CALL_STATE_CURRENT
336 || call.getCallStateInt() == state.CALL_STATE_HOLD) {
337 service.hangUp(call.getCallId());
338 return;
alision85992112013-05-29 12:18:08 -0400339
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000340 } else if (call.getCallStateInt() == state.CALL_STATE_RINGING) {
341 if (call.getCallType() == state.CALL_TYPE_INCOMING) {
342 service.refuse(call.getCallId());
343 return;
344 } else if (call.getCallType() == state.CALL_TYPE_OUTGOING) {
345 service.hangUp(call.getCallId());
346 return;
347 }
348 }
349 } catch (RemoteException e) {
350 Log.e(TAG, "Cannot call service method", e);
351 }
352 }
alision85992112013-05-29 12:18:08 -0400353
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000354 @Override
355 public void onCallSuspended(SipCall call) {
356 try {
357 if (call.getCallStateInt() == state.CALL_STATE_CURRENT) {
358 service.hold(call.getCallId());
359 return;
360 }
361 } catch (RemoteException e) {
362 Log.e(TAG, "Cannot call service method", e);
363 }
364 }
alision85992112013-05-29 12:18:08 -0400365
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000366 @Override
367 public void onCallResumed(SipCall call) {
368 try {
369 if (call.getCallStateInt() == state.CALL_STATE_HOLD) {
370 service.unhold(call.getCallId());
371 return;
372 }
373 } catch (RemoteException e) {
374 Log.e(TAG, "Cannot call service method", e);
375 }
alision85992112013-05-29 12:18:08 -0400376
alision85992112013-05-29 12:18:08 -0400377
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000378 }
alision85992112013-05-29 12:18:08 -0400379
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000380 @Override
381 public void onCalltransfered(SipCall call,String to) {
382 try {
383 if (call.getCallStateInt() == state.CALL_STATE_CURRENT) {
384 service.transfer(call.getCallId(), to);
385 }
386 } catch (RemoteException e) {
387 Log.e(TAG, "Cannot call service method", e);
388 }
alision85992112013-05-29 12:18:08 -0400389
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000390 }
alision85992112013-05-29 12:18:08 -0400391
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000392 @Override
393 public void onRecordCall(SipCall call) {
394 try {
395 if (call.getCallStateInt() == state.CALL_STATE_CURRENT) {
396 service.setRecordPath(Environment.getExternalStorageDirectory().getAbsolutePath());
397 Log.w(TAG, "Recording path" + service.getRecordPath());
398 service.setRecordingCall(call.getCallId());
399 }
400 } catch (RemoteException e) {
401 Log.e(TAG, "Cannot call service method", e);
402 }
alision85992112013-05-29 12:18:08 -0400403
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000404 }
alision85992112013-05-29 12:18:08 -0400405
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000406 @Override
407 public void onSendMessage(SipCall call, String msg) {
408 try {
409 if (call.getCallStateInt() == state.CALL_STATE_CURRENT) {
410 service.sendTextMessage(call.getCallId(), msg, "Me");
411 }
412 } catch (RemoteException e) {
413 Log.e(TAG, "Cannot call service method", e);
414 }
alision85992112013-05-29 12:18:08 -0400415
Adrien Béraudc9c424d2013-05-30 17:47:35 +1000416 }
alisiond45da712013-05-30 09:18:49 -0400417
alisiond45da712013-05-30 09:18:49 -0400418
Alexandre Savard14323be2012-10-24 10:02:13 -0400419}