diff --git a/.gitignore b/.gitignore index 6668eaa3a512bd33f0fe35cd4b2b1ae967acabd8..38beb5d7dae69d41a269a0fed6c93a4e2bab2ff9 100644 --- a/.gitignore +++ b/.gitignore @@ -42,7 +42,8 @@ doc/doxygen/gtk-gui-doc doc/*.html # Ignore built stuff -/src/.libs +.libs +.deps # PJSIP files *.depend diff --git a/daemon/src/audio/alsa/alsalayer.cpp b/daemon/src/audio/alsa/alsalayer.cpp index c3416825413e4947bda9b67b60c4997e85463508..5363ba338f53e30c6933e13dd90068aa1dedb8c9 100644 --- a/daemon/src/audio/alsa/alsalayer.cpp +++ b/daemon/src/audio/alsa/alsalayer.cpp @@ -523,7 +523,7 @@ namespace void AlsaLayer::capture(void) { - unsigned int mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate(); + unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); bool resample = audioSampleRate_ != mainBufferSampleRate; int toGetSamples = snd_pcm_avail_update (captureHandle_); @@ -550,11 +550,11 @@ void AlsaLayer::capture(void) SFLDataFormat* rsmpl_out = (SFLDataFormat*) malloc (outBytes); converter_->resample ( (SFLDataFormat*) in, rsmpl_out, mainBufferSampleRate, audioSampleRate_, toGetSamples); dcblocker_.process(rsmpl_out, rsmpl_out, outSamples); - getMainBuffer()->putData (rsmpl_out, outBytes); + Manager::instance().getMainBuffer()->putData (rsmpl_out, outBytes); free (rsmpl_out); } else { dcblocker_.process(in, in, toGetSamples); - getMainBuffer()->putData (in, toGetBytes); + Manager::instance().getMainBuffer()->putData (in, toGetBytes); } end: @@ -565,10 +565,10 @@ void AlsaLayer::playback(int maxSamples) { unsigned short spkrVolume = Manager::instance().getSpkrVolume(); - unsigned int mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate(); + unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); bool resample = audioSampleRate_ != mainBufferSampleRate; - int toGet = getMainBuffer()->availForGet(); + int toGet = Manager::instance().getMainBuffer()->availForGet(); int toPut = maxSamples * sizeof(SFLDataFormat); if (toGet <= 0) { // no audio available, play tone or silence @@ -602,7 +602,7 @@ void AlsaLayer::playback(int maxSamples) toGet = maxNbBytesToGet; SFLDataFormat *out = (SFLDataFormat*) malloc (toGet); - getMainBuffer()->getData (out, toGet); + Manager::instance().getMainBuffer()->getData (out, toGet); adjustVolume(out, toGet / sizeof(SFLDataFormat), spkrVolume); if (resample) { @@ -644,7 +644,7 @@ void AlsaLayer::audioCallback (void) write (out, toGet, playbackHandle_); free (out); // Consume the regular one as well (same amount of bytes) - getMainBuffer()->discard (toGet); + Manager::instance().getMainBuffer()->discard (toGet); } else { // regular audio data playback(playbackAvailSmpl); diff --git a/daemon/src/audio/audiolayer.cpp b/daemon/src/audio/audiolayer.cpp index 2e440b3c8503c8577600fc178ea038838bbc5310..f568abdd749a68f128c927e6d6b5bf30cf5d5a9b 100644 --- a/daemon/src/audio/audiolayer.cpp +++ b/daemon/src/audio/audiolayer.cpp @@ -56,7 +56,7 @@ void AudioLayer::flushMain (void) { ost::MutexLock guard (mutex_); // should pass call id - getMainBuffer()->flushAllBuffers(); + Manager::instance().getMainBuffer()->flushAllBuffers(); } void AudioLayer::flushUrgent (void) diff --git a/daemon/src/audio/audiolayer.h b/daemon/src/audio/audiolayer.h index 3fb9b1d5b67132bf5bfc19ff5fb1078934a099c3..a3243ee9b0c79765236b36651502d474bb145f45 100644 --- a/daemon/src/audio/audiolayer.h +++ b/daemon/src/audio/audiolayer.h @@ -111,18 +111,6 @@ class AudioLayer return audioSampleRate_; } - /** - * Get a pointer to the application MainBuffer class. - * - * In order to send signal to other parts of the application, one must pass through the mainbuffer. - * Audio instances must be registered into the MainBuffer and bound together via the ManagerImpl. - * - * @return MainBuffer* a pointer to the MainBuffer instance - */ - MainBuffer* getMainBuffer (void) const { - return Manager::instance().getMainBuffer(); - } - /** * Get the mutex lock for the entire audio layer */ diff --git a/daemon/src/audio/pulseaudio/pulselayer.cpp b/daemon/src/audio/pulseaudio/pulselayer.cpp index 60b79e2a68ffbaa879ccf0e8cf17bf5949f3f044..c6b1148dc2be6cb2053e077d1b3435a4b1d38470 100644 --- a/daemon/src/audio/pulseaudio/pulselayer.cpp +++ b/daemon/src/audio/pulseaudio/pulselayer.cpp @@ -434,7 +434,7 @@ void PulseLayer::writeToSpeaker (void) urgentRingBuffer_.Get (data, urgentBytes); pa_stream_write (s, data, urgentBytes, NULL, 0, PA_SEEK_RELATIVE); // Consume the regular one as well (same amount of bytes) - getMainBuffer()->discard (urgentBytes); + Manager::instance().getMainBuffer()->discard (urgentBytes); return; } @@ -450,7 +450,7 @@ void PulseLayer::writeToSpeaker (void) flushUrgent(); // flush remaining samples in _urgentRingBuffer - size_t availSamples = getMainBuffer()->availForGet() / sizeof(SFLDataFormat); + size_t availSamples = Manager::instance().getMainBuffer()->availForGet() / sizeof(SFLDataFormat); if (availSamples == 0) { pa_stream_begin_write(s, &data, &bytes); memset(data, 0, bytes); @@ -458,7 +458,7 @@ void PulseLayer::writeToSpeaker (void) return; } - unsigned int mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate(); + unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); bool resample = audioSampleRate_ != mainBufferSampleRate; // how much samples we can write in the output @@ -479,7 +479,7 @@ void PulseLayer::writeToSpeaker (void) size_t inBytes = inSamples * sizeof (SFLDataFormat); pa_stream_begin_write(s, &data, &inBytes); - getMainBuffer()->getData (data, inBytes); + Manager::instance().getMainBuffer()->getData (data, inBytes); if (resample) { SFLDataFormat* rsmpl_out = (SFLDataFormat*) pa_xmalloc (outBytes); @@ -502,7 +502,7 @@ void PulseLayer::readFromMic (void) return; } - unsigned int mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate(); + unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); bool resample = audioSampleRate_ != mainBufferSampleRate; if (resample) { double resampleFactor = (double) audioSampleRate_ / mainBufferSampleRate; @@ -520,7 +520,7 @@ void PulseLayer::readFromMic (void) converter_->resample((SFLDataFormat*)data, mic_buffer_, mainBufferSampleRate, audioSampleRate_, samples); dcblocker_.process(mic_buffer_, resample ? mic_buffer_ : (SFLDataFormat*)data, samples); - getMainBuffer()->putData(mic_buffer_, bytes); + Manager::instance().getMainBuffer()->putData(mic_buffer_, bytes); if (pa_stream_drop (record_->pulseStream()) < 0) _error ("Audio: Error: capture stream drop failed: %s" , pa_strerror (pa_context_errno (context_))); diff --git a/daemon/src/iax/iaxcall.cpp b/daemon/src/iax/iaxcall.cpp index fa09091f32ce79e6d9dfab091f09e3e983a813dd..e2a8436d724ee68286bb2cb80362d1d7c52563c8 100644 --- a/daemon/src/iax/iaxcall.cpp +++ b/daemon/src/iax/iaxcall.cpp @@ -72,17 +72,10 @@ namespace { } } -IAXCall::IAXCall (const std::string& id, Call::CallType type) : Call (id, type), _session (NULL) +IAXCall::IAXCall (const std::string& id, Call::CallType type) : Call (id, type), session (NULL) { } -void -IAXCall::setFormat (int format) -{ - _format = format; - setAudioCodec(ASTFormatToCodec(format)); -} - int IAXCall::getSupportedFormat (const std::string &accountID) const { @@ -118,7 +111,7 @@ int IAXCall::getFirstMatchingFormat (int needles, const std::string &accountID) return 0; } -int IAXCall::getAudioCodec() +int IAXCall::getAudioCodec(void) { - return _audioCodec; + return ASTFormatToCodec(format); } diff --git a/daemon/src/iax/iaxcall.h b/daemon/src/iax/iaxcall.h index a4579e4d1bc9a752f6735156251908ce976d71ee..64765f97716dc1c95f8a31f527b4dbced43af268 100644 --- a/daemon/src/iax/iaxcall.h +++ b/daemon/src/iax/iaxcall.h @@ -50,38 +50,6 @@ class IAXCall : public Call */ IAXCall (const std::string& id, Call::CallType type); - /** - * @return iax_session* The session pointer or NULL - */ - iax_session* getSession() const { - return _session; - } - - /** - * Set the session pointer - * @param session the session pointer to assign - */ - void setSession (iax_session* session) { - _session = session; - } - - /** - * Set format (one single bit) - * This function sets the _audioCodec variable with the correct - * codec. - * @param format The format representing the codec - */ - void setFormat (int format); - - /** - * Get format for the voice codec used - * @return int Bitmask for codecs defined in iax/frame.h - */ - int getFormat() const { - return _format; - } - - /** * @return int The bitwise list of supported formats */ @@ -102,32 +70,10 @@ class IAXCall : public Call */ int getFirstMatchingFormat (int needles, const std::string &accountID) const; - /** - * Return audio codec [mutex protected] - * @return int The payload of the codec - */ - int getAudioCodec(); - - private: - /** Each call is associated with an iax_session */ - iax_session* _session; + int getAudioCodec(void); - /** - * Set the audio codec used. [not protected] - * @param audioCodec The payload of the codec - */ - void setAudioCodec (int audioCodec) { - _audioCodec = audioCodec; - } - - /** Codec pointer */ - int _audioCodec; - - /** - * Format currently in use in the conversation, - * sent in each outgoing voice packet. - */ - int _format; + int format; + iax_session* session; }; #endif diff --git a/daemon/src/iax/iaxvoiplink.cpp b/daemon/src/iax/iaxvoiplink.cpp index 742ea4b254aae73cbf04450d3df2a17859908709..46827988746b0ce0c360ddc8123fb6d503cb535e 100644 --- a/daemon/src/iax/iaxvoiplink.cpp +++ b/daemon/src/iax/iaxvoiplink.cpp @@ -41,151 +41,89 @@ #include <cmath> #include <dlfcn.h> -#define IAX_BLOCKING 1 -#define IAX_NONBLOCKING 0 - -#define IAX_SUCCESS 0 -#define IAX_FAILURE -1 - -#define RANDOM_IAX_PORT rand() % 64000 + 1024 - -#define MUSIC_ONHOLD true - -#define CHK_VALID_CALL if (call == NULL) { _debug("IAX: Call doesn't exists"); \ - return false; } - -namespace { - const char * const HOOKS = "Hooks"; /** Hooks section */ - const char * const URLHOOK_IAX2_ENABLED = "Hooks.iax2_enabled"; - const char * const URLHOOK_COMMAND = "Hooks.url_command"; -} // end anonymous namespace - IAXVoIPLink::IAXVoIPLink (const std::string& accountID) : evThread_(new EventThread(this)) , regSession_(NULL) , nextRefreshStamp_(0) - , audiolayer_(NULL) - , converterSamplingRate_(0) - , converter_(new SamplerateConverter (44100)) + , converter_(44100) , initDone_(false) , accountID_(accountID) { - // to get random number for RANDOM_PORT - srand(time(NULL)); + srand(time(NULL)); // to get random number for RANDOM_PORT } IAXVoIPLink::~IAXVoIPLink() { - delete converter_; delete evThread_; - regSession_ = NULL; // shall not delete it + regSession_ = NULL; // shall not delete it // XXX: but why? terminate(); } void IAXVoIPLink::init() { - // If it was done, don't do it again, until we call terminate() if (initDone_) return; - 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", 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", last_port); + for (int port = IAX_DEFAULT_PORTNO, nbTry = 0; nbTry < 3 ; port = rand() % 64000 + 1024, nbTry++) { + if (iax_init(port) >= 0) { evThread_->start(); - - audiolayer_ = Manager::instance().getAudioDriver(); - - // may be different than one already setted - converterSamplingRate_ = Manager::instance().getMainBuffer()->getInternalSamplingRate(); - - break; + initDone_ = true; + break; } - - nbTry--; - - initDone_ = true; - } - - if (port == IAX_FAILURE or nbTry == 0) { - _debug ("Fail to initialize iax"); - initDone_ = false; } } void IAXVoIPLink::terminate() { - // If it was done, don't do it again, until we call init() if (!initDone_) return; - // Hangup all calls - terminateIAXCall(); - - initDone_ = false; -} - -void -IAXVoIPLink::terminateIAXCall() -{ ost::MutexLock m(_callMapMutex); for (CallMap::iterator iter = _callMap.begin(); iter != _callMap.end(); ++iter) { IAXCall *call = dynamic_cast<IAXCall*> (iter->second); if (call) { - { - ost::MutexLock m(mutexIAX_); - iax_hangup (call->getSession(), (char*) "Dumped Call"); - } - call->setSession (NULL); + ost::MutexLock m(mutexIAX_); + iax_hangup (call->session, (char*) "Dumped Call"); delete call; } } _callMap.clear(); + + initDone_ = false; } void IAXVoIPLink::getEvent() { - { - ost::MutexLock m(mutexIAX_); - iax_event *event; - while ((event = iax_get_event (IAX_NONBLOCKING)) != NULL) { - // If we received an 'ACK', libiax2 tells apps to ignore them. - if (event->etype == IAX_EVENT_NULL) - continue; - - IAXCall *call = iaxFindCallBySession (event->session); - - if (call) - iaxHandleCallEvent (event, call); - else if (event->session && event->session == regSession_) // This is a registration session, deal with it - iaxHandleRegReply (event); - else // We've got an event before it's associated with any call - iaxHandlePrecallEvent (event); - - iax_event_free (event); - } - free(event); - } + mutexIAX_.enter(); + iax_event *event; + while ((event = iax_get_event(0)) != NULL) { + // If we received an 'ACK', libiax2 tells apps to ignore them. + if (event->etype == IAX_EVENT_NULL) { + iax_event_free (event); + continue; + } + + IAXCall *call = iaxFindCallBySession (event->session); + + if (call) + iaxHandleCallEvent (event, call); + else if (event->session && event->session == regSession_) + iaxHandleRegReply (event); // This is a registration session, deal with it + else // We've got an event before it's associated with any call + iaxHandlePrecallEvent (event); + + iax_event_free (event); + } + mutexIAX_.leave(); + + if (nextRefreshStamp_ && nextRefreshStamp_ < time (NULL)) + sendRegister(dynamic_cast<IAXAccount *> (Manager::instance().getAccount(accountID_))); sendAudioFromMic(); @@ -196,10 +134,6 @@ IAXVoIPLink::getEvent() void IAXVoIPLink::sendAudioFromMic (void) { - // We have to update the audio layer type in case we switched - // TODO Find out a better way to do it - updateAudiolayer(); - for (CallMap::const_iterator iter = _callMap.begin(); iter != _callMap.end() ; ++iter) { IAXCall *currentCall = dynamic_cast<IAXCall*>(iter->second); if (!currentCall or currentCall->getState() != Call::Active) @@ -208,21 +142,21 @@ IAXVoIPLink::sendAudioFromMic (void) int codecType = currentCall->getAudioCodec(); sfl::AudioCodec *audioCodec = static_cast<sfl::AudioCodec *>(Manager::instance().audioCodecFactory.getCodec(codecType)); - if (!audioCodec or !audiolayer_) + if (!audioCodec) continue; Manager::instance().getMainBuffer()->setInternalSamplingRate (audioCodec->getClockRate()); - unsigned int mainBufferSampleRate = audiolayer_->getMainBuffer()->getInternalSamplingRate(); + unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); // we have to get 20ms of data from the mic *20/1000 = /50 // rate/50 shall be lower than IAX__20S_48KHZ_MAX int bytesNeeded = mainBufferSampleRate * 20 / 1000 * sizeof (SFLDataFormat); - if (audiolayer_->getMainBuffer()->availForGet (currentCall->getCallId()) < bytesNeeded) + if (Manager::instance().getMainBuffer()->availForGet (currentCall->getCallId()) < bytesNeeded) continue; // Get bytes from micRingBuffer to data_from_mic - int bytes = audiolayer_->getMainBuffer()->getData (decData, bytesNeeded, currentCall->getCallId()); + int bytes = Manager::instance().getMainBuffer()->getData (decData, bytesNeeded, currentCall->getCallId()); int samples = bytes / sizeof(SFLDataFormat); int compSize; @@ -230,7 +164,7 @@ IAXVoIPLink::sendAudioFromMic (void) int outSamples; SFLDataFormat *in; if (audioRate != mainBufferSampleRate) { - converter_->resample (decData, resampledData, audioRate, mainBufferSampleRate, samples); + converter_.resample (decData, resampledData, audioRate, mainBufferSampleRate, samples); in = resampledData; outSamples = 0; } else { @@ -239,16 +173,11 @@ IAXVoIPLink::sendAudioFromMic (void) } compSize = audioCodec->encode (encodedData, in, DEC_BUFFER_SIZE); - // Send it out! - { - ost::MutexLock m(mutexIAX_); - - // Make sure the session and the call still exists. - if (currentCall->getSession() and (bytes > 0)) { - if (iax_send_voice (currentCall->getSession(), currentCall->getFormat(), encodedData, compSize, outSamples) == -1) - _error ("IAX: Error sending voice data."); - } - } + if (currentCall->session and bytes > 0) { + ost::MutexLock m(mutexIAX_); + if (iax_send_voice (currentCall->session, currentCall->format, encodedData, compSize, outSamples) == -1) + _error ("IAX: Error sending voice data."); + } } } @@ -287,16 +216,15 @@ IAXVoIPLink::sendRegister (Account *a) void IAXVoIPLink::sendUnregister (Account *a) { - ost::MutexLock m(mutexIAX_); if (regSession_) { + ost::MutexLock m(mutexIAX_); iax_destroy (regSession_); regSession_ = NULL; } nextRefreshStamp_ = 0; - IAXAccount *account = dynamic_cast<IAXAccount*>(a); - account->setRegistrationState (Unregistered); + dynamic_cast<IAXAccount*>(a)->setRegistrationState(Unregistered); } Call* @@ -307,14 +235,10 @@ IAXVoIPLink::newOutgoingCall (const std::string& id, const std::string& toUrl) call->setPeerNumber (toUrl); call->initRecFileName (toUrl); - if (iaxOutgoingInvite (call)) { - call->setConnectionState (Call::Progressing); - call->setState (Call::Active); - addCall (call); - } else { - delete call; - call = NULL; - } + iaxOutgoingInvite (call); + call->setConnectionState (Call::Progressing); + call->setState (Call::Active); + addCall (call); return call; } @@ -327,16 +251,14 @@ IAXVoIPLink::answer (Call *c) Manager::instance().addStream (call->getCallId()); - { - ost::MutexLock m(mutexIAX_); - iax_answer(call->getSession()); - } + mutexIAX_.enter(); + iax_answer(call->session); + mutexIAX_.leave(); call->setState(Call::Active); call->setConnectionState(Call::Connected); - // Flush main buffer - audiolayer_->flushMain(); + Manager::instance().getMainBuffer()->flushAllBuffers(); } void @@ -350,11 +272,11 @@ IAXVoIPLink::hangup (const std::string& id) Manager::instance().getMainBuffer()->unBindAll(call->getCallId()); - mutexIAX_.enterMutex(); - iax_hangup (call->getSession(), (char*) "Dumped Call"); - mutexIAX_.leaveMutex(); + mutexIAX_.enter(); + iax_hangup (call->session, (char*) "Dumped Call"); + mutexIAX_.leave(); - call->setSession(NULL); + call->session = NULL; removeCall(id); } @@ -371,7 +293,7 @@ IAXVoIPLink::peerHungup (const std::string& id) Manager::instance().getMainBuffer()->unBindAll (call->getCallId()); - call->setSession (NULL); + call->session = NULL; removeCall (id); } @@ -387,9 +309,9 @@ IAXVoIPLink::onhold (const std::string& id) Manager::instance().getMainBuffer()->unBindAll (call->getCallId()); - mutexIAX_.enterMutex(); - iax_quelch_moh (call->getSession(), MUSIC_ONHOLD); - mutexIAX_.leaveMutex(); + mutexIAX_.enter(); + iax_quelch_moh (call->session, true); + mutexIAX_.leave(); call->setState (Call::Hold); } @@ -403,10 +325,10 @@ IAXVoIPLink::offhold (const std::string& id) Manager::instance().addStream (call->getCallId()); - mutexIAX_.enterMutex(); - iax_unquelch (call->getSession()); - mutexIAX_.leaveMutex(); - audiolayer_->startStream(); + mutexIAX_.enter(); + iax_unquelch (call->session); + mutexIAX_.leave(); + Manager::instance().getAudioDriver()->startStream(); call->setState (Call::Active); } @@ -420,31 +342,28 @@ IAXVoIPLink::transfer (const std::string& id, const std::string& to) char callto[to.length() +1]; strcpy (callto, to.c_str()); - mutexIAX_.enterMutex(); - iax_transfer (call->getSession(), callto); - mutexIAX_.leaveMutex(); + mutexIAX_.enter(); + iax_transfer (call->session, callto); + mutexIAX_.leave(); } bool IAXVoIPLink::attendedTransfer(const std::string& /*transferID*/, const std::string& /*targetID*/) { - // TODO implement attended transfer for IAX - return false; + return false; // TODO } -bool +void IAXVoIPLink::refuse (const std::string& id) { IAXCall* call = getIAXCall (id); - CHK_VALID_CALL; - - mutexIAX_.enterMutex(); - iax_reject (call->getSession(), (char*) "Call rejected manually."); - mutexIAX_.leaveMutex(); - - removeCall (id); + if (call) { + mutexIAX_.enter(); + iax_reject (call->session, (char*) "Call rejected manually."); + mutexIAX_.leave(); - return true; + removeCall (id); + } } @@ -453,9 +372,9 @@ IAXVoIPLink::carryingDTMFdigits (const std::string& id, char code) { IAXCall* call = getIAXCall (id); if (call) { - mutexIAX_.enterMutex(); - iax_send_dtmf (call->getSession(), code); - mutexIAX_.leaveMutex(); + mutexIAX_.enter(); + iax_send_dtmf (call->session, code); + mutexIAX_.leave(); } } @@ -465,12 +384,11 @@ IAXVoIPLink::sendTextMessage (sfl::InstantMessaging *module, const std::string& /*from*/) { IAXCall* call = getIAXCall (callID); - if (!call) - return; - - mutexIAX_.enterMutex(); - module->send_iax_message (call->getSession(), callID, message.c_str()); - mutexIAX_.leaveMutex(); + if (call) { + mutexIAX_.enter(); + module->send_iax_message (call->session, callID, message.c_str()); + mutexIAX_.leave(); + } } @@ -483,19 +401,12 @@ IAXVoIPLink::getCurrentCodecName(Call *c) const } -bool +void IAXVoIPLink::iaxOutgoingInvite (IAXCall* call) { ost::MutexLock m(mutexIAX_); - iax_session *newsession = iax_session_new(); - - if (!newsession) { - _debug ("IAX Error: Can't make new session for a new call"); - return false; - } - - call->setSession(newsession); + call->session = iax_session_new(); IAXAccount *account = dynamic_cast<IAXAccount *>(Manager::instance().getAccount(accountID_)); std::string username(account->getUsername()); @@ -505,46 +416,31 @@ IAXVoIPLink::iaxOutgoingInvite (IAXCall* call) int audio_format_preferred = call->getFirstMatchingFormat(call->getSupportedFormat(accountID_), accountID_); int audio_format_capability = call->getSupportedFormat(accountID_); - _debug ("IAX New call: %s", strNum.c_str()); - iax_call(newsession, username.c_str(), username.c_str(), strNum.c_str(), + iax_call(call->session, username.c_str(), username.c_str(), strNum.c_str(), NULL, 0, audio_format_preferred, audio_format_capability); - - return true; } IAXCall* IAXVoIPLink::iaxFindCallBySession (struct iax_session* session) { - // access to callMap shoud use that - // the code below is like findSIPCallWithCid() ost::MutexLock m(_callMapMutex); for (CallMap::const_iterator iter = _callMap.begin(); iter != _callMap.end(); ++iter) { IAXCall* call = dynamic_cast<IAXCall*> (iter->second); - if (call and call->getSession() == session) + if (call and call->session == session) return call; } - return NULL; // not found + return NULL; } void IAXVoIPLink::iaxHandleCallEvent (iax_event* event, IAXCall* call) { - // call should not be 0 - // note activity? - // std::string id = call->getCallId(); switch (event->etype) { - case IAX_EVENT_HANGUP: - - if (Manager::instance().isCurrentCall (id)) { - // stop audio - // audiolayer->stopStream(); - } - Manager::instance().peerHungupCall (id); removeCall (id); @@ -552,19 +448,14 @@ IAXVoIPLink::iaxHandleCallEvent (iax_event* event, IAXCall* call) case IAX_EVENT_REJECT: call->setConnectionState (Call::Connected); - call->setState (Call::Error); Manager::instance().callFailure (id); removeCall (id); break; case IAX_EVENT_ACCEPT: - // Call accepted over there by the computer, not the user yet. - _debug ("IAX_EVENT_ACCEPT: codec format: %d", event->ies.format); - if (event->ies.format) - call->setFormat (event->ies.format); - + call->format = event->ies.format; break; case IAX_EVENT_ANSWER: @@ -576,19 +467,13 @@ IAXVoIPLink::iaxHandleCallEvent (iax_event* event, IAXCall* call) call->setConnectionState (Call::Connected); call->setState (Call::Active); - // audiolayer->startStream(); - - _debug ("IAX_EVENT_ANSWER: codec format: %d", event->ies.format); - - // Should not get here, should have been set in EVENT_ACCEPT if (event->ies.format) - call->setFormat (event->ies.format); + call->format = event->ies.format; Manager::instance().peerAnsweredCall (id); - // start audio here? - audiolayer_->startStream(); - audiolayer_->flushMain(); + Manager::instance().getAudioDriver()->startStream(); + Manager::instance().getMainBuffer()->flushAllBuffers(); break; @@ -600,9 +485,6 @@ IAXVoIPLink::iaxHandleCallEvent (iax_event* event, IAXCall* call) break; case IAX_EVENT_VOICE: - //if (!audiolayer->isCaptureActive ()) - // audiolayer->startStream (); - // _debug("IAX_EVENT_VOICE: "); iaxHandleVoiceEvent (event, call); break; @@ -622,10 +504,8 @@ IAXVoIPLink::iaxHandleCallEvent (iax_event* event, IAXCall* call) break; case IAX_EVENT_URL: - - if (Manager::instance().getConfigString (HOOKS, URLHOOK_IAX2_ENABLED) == "1") - UrlHook::runAction (Manager::instance().getConfigString (HOOKS, URLHOOK_COMMAND), (char*) event->data); - + if (Manager::instance().getConfigString ("Hooks", "Hooks.iax2_enabled") == "1") + UrlHook::runAction (Manager::instance().getConfigString ("Hooks", "Hooks.url_command"), (char*) event->data); break; } } @@ -639,11 +519,6 @@ IAXVoIPLink::iaxHandleVoiceEvent (iax_event* event, IAXCall* call) if (!event->datalen) return; - if (audiolayer_) { - _debug ("IAX: incoming audio, but no sound card open"); - return; - } - sfl::AudioCodec *audioCodec = static_cast<sfl::AudioCodec *>(Manager::instance().audioCodecFactory.getCodec(call->getAudioCodec())); if (!audioCodec) return; @@ -651,35 +526,27 @@ IAXVoIPLink::iaxHandleVoiceEvent (iax_event* event, IAXCall* call) Manager::instance().getMainBuffer()->setInternalSamplingRate(audioCodec->getClockRate()); unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); - // On-the-fly codec changing (normally, when we receive a full packet) - // as per http://tools.ietf.org/id/draft-guy-iax-03.txt - // - subclass holds the voiceformat property. - - if (event->subclass && event->subclass != call->getFormat()) { - _debug ("iaxHandleVoiceEvent: no format found in call setting it to %i", event->subclass); - call->setFormat (event->subclass); - } + if (event->subclass) + call->format = event->subclass; unsigned char *data = (unsigned char*) event->data; unsigned int size = event->datalen; - // Decode data with relevant codec unsigned int max = audioCodec->getClockRate() * 20 / 1000; - if (size > max) { - _debug ("The size %d is bigger than expected %d. Packet cropped. Ouch!", size, max); + if (size > max) size = max; - } int samples = audioCodec->decode (decData, data , size); int outSize = samples * sizeof(SFLDataFormat); + SFLDataFormat *out = decData; unsigned int audioRate = audioCodec->getClockRate(); if (audioRate != mainBufferSampleRate) { outSize = (double)outSize * (mainBufferSampleRate / audioRate); - converter_->resample (decData, resampledData, mainBufferSampleRate, audioRate, samples); - audiolayer_->getMainBuffer()->putData (resampledData, outSize, call->getCallId()); - } else - audiolayer_->getMainBuffer()->putData (decData, outSize, call->getCallId()); + converter_.resample (decData, resampledData, mainBufferSampleRate, audioRate, samples); + out = resampledData; + } + Manager::instance().getMainBuffer()->putData (out, outSize, call->getCallId()); } /** @@ -689,150 +556,69 @@ void IAXVoIPLink::iaxHandleRegReply (iax_event* event) { IAXAccount *account = dynamic_cast<IAXAccount *>(Manager::instance().getAccount(accountID_)); + if (event->etype != IAX_EVENT_REGREJ && event->etype != IAX_EVENT_REGACK) + return; - if (event->etype == IAX_EVENT_REGREJ) { - /* Authentication failed! */ - { - ost::MutexLock m(mutexIAX_); - iax_destroy(regSession_); - } - regSession_ = NULL; - // Update the account registration state - account->setRegistrationState (ErrorAuth); - } + ost::MutexLock m(mutexIAX_); + iax_destroy(regSession_); + regSession_ = NULL; - else if (event->etype == IAX_EVENT_REGACK) { - /* Authentication succeeded */ - { - ost::MutexLock m(mutexIAX_); - iax_destroy (regSession_); - } - regSession_ = NULL; + account->setRegistrationState((event->etype == IAX_EVENT_REGREJ) ? ErrorAuth : Registered); - // I mean, save the timestamp, so that we re-register again in the REFRESH time. - // Defaults to 60, as per draft-guy-iax-03. + if (event->etype == IAX_EVENT_REGACK) nextRefreshStamp_ = time (NULL) + (event->ies.refresh ? event->ies.refresh : 60); - account->setRegistrationState (Registered); - } } -int IAXVoIPLink::processIAXMsgCount (int msgcount) -{ - // IAX sends the message count under a specific format: - // 1 - // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // | 0x18 | 0x02 | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // | Old messages | New messages | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - // For now we just need the new messages informations. - // Thus: - // 0 <= msgcount <= 255 => msgcount new messages, 0 old messages - // msgcount >= 256 => msgcount/256 old messages , msgcount%256 new messages (RULES) - - return msgcount % 256; -} - - void IAXVoIPLink::iaxHandlePrecallEvent (iax_event* event) { - IAXCall* call = NULL; + IAXCall *call; std::string id; + int format; switch (event->etype) { - case IAX_EVENT_REGACK: - - case IAX_EVENT_REGREJ: - _debug ("IAX Registration Event in a pre-call setup"); - break; - - case IAX_EVENT_REGREQ: - // Received when someone wants to register to us!?! - // Asterisk receives and answers to that, not us, we're a phone. - _debug ("Registration by a peer, don't allow it"); - break; - case IAX_EVENT_CONNECT: - // We've got an incoming call! Yikes! - _debug ("> IAX_EVENT_CONNECT (receive)"); - id = Manager::instance().getNewCallID(); call = new IAXCall (id, Call::Incoming); - - // Setup the new IAXCall - // Associate the call to the session. - call->setSession (event->session); - + call->session = event->session; call->setConnectionState (Call::Progressing); - if (event->ies.calling_number) - call->setPeerNumber (std::string (event->ies.calling_number)); + call->setPeerNumber(event->ies.calling_number); if (event->ies.calling_name) call->setPeerName (std::string (event->ies.calling_name)); // if peerNumber exist append it to the name string call->initRecFileName (std::string (event->ies.calling_number)); + Manager::instance().incomingCall(call, accountID_); - if (Manager::instance().incomingCall (call, accountID_)) { - /** @todo Faudra considérer éventuellement le champ CODEC PREFS pour - * l'établissement du codec de transmission */ - - // Remote lists its capabilities - int format = call->getFirstMatchingFormat (event->ies.capability, accountID_); - // Remote asks for preferred codec voiceformat - int pref_format = call->getFirstMatchingFormat (event->ies.format, accountID_); - - // Priority to remote's suggestion. In case it's a forwarding, no transcoding - // will be needed from the server, thus less latency. - - if (pref_format) - format = pref_format; - - iax_accept (event->session, format); - - iax_ring_announce (event->session); + format = call->getFirstMatchingFormat (event->ies.format, accountID_); + if (!format) + format = call->getFirstMatchingFormat (event->ies.capability, accountID_); - addCall (call); - - // Set the audio codec now, to avoid non-set codec problem later - call->setFormat (format); - - } else { - // reject call, unable to add it - iax_reject (event->session, (char*) "Error ringing user."); - delete call; - } + iax_accept (event->session, format); + iax_ring_announce (event->session); + addCall (call); + call->format = format; break; case IAX_EVENT_HANGUP: - // Remote peer hung up - call = iaxFindCallBySession (event->session); - id = call->getCallId(); - _debug ("IAXVoIPLink::hungup::iaxHandlePrecallEvent"); + id = iaxFindCallBySession(event->session)->getCallId(); Manager::instance().peerHungupCall (id); removeCall (id); break; case IAX_EVENT_TIMEOUT: // timeout for an unknown session - break; - case IAX_IE_MSGCOUNT: - break; - + case IAX_EVENT_REGACK: + case IAX_EVENT_REGREJ: + case IAX_EVENT_REGREQ: + // Received when someone wants to register to us!?! + // Asterisk receives and answers to that, not us, we're a phone. default: - _debug ("IAXVoIPLink::iaxHandlePrecallEvent: Unknown event type (in precall): %d", event->etype); + break; } } - -void IAXVoIPLink::updateAudiolayer (void) -{ - ost::MutexLock m(mutexIAX_); - audiolayer_ = Manager::instance().getAudioDriver(); -} diff --git a/daemon/src/iax/iaxvoiplink.h b/daemon/src/iax/iaxvoiplink.h index ed8757dc17f2f1f8602aa8842001f13695ce5462..5dab2f2dcfdd0a72019a9f9c5cb2fb20c16cb4e7 100644 --- a/daemon/src/iax/iaxvoiplink.h +++ b/daemon/src/iax/iaxvoiplink.h @@ -36,12 +36,12 @@ #include <iax-client.h> #include "audio/codecs/audiocodec.h" // for DEC_BUFFER_SIZE #include "global.h" +#include "audio/samplerateconverter.h" namespace sfl { class InstantMessaging; } -class SamplerateConverter; class EventThread; class IAXCall; @@ -164,10 +164,8 @@ class IAXVoIPLink : public VoIPLink /** * Refuse a call * @param id The ID of the call - * @return bool true on success - * false otherwise */ - virtual bool refuse (const std::string& id); + virtual void refuse (const std::string& id); /** * Send DTMF @@ -185,11 +183,6 @@ class IAXVoIPLink : public VoIPLink */ virtual std::string getCurrentCodecName(Call *c) const; - - public: // iaxvoiplink only - - void updateAudiolayer (void); - private: /* * Decode the message count IAX send. @@ -208,11 +201,6 @@ class IAXVoIPLink : public VoIPLink */ IAXCall* getIAXCall (const std::string& id); - /** - * Delete every call - */ - void terminateIAXCall(); - /** * Find a iaxcall by iax session number * @param session an iax_session valid pointer @@ -255,7 +243,7 @@ class IAXVoIPLink : public VoIPLink * Send an outgoing call invite to iax * @param call An IAXCall pointer */ - bool iaxOutgoingInvite (IAXCall* call); + void iaxOutgoingInvite (IAXCall* call); /** Threading object */ EventThread* evThread_; @@ -272,17 +260,13 @@ class IAXVoIPLink : public VoIPLink * iax_stuff inside this class. */ ost::Mutex mutexIAX_; - /** Connection to audio card/device */ - AudioLayer* audiolayer_; - /** encoder/decoder/resampler buffers */ SFLDataFormat decData[DEC_BUFFER_SIZE]; SFLDataFormat resampledData[DEC_BUFFER_SIZE]; unsigned char encodedData[DEC_BUFFER_SIZE]; - int converterSamplingRate_; /** Sample rate converter object */ - SamplerateConverter* converter_; + SamplerateConverter converter_; /** Whether init() was called already or not * This should be used in init() and terminate(), to diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp index 1724cba6b26af62fd42764aab36fbe67a3789afb..222da33d093082b4f02ccff21cd220aff3b378e6 100644 --- a/daemon/src/managerimpl.cpp +++ b/daemon/src/managerimpl.cpp @@ -585,10 +585,8 @@ bool ManagerImpl::attendedTransfer(const std::string& transferID, const std::str } //THREAD=Main : Call:Incoming -bool ManagerImpl::refuseCall (const std::string& id) +void ManagerImpl::refuseCall (const std::string& id) { - bool returnValue; - stopTone(); if (getCallList().size() <= 1) { @@ -600,31 +598,25 @@ bool ManagerImpl::refuseCall (const std::string& id) /* Direct IP to IP call */ if (getConfigFromCall (id) == Call::IPtoIP) - returnValue = SIPVoIPLink::instance ()-> refuse (id); + SIPVoIPLink::instance()->refuse (id); else { /* Classic call, attached to an account */ std::string accountid = getAccountFromCall (id); if (accountid.empty()) - return false; + return; - returnValue = getAccountLink (accountid)->refuse (id); + getAccountLink(accountid)->refuse(id); removeCallAccount (id); } - // if the call was outgoing or established, we didn't refuse it - // so the method did nothing - if (returnValue) { - removeWaitingCall (id); - _dbus.getCallManager()->callStateChanged (id, "HUNGUP"); - } + removeWaitingCall(id); + _dbus.getCallManager()->callStateChanged(id, "HUNGUP"); // Disconnect streams removeStream(id); getMainBuffer()->stateInfo(); - - return returnValue; } Conference* @@ -1361,8 +1353,6 @@ bool ManagerImpl::incomingCallWaiting () void ManagerImpl::addWaitingCall (const std::string& id) { - _info ("Manager: Add waiting call %s (%d calls)", id.c_str(), _nbIncomingWaitingCall); - ost::MutexLock m(_waitingCallMutex); _waitingCall.insert (id); _nbIncomingWaitingCall++; @@ -1370,12 +1360,8 @@ void ManagerImpl::addWaitingCall (const std::string& id) void ManagerImpl::removeWaitingCall (const std::string& id) { - _info ("Manager: Remove waiting call %s (%d calls)", id.c_str(), _nbIncomingWaitingCall); - ost::MutexLock m(_waitingCallMutex); - // should return more than 1 if it erase a call - - if (_waitingCall.erase (id)) + if (_waitingCall.erase(id)) _nbIncomingWaitingCall--; } @@ -1388,17 +1374,14 @@ bool ManagerImpl::isWaitingCall (const std::string& id) // Management of event peer IP-phone //////////////////////////////////////////////////////////////////////////////// // SipEvent Thread -bool ManagerImpl::incomingCall (Call* call, const std::string& accountId) +void ManagerImpl::incomingCall (Call* call, const std::string& accountId) { assert(call); stopTone(); - _debug ("Manager: Incoming call %s for account %s", call->getCallId().data(), accountId.c_str()); - associateCallToAccount (call->getCallId(), accountId); - // If account is null it is an ip to ip call - if (accountId.empty()) + if (accountId == "") associateConfigToCall (call->getCallId(), Call::IPtoIP); else { // strip sip: which is not required and bring confusion with ip to ip calls @@ -1407,45 +1390,26 @@ bool ManagerImpl::incomingCall (Call* call, const std::string& accountId) size_t startIndex = peerNumber.find ("sip:"); - if (startIndex != std::string::npos) { - std::string strippedPeerNumber = peerNumber.substr (startIndex + 4); - call->setPeerNumber (strippedPeerNumber); - } + if (startIndex != std::string::npos) + call->setPeerNumber (peerNumber.substr (startIndex + 4)); } if (!hasCurrentCall()) { - _debug ("Manager: Has no current call start ringing"); call->setConnectionState (Call::Ringing); ringtone (accountId); - - } else - _debug ("Manager: has current call, beep in current audio stream"); + } addWaitingCall (call->getCallId()); std::string from(call->getPeerName()); std::string number(call->getPeerNumber()); - std::string display_name(call->getDisplayName()); - if (not from.empty() and not number.empty()) { - from.append (" <"); - from.append (number); - from.append (">"); - } else if (from.empty()) { - from.append ("<"); - from.append (number); - from.append (">"); - } - - /* Broadcast a signal over DBus */ - _debug ("Manager: From: %s, Number: %s, Display Name: %s", from.c_str(), number.c_str(), display_name.c_str()); + if (not from.empty() and not number.empty()) + from += " "; - std::string display(display_name); - display.append(" "); - display.append(from); + from += "<" + number + ">"; - _dbus.getCallManager()->incomingCall(accountId, call->getCallId(), display); - return true; + _dbus.getCallManager()->incomingCall(accountId, call->getCallId(), call->getDisplayName() + " " + from); } diff --git a/daemon/src/managerimpl.h b/daemon/src/managerimpl.h index 616def92beddd00191c4882e52dcf60b41bca0bb..024ec8992d91b70d2db5698e65421c8613796a47 100644 --- a/daemon/src/managerimpl.h +++ b/daemon/src/managerimpl.h @@ -231,7 +231,7 @@ class ManagerImpl * Refuse the call * @param id The call identifier */ - bool refuseCall (const std::string& id); + void refuseCall (const std::string& id); /** * Create a new conference given two participant @@ -365,9 +365,8 @@ class ManagerImpl * and notify user * @param call A call pointer * @param accountId an account id - * @return bool True if the call was added correctly */ - bool incomingCall (Call* call, const std::string& accountId); + void incomingCall (Call* call, const std::string& accountId); /** * Notify the user that the recipient of the call has answered and the put the diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index 53594c6a6258e2235e8e2cc05ee28c31dcbdc1b9..decbbf4474160f9864ba3c246f4b9fc404b9fa66 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -667,28 +667,26 @@ bool SIPVoIPLink::attendedTransfer(const std::string& id, const std::string& to) return transferCommon(getSIPCall(id), &dst); } -bool +void SIPVoIPLink::refuse (const std::string& id) { SIPCall *call = getSIPCall (id); if (!call->isIncoming() or call->getConnectionState() == Call::Connected) - return false; + return; call->getAudioRtp()->stop(); pjsip_tx_data *tdata; if (pjsip_inv_end_session (call->inv, PJSIP_SC_DECLINE, NULL, &tdata) != PJ_SUCCESS) - return false; + return; if (pjsip_inv_send_msg (call->inv, tdata) != PJ_SUCCESS) - return false; + return; // Make sure the pointer is NULL in callbacks call->inv->mod_data[_mod_ua.id] = NULL; removeCall (id); - - return true; } std::string @@ -1730,8 +1728,12 @@ static pj_bool_t transaction_request_cb (pjsip_rx_data *rdata) call->getAudioRtp()->start (static_cast<sfl::AudioCodec *>(audiocodec)); pjsip_dialog* dialog; - if (pjsip_dlg_create_uas (pjsip_ua_instance(), rdata, NULL, &dialog) != PJ_SUCCESS) - goto fail; + if (pjsip_dlg_create_uas (pjsip_ua_instance(), rdata, NULL, &dialog) != PJ_SUCCESS) { + delete call; + pjsip_endpt_respond_stateless (_endpt, rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, NULL, NULL, NULL); + return false; + + } pjsip_inv_create_uas (dialog, rdata, call->getLocalSDP()->getLocalSdpSession(), 0, &call->inv); @@ -1767,18 +1769,11 @@ static pj_bool_t transaction_request_cb (pjsip_rx_data *rdata) call->setConnectionState (Call::Ringing); - if (!Manager::instance().incomingCall (call, account_id)) - goto fail; - + Manager::instance().incomingCall (call, account_id); Manager::instance().getAccountLink (account_id)->addCall (call); } return true; - -fail: - delete call; - pjsip_endpt_respond_stateless (_endpt, rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, NULL, NULL, NULL); - return false; } static pj_bool_t transaction_response_cb (pjsip_rx_data *rdata) diff --git a/daemon/src/sip/sipvoiplink.h b/daemon/src/sip/sipvoiplink.h index 4d50d830ef710a287c78e422f17fc84bee65e9a5..edaa5e2fb9fc799e2172922be89650451d83fbb4 100644 --- a/daemon/src/sip/sipvoiplink.h +++ b/daemon/src/sip/sipvoiplink.h @@ -164,9 +164,8 @@ class SIPVoIPLink : public VoIPLink /** * Refuse the call * @param id The call identifier - * @return bool True on success */ - virtual bool refuse (const std::string& id); + virtual void refuse (const std::string& id); /** * Send DTMF refering to account configuration diff --git a/daemon/src/voiplink.h b/daemon/src/voiplink.h index 35f7a368e02da17fce3f82a94201e25d88065c0d..0936e3c4630edf4ae044d649f3731b87ef00a57a 100644 --- a/daemon/src/voiplink.h +++ b/daemon/src/voiplink.h @@ -148,9 +148,8 @@ class VoIPLink /** * Refuse incoming call * @param id The call identifier - * @return bool True on success */ - virtual bool refuse (const std::string& id) = 0; + virtual void refuse (const std::string& id) = 0; /** * Send DTMF