iaxvoiplink.cpp 17.8 KB
Newer Older
yanmorin's avatar
 
yanmorin committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
 *  Copyright (C) 2006 Savoir-Faire Linux inc.
 *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
 *                                                                              
 *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
yanmorin's avatar
   
yanmorin committed
19
#include "iaxvoiplink.h"
yanmorin's avatar
   
yanmorin committed
20
#include "global.h" // for _debug
21
22
#include "iaxcall.h"
#include "eventthread.h"
yanmorin's avatar
   
yanmorin committed
23

yanmorin's avatar
yanmorin committed
24
#include "manager.h"
25
26
#include "audio/audiocodec.h"
#include "audio/audiolayer.h"
yanmorin's avatar
yanmorin committed
27

28
#include <samplerate.h>
29

yanmorin's avatar
   
yanmorin committed
30
31
#define IAX_SUCCESS  0
#define IAX_FAILURE -1
yanmorin's avatar
 
yanmorin committed
32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#define RANDOM_IAX_PORT   rand() % 64000 + 1024

// from IAXC : iaxclient.h

/* payload formats : WARNING: must match libiax values!!! */
/* Data formats for capabilities and frames alike */
#define IAX__FORMAT_G723_1       (1 << 0)        /* G.723.1 compression */
#define IAX__FORMAT_GSM          (1 << 1)        /* GSM compression */
#define IAX__FORMAT_ULAW         (1 << 2)        /* Raw mu-law data (G.711) */
#define IAX__FORMAT_ALAW         (1 << 3)        /* Raw A-law data (G.711) */
#define IAX__FORMAT_G726         (1 << 4)        /* ADPCM, 32kbps  */
#define IAX__FORMAT_ADPCM        (1 << 5)        /* ADPCM IMA */
#define IAX__FORMAT_SLINEAR      (1 << 6)        /* Raw 16-bit Signed Linear (8000 Hz) PCM */
#define IAX__FORMAT_LPC10        (1 << 7)        /* LPC10, 180 samples/frame */
#define IAX__FORMAT_G729A        (1 << 8)        /* G.729a Audio */
#define IAX__FORMAT_SPEEX        (1 << 9)        /* Speex Audio */
#define IAX__FORMAT_ILBC         (1 << 10)       /* iLBC Audio */

#define IAX__FORMAT_MAX_AUDIO    (1 << 15)  /* Maximum audio format */
#define IAX__FORMAT_JPEG         (1 << 16)       /* JPEG Images */
#define IAX__FORMAT_PNG          (1 << 17)       /* PNG Images */
#define IAX__FORMAT_H261         (1 << 18)       /* H.261 Video */
#define IAX__FORMAT_H263         (1 << 19)       /* H.263 Video */
#define IAX__FORMAT_H263_PLUS    (1 << 20)       /* H.263+ Video */
#define IAX__FORMAT_MPEG4        (1 << 21)       /* MPEG4 Video */
#define IAX__FORMAT_H264         (1 << 23)       /* H264 Video */
#define IAX__FORMAT_THEORA       (1 << 24)       /* Theora Video */

61
62
63
#define IAX__20S_8KHZ_MAX   320 // 320 samples
#define IAX__20S_48KHZ_MAX  1920 // 320*6 samples, 6 = 48000/8000

yanmorin's avatar
   
yanmorin committed
64
65
IAXVoIPLink::IAXVoIPLink(const AccountID& accountID)
 : VoIPLink(accountID)
yanmorin's avatar
 
yanmorin committed
66
{
67
  _evThread = new EventThread(this);
68
  _regSession = NULL;
69
70
71

  // to get random number for RANDOM_PORT
  srand (time(NULL));
72

73
74
  audiocodec = NULL;
  audiolayer = NULL;
75
76
77
78
79
80
81
82
83

  _receiveDataDecoded = new int16[IAX__20S_48KHZ_MAX];
  _sendDataEncoded   =  new unsigned char[IAX__20S_8KHZ_MAX];

  // we estimate that the number of format after a conversion 8000->48000 is expanded to 6 times
  _dataAudioLayer = new SFLDataFormat[IAX__20S_48KHZ_MAX];
  _floatBuffer8000  = new float32[IAX__20S_8KHZ_MAX];
  _floatBuffer48000 = new float32[IAX__20S_48KHZ_MAX];
  _intBuffer8000  = new int16[IAX__20S_8KHZ_MAX];
yanmorin's avatar
   
yanmorin committed
84
}
yanmorin's avatar
 
yanmorin committed
85
86


yanmorin's avatar
   
yanmorin committed
87
88
IAXVoIPLink::~IAXVoIPLink()
{
89
90
  delete _evThread; _evThread = NULL;
  _regSession = NULL; // shall not delete it
91
  terminate();
92

93
94
95
96
97
98
  audiocodec = NULL;
  audiolayer = NULL;
  delete [] _intBuffer8000; _intBuffer8000 = NULL;
  delete [] _floatBuffer48000; _floatBuffer48000 = NULL;
  delete [] _floatBuffer8000; _floatBuffer8000 = NULL;
  delete [] _dataAudioLayer; _dataAudioLayer = NULL;
99

100
101
  delete [] _sendDataEncoded; _sendDataEncoded = NULL;
  delete [] _receiveDataDecoded; _receiveDataDecoded = NULL;
yanmorin's avatar
   
yanmorin committed
102
}
yanmorin's avatar
 
yanmorin committed
103

yanmorin's avatar
   
yanmorin committed
104
105
106
107
108
109
bool
IAXVoIPLink::init()
{
  bool returnValue = false;
  //_localAddress = "127.0.0.1";
  // port 0 is default
yanmorin's avatar
   
yanmorin committed
110
  //  iax_enable_debug(); have to enable debug when compiling iax...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  int port = IAX_DEFAULT_PORTNO;
  int last_port = 0;
  int nbTry = 3;

  while (port != IAX_FAILURE && nbTry) {
    last_port = port;
    port = iax_init(port);
    if ( port < 0 ) {
      _debug("IAX Warning: already initialize on port %d\n", last_port);
      port = RANDOM_IAX_PORT;
    } else if (port == IAX_FAILURE) {
      _debug("IAX Fail to start on port %d", last_port);
      port = RANDOM_IAX_PORT;
    } else {
      _debug("IAX Info: listening on port %d\n", last_port);
      _localPort = last_port;
      returnValue = true;

      _evThread->start();
130
131
132
133

      // audio stuff, not dynamic yet
      audiocodec = Manager::instance().getCodecDescriptorMap().getCodec((CodecType)0);
      audiolayer = Manager::instance().getAudioDriver();
134
135
136
137
138
139
      break;
    }
    nbTry--;
  }
  if (port == IAX_FAILURE || nbTry==0) {
    _debug("Fail to initialize iax\n");
yanmorin's avatar
   
yanmorin committed
140
141
142
  }
  return returnValue;
}
yanmorin's avatar
 
yanmorin committed
143

yanmorin's avatar
   
yanmorin committed
144
145
146
147
148
void
IAXVoIPLink::terminate()
{
//  iaxc_shutdown();  
//  hangup all call
149
    terminateIAXCall();
yanmorin's avatar
   
yanmorin committed
150
151
//  iax_hangup(calls[callNo].session,"Dumped Call");
}
152

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
void
IAXVoIPLink::terminateIAXCall()
{
  ost::MutexLock m(_callMapMutex);
  CallMap::iterator iter = _callMap.begin();
  IAXCall *call;
  while( iter != _callMap.end() ) {
    call = dynamic_cast<IAXCall*>(iter->second);
    if (call) {
      _mutexIAX.enterMutex();
      iax_hangup(call->getSession(),"Dumped Call");
      _mutexIAX.leaveMutex();
      call->setSession(0);
      delete call; call = 0;
    }
    iter++;
  }
  _callMap.clear();
}

173
174
175
176
void
IAXVoIPLink::getEvent() 
{
  // mutex here
177
178
  _mutexIAX.enterMutex();

179
180
181
  iax_event* event = NULL;
  IAXCall* call = NULL;
  while ( (event = iax_get_event(TRUE)) != NULL ) {
182
    //_debug ("Receive IAX Event: %d\n", event->etype);
183
    call = iaxFindCallBySession(event->session);
184
    if (call != 0) {
185
      iaxHandleCallEvent(event, call);
yanmorin's avatar
yanmorin committed
186
    } else if (event->session != 0 && event->session == _regSession) {
187
188
      // in iaxclient, there is many session handling, here, only one
      iaxHandleRegReply(event);
yanmorin's avatar
yanmorin committed
189
    } else {
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
      switch(event->etype) {
        case IAX_EVENT_REGACK:
        case IAX_EVENT_REGREJ:
          _debug("Unknown IAX Registration Event\n");
        break;

        case IAX_EVENT_REGREQ:
          _debug("Registration by a peer, don't allow it\n");
        break;
        case IAX_EVENT_CONNECT: // new call
          // New incoming call!	
        break;

        case IAX_EVENT_TIMEOUT: // timeout for an unknown session

        break;

        default:
          _debug("Unknown event type: %d\n", event->etype);
      }
210
    }
yanmorin's avatar
yanmorin committed
211
    iax_event_free(event);
212
  }
yanmorin's avatar
yanmorin committed
213
214
215
216
217
218
219
220
221
222
223
224
225

  // send sound here
  if(_currentCall != 0 && audiolayer != 0) {
    int samples = audiolayer->canGetMic(); 
    if (samples != 0) {
      int  datalen = audiolayer->getMic(_sendDataEncoded, samples);
      _debug("iax_send_voice(%p, %d, ,%d, %d)\n", _currentCall->getSession(), _currentCall->getFormat(), datalen, samples);
      //if ( iax_send_voice(_currentCall->getSession(), _currentCall->getFormat(), (char*)_sendDataEncoded, datalen, samples) == -1) {
      //	   // error sending voice
      //}
    }
  }

yanmorin's avatar
yanmorin committed
226
  // unlock mutex here
227
  _mutexIAX.leaveMutex();
yanmorin's avatar
yanmorin committed
228
229
230
231
  //iaxRefreshRegistrations();

  // thread wait 5 millisecond
  _evThread->sleep(5);
232
233
234
235
236
}

bool
IAXVoIPLink::setRegister() 
{
yanmorin's avatar
yanmorin committed
237
  bool result = false;
238
  if (_regSession == NULL) {
yanmorin's avatar
yanmorin committed
239
240
241
242
243
244
245
246
    if (_host.empty()) {
      Manager::instance().displayConfigError("Fill host field for IAX Account");
      return false;
    }
    if (_user.empty()) {
      Manager::instance().displayConfigError("Fill user field for IAX Account");
      return false;
    }
yanmorin's avatar
yanmorin committed
247

248
249
    // lock
    _mutexIAX.enterMutex();
yanmorin's avatar
yanmorin committed
250
251
252
253
254
255
256
    _regSession = iax_session_new();

    if (!_regSession) {
      _debug("error when generating new session for register");
    } else {
      // refresh
      // last reg
yanmorin's avatar
yanmorin committed
257
258
259
260
261
262
263
264
      char host[_host.length()+1]; 
      strcpy(host, _host.c_str());
      char user[_user.length()+1];
      strcpy(user, _user.c_str());
      char pass[_pass.length()+1]; 
      strcpy(pass, _pass.c_str());
      //iax_register don't use const char*

265
266
267
      _debug("IAX Sending registration to %s with user %s\n", host, user);
      int val = iax_register(_regSession, host, user, pass, 300);
      _debug ("Return value: %d\n", val);
yanmorin's avatar
yanmorin committed
268
      result = true;
yanmorin's avatar
yanmorin committed
269
270
    }

271
    _mutexIAX.leaveMutex();
yanmorin's avatar
yanmorin committed
272
  }
yanmorin's avatar
yanmorin committed
273
  return result;
274
275
276
277
278
}

bool
IAXVoIPLink::setUnregister()
{
279
  if (_regSession == NULL) {
280
281
282
    // lock here
    _mutexIAX.enterMutex();
    iax_destroy(_regSession);
283
    _regSession = NULL;
284
285
286
287
    // unlock here
    _mutexIAX.leaveMutex();
    return false;
  }
288
289
290
  return false;
}

291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
Call* 
IAXVoIPLink::newOutgoingCall(const CallID& id, const std::string& toUrl)
{
  IAXCall* call = new IAXCall(id, Call::Outgoing);
  if (call) {
    call->setPeerNumber(toUrl);
    // we have to add the codec before using it in SIPOutgoingInvite...
    //call->setCodecMap(Manager::instance().getCodecDescriptorMap());
    if ( iaxOutgoingInvite(call) ) {
      call->setConnectionState(Call::Progressing);
      call->setState(Call::Active);
      addCall(call);
    } else {
      delete call; call = 0;
    }
  }
  return call;
}

310
311
312
313
314
315
316
317
318
319
320
321
322
bool 
IAXVoIPLink::answer(const CallID& id) 
{
  IAXCall* call = getIAXCall(id);
  if (call==0) { _debug("Call doesn't exists\n"); return false; }
  _mutexIAX.enterMutex();
  iax_answer(call->getSession());
  _mutexIAX.leaveMutex();
  call->setState(Call::Active);
  call->setConnectionState(Call::Connected);
  return true;
}

yanmorin's avatar
yanmorin committed
323
324
325
326
327
328
329
330
331
bool 
IAXVoIPLink::hangup(const CallID& id)
{
	IAXCall* call = getIAXCall(id);
	if (call==0) { _debug("Call doesn't exists\n"); return false; }

	_mutexIAX.enterMutex();
	iax_hangup(call->getSession(),"Dumped Call");
	_mutexIAX.leaveMutex();
332
	call->setSession(0);
yanmorin's avatar
yanmorin committed
333
334
335
336
337
338
	if (Manager::instance().isCurrentCall(id)) {
	   // stop audio
	}
	removeCall(id);
	return true;	
}
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365

bool 
IAXVoIPLink::onhold(const CallID& id) 
{
  IAXCall* call = getIAXCall(id);
  if (call==0) { _debug("Call doesn't exists\n"); return false; }
  //if (call->getState() == Call::Hold) { _debug("Call is already on hold\n"); return false; }
  _mutexIAX.enterMutex();
  iax_quelch(call->getSession());
  _mutexIAX.leaveMutex();
  call->setState(Call::Hold);
  return true;
}

bool 
IAXVoIPLink::offhold(const CallID& id)
{
  IAXCall* call = getIAXCall(id);
  if (call==0) { _debug("Call doesn't exists\n"); return false; }
  //if (call->getState() == Call::Active) { _debug("Call is already active\n"); return false; }
  _mutexIAX.enterMutex();
  iax_unquelch(call->getSession());
  _mutexIAX.leaveMutex();
  call->setState(Call::Active);
  return true;
}

366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
bool 
IAXVoIPLink::transfer(const CallID& id, const std::string& to)
{
  IAXCall* call = getIAXCall(id);
  if (call==0) { _debug("Call doesn't exists\n"); return false; }

  char callto[to.length()+1];
  strcpy(callto, to.c_str());
  
  _mutexIAX.enterMutex();
  iax_transfer(call->getSession(), callto); 
  _mutexIAX.leaveMutex();

  // should we remove it?
  // removeCall(id);
}

bool 
IAXVoIPLink::refuse(const CallID& id)
{
  IAXCall* call = getIAXCall(id);
  if (call==0) { _debug("Call doesn't exists\n"); return false; }
  _mutexIAX.enterMutex();
  iax_reject(call->getSession(), "Call rejected manually.");
  _mutexIAX.leaveMutex();
  removeCall(id);
}

bool
IAXVoIPLink::carryingDTMFdigits(const CallID& id, char code)
{
  IAXCall* call = getIAXCall(id);
  if (call==0) { _debug("Call doesn't exists\n"); return false; }
  _mutexIAX.enterMutex();
  iax_send_dtmf(call->getSession(), code);
  _mutexIAX.leaveMutex();
}

404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
bool
IAXVoIPLink::iaxOutgoingInvite(IAXCall* call) 
{
  struct iax_session *newsession;
  // lock here
  _mutexIAX.enterMutex();
  newsession = iax_session_new();
  if (!newsession) {
     _debug("IAX Error: Can't make new session for a new call\n");
     // unlock here
     _mutexIAX.leaveMutex();
     return false;
  }
  call->setSession(newsession);
  /* reset activity and ping "timers" */
  // iaxc_note_activity(callNo);
yanmorin's avatar
yanmorin committed
420
  
421
  std::string strNum = _user + ":" + _pass + "@" + _host + "/" + call->getPeerNumber();  
yanmorin's avatar
yanmorin committed
422
423
424
425
426
427

  char user[_user.length()+1];
  strcpy(user, _user.c_str());
  
  char num[strNum.length()+1];
  strcpy(num, strNum.c_str());
428
429
430

  char* lang = NULL;
  int wait = 0;
431
  int audio_format_preferred =  IAX__FORMAT_ULAW;
432
  int audio_format_capability = IAX__FORMAT_ULAW; // | IAX__FORMAT_ALAW | IAX__FORMAT_GSM | IAX__FORMAT_SPEEX;
433

434
  _debug("IAX New call: %s\n", num);
yanmorin's avatar
yanmorin committed
435
  iax_call(newsession, user, user, num, lang, wait, audio_format_preferred, audio_format_capability);
436
437
438
439
440
441
442

  // unlock here
  _mutexIAX.leaveMutex();
  return true;
}


443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
IAXCall* 
IAXVoIPLink::iaxFindCallBySession(struct iax_session* session) 
{
  // access to callMap shoud use that
  // the code below is like findSIPCallWithCid() 
  ost::MutexLock m(_callMapMutex);	
  IAXCall* call = 0;
  CallMap::iterator iter = _callMap.begin();
  while(iter != _callMap.end()) {
    call = dynamic_cast<IAXCall*>(iter->second);
    if (call && call->getSession() == session) {
      return call;
    }
    iter++;
  }
  return 0; // not found
}

void
IAXVoIPLink::iaxHandleCallEvent(iax_event* event, IAXCall* call) 
{
yanmorin's avatar
yanmorin committed
464
465
466
  // call should not be 0
  // note activity?
  //
yanmorin's avatar
yanmorin committed
467
  CallID id = call->getCallId();
468
469
  int16* output = 0; // for audio output

yanmorin's avatar
yanmorin committed
470
  switch(event->etype) {
yanmorin's avatar
yanmorin committed
471
    case IAX_EVENT_HANGUP:
yanmorin's avatar
yanmorin committed
472
473
      Manager::instance().peerHungupCall(id); 
      if (Manager::instance().isCurrentCall(id)) {
yanmorin's avatar
yanmorin committed
474
	    _currentCall = 0;
475
        audiolayer->stopStream();
yanmorin's avatar
yanmorin committed
476
477
478
        // stop audio
      }
      removeCall(id);
yanmorin's avatar
yanmorin committed
479
480
481
    break;

    case IAX_EVENT_REJECT:
yanmorin's avatar
yanmorin committed
482
483
484
      Manager::instance().peerHungupCall(id); 
      if (Manager::instance().isCurrentCall(id)) {
        // stop audio
yanmorin's avatar
yanmorin committed
485
		_currentCall = 0;
486
        audiolayer->stopStream();
yanmorin's avatar
yanmorin committed
487
488
489
      }
      removeCall(id);
     break;
yanmorin's avatar
yanmorin committed
490
491

    case IAX_EVENT_ACCEPT:
yanmorin's avatar
yanmorin committed
492
493
      // accept
      // 
494
      call->setFormat(event->ies.format);
yanmorin's avatar
yanmorin committed
495
    break;
496

yanmorin's avatar
yanmorin committed
497
    case IAX_EVENT_ANSWER:
yanmorin's avatar
yanmorin committed
498
499
500
501
    	if (call->getConnectionState() != Call::Connected){
		call->setConnectionState(Call::Connected);
		call->setState(Call::Active);

502
503
		call->setFormat(event->ies.format);
		
yanmorin's avatar
yanmorin committed
504
		Manager::instance().peerAnsweredCall(id);
yanmorin's avatar
yanmorin committed
505
		_currentCall = call;
506
		audiolayer->startStream();
yanmorin's avatar
yanmorin committed
507
508
509
510
511
		// start audio here?
	} else {
		// deja connecté
		// ?
	}
yanmorin's avatar
yanmorin committed
512
513
514
    break;
    
    case IAX_EVENT_BUSY:
yanmorin's avatar
yanmorin committed
515
516
517
518
519
      call->setConnectionState(Call::Connected);
      call->setState(Call::Busy);
      Manager::instance().displayErrorText(id, "Busy");
      Manager::instance().callBusy(id);
      removeCall(id);
yanmorin's avatar
yanmorin committed
520
521
522
    break;
    
    case IAX_EVENT_VOICE:
523
     if (audiocodec != NULL && audiolayer != NULL) {
524
        //_debug("Receive: len=%d, format=%d, _receiveDataDecoded=%p\n", event->datalen, call->getFormat(), _receiveDataDecoded);
525
526
        unsigned char* data = (unsigned char*)event->data;
        unsigned int size   = event->datalen;
527
528
529
530
531
        if (size > IAX__20S_8KHZ_MAX) {
          _debug("the size %d is bigger than expected %d. crop\n", size, IAX__20S_8KHZ_MAX);
          size = IAX__20S_8KHZ_MAX;
        }
        int expandedSize = audiocodec->codecDecode(_receiveDataDecoded, data, size);
532
        int nbInt16      = expandedSize/sizeof(int16);
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
        if (nbInt16 > IAX__20S_8KHZ_MAX) {
          _debug("We have decoded a IAX packet larger than expected: %s VS %s. crop\n", nbInt16, IAX__20S_8KHZ_MAX);
          nbInt16=IAX__20S_8KHZ_MAX;
        }

        SFLDataFormat* toAudioLayer;
        int nbSample = nbInt16;
        int nbSampleMaxRate = nbInt16 * 6;

        if ( audiolayer->getSampleRate() != audiocodec->getClockRate() ) {
          // convert here
          double         factord = (double)audiolayer->getSampleRate()/ audiocodec->getClockRate();

          SRC_DATA src_data;
          src_data.data_in = _floatBuffer8000;
          src_data.data_out = _floatBuffer48000;
          src_data.input_frames = nbSample;
          src_data.output_frames = nbSampleMaxRate;
          src_data.src_ratio = factord;
          src_short_to_float_array(_receiveDataDecoded, _floatBuffer8000, nbSample);
          src_simple (&src_data, SRC_SINC_BEST_QUALITY/*SRC_SINC_MEDIUM_QUALITY*/, 1); // 1=mono channel
         
          nbSample = ( src_data.output_frames_gen > IAX__20S_48KHZ_MAX) ? IAX__20S_48KHZ_MAX : src_data.output_frames_gen;
          #ifdef DATAFORMAT_IS_FLOAT
            toAudioLayer = _floatBuffer48000;
yanmorin's avatar
yanmorin committed
558
          #else
559
            src_float_to_short_array(_floatBuffer48000, _dataAudioLayer, nbSample);
yanmorin's avatar
yanmorin committed
560
561
            toAudioLayer = _dataAudioLayer;
          #endif
562
563
564
565
  	
        } else {
          nbSample = nbInt16;
          #ifdef DATAFORMAT_IS_FLOAT
yanmorin's avatar
yanmorin committed
566
            // convert _receiveDataDecoded to float inside _receiveData
567
            src_short_to_float_array(_receiveDataDecoded, _floatBuffer8000, nbSample);
yanmorin's avatar
yanmorin committed
568
  	        toAudioLayer = _floatBuffer8000;
569
          #else
yanmorin's avatar
yanmorin committed
570
  	        toAudioLayer = _receiveDataDecoded; // int to int
571
572
573
          #endif
        }
        audiolayer->putMain(toAudioLayer, nbSample * sizeof(SFLDataFormat));
574
      }
yanmorin's avatar
yanmorin committed
575
    break;
576

yanmorin's avatar
yanmorin committed
577
578
    case IAX_EVENT_TEXT:
    break;
579

yanmorin's avatar
yanmorin committed
580
581
    case IAX_EVENT_RINGA:
    break;
582

yanmorin's avatar
yanmorin committed
583
584
585
586
587
588
    case IAX_EVENT_PONG:
    break;
    
    case IAX_EVENT_URL:
    break;
    
yanmorin's avatar
yanmorin committed
589
590
//    case IAX_EVENT_CNG: ??
//    break;
yanmorin's avatar
yanmorin committed
591
592
593
594
595
596
597
598
    
    case IAX_EVENT_TIMEOUT:
    break;
    
    case IAX_EVENT_TRANSFER:
    break;
    
    default:
yanmorin's avatar
yanmorin committed
599
      _debug("Unknown event type: %d\n", event->etype);
yanmorin's avatar
yanmorin committed
600
601
602
603
    
  }
}

604
605


yanmorin's avatar
yanmorin committed
606
607
608
void
IAXVoIPLink::iaxHandleRegReply(iax_event* event) 
{
609
610
611
  //unregister
  if (event->etype == IAX_EVENT_REGREJ) {
    iax_destroy(_regSession);
612
    _regSession = NULL;
613
614
615
616
    Manager::instance().registrationFailed(getAccountID());
  } else if (event->etype == IAX_EVENT_REGACK) {
    Manager::instance().registrationSucceed(getAccountID());
  }
617
}
yanmorin's avatar
yanmorin committed
618
619
620
621
622
623
624
625
626
627

IAXCall* 
IAXVoIPLink::getIAXCall(const CallID& id) 
{
  Call* call = getCall(id);
  if (call) {
    return dynamic_cast<IAXCall*>(call);
  }
  return 0;
}