diff --git a/config.ini b/config.ini index 4b5336e913197de68b58844e3a84f18486e63012..2bb223f4c51b63ad0172f8bbb500aef3a4c06895 100644 --- a/config.ini +++ b/config.ini @@ -9,7 +9,7 @@ name = libringclient submodule = network folder = libringclient kde_release = no -version = 0.1.0 +version = 0.2.0 docs = yes translations = yes gitModule = yes diff --git a/src/call.cpp b/src/call.cpp index d0879d308ea2873b771aa9f1756e6805c9a9275d..862c651caaadcbd67540235886b659934a1ae428 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -72,6 +72,7 @@ const TypedStateMachine< TypedStateMachine< Call::State , Call::Action> , Call::State> CallPrivate::actionPerformedStateMap = {{ // ACCEPT REFUSE TRANSFER HOLD RECORD /**/ +/*NEW */ {{Call::State::DIALING , Call::State::ABORTED , Call::State::ERROR , Call::State::ERROR , Call::State::ERROR }},/**/ /*INCOMING */ {{Call::State::INCOMING , Call::State::INCOMING , Call::State::ERROR , Call::State::INCOMING , Call::State::INCOMING }},/**/ /*RINGING */ {{Call::State::ERROR , Call::State::RINGING , Call::State::ERROR , Call::State::ERROR , Call::State::RINGING }},/**/ /*CURRENT */ {{Call::State::ERROR , Call::State::CURRENT , Call::State::TRANSFERRED , Call::State::CURRENT , Call::State::CURRENT }},/**/ @@ -86,16 +87,18 @@ const TypedStateMachine< TypedStateMachine< Call::State , Call::Action> , Call:: /*CONF */ {{Call::State::ERROR , Call::State::CURRENT , Call::State::TRANSFERRED , Call::State::CURRENT , Call::State::CURRENT }},/**/ /*CONF_HOLD */ {{Call::State::ERROR , Call::State::HOLD , Call::State::TRANSF_HOLD , Call::State::HOLD , Call::State::HOLD }},/**/ /*INIT */ {{Call::State::INITIALIZATION, Call::State::OVER , Call::State::ERROR , Call::State::ERROR , Call::State::ERROR }},/**/ +/*ABORTED */ {{Call::State::ERROR , Call::State::ERROR , Call::State::ERROR , Call::State::ERROR , Call::State::ERROR }},/**/ }};// */ #define CP &CallPrivate const TypedStateMachine< TypedStateMachine< function , Call::Action > , Call::State > CallPrivate::actionPerformedFunctionMap = {{ // ACCEPT REFUSE TRANSFER HOLD RECORD /**/ +/*NEW */ {{CP::nothing , CP::abort , CP::nothing , CP::nothing , CP::nothing }},/**/ /*INCOMING */ {{CP::accept , CP::refuse , CP::acceptTransf , CP::acceptHold , CP::toggleRecord }},/**/ /*RINGING */ {{CP::nothing , CP::hangUp , CP::nothing , CP::nothing , CP::toggleRecord }},/**/ /*CURRENT */ {{CP::nothing , CP::hangUp , CP::nothing , CP::hold , CP::toggleRecord }},/**/ -/*DIALING */ {{CP::call , CP::cancel , CP::nothing , CP::nothing , CP::nothing }},/**/ +/*DIALING */ {{CP::call , CP::abort , CP::nothing , CP::nothing , CP::nothing }},/**/ /*HOLD */ {{CP::nothing , CP::hangUp , CP::nothing , CP::unhold , CP::toggleRecord }},/**/ /*FAILURE */ {{CP::nothing , CP::remove , CP::nothing , CP::nothing , CP::nothing }},/**/ /*BUSY */ {{CP::nothing , CP::hangUp , CP::nothing , CP::nothing , CP::nothing }},/**/ @@ -106,12 +109,14 @@ const TypedStateMachine< TypedStateMachine< function , Call::Action > , Call::St /*CONF */ {{CP::nothing , CP::hangUp , CP::nothing , CP::hold , CP::toggleRecord }},/**/ /*CONF_HOLD */ {{CP::nothing , CP::hangUp , CP::nothing , CP::unhold , CP::toggleRecord }},/**/ /*INITIALIZATION */ {{CP::call , CP::cancel , CP::nothing , CP::nothing , CP::nothing }},/**/ +/*ABORTED */ {{CP::call , CP::cancel , CP::nothing , CP::nothing , CP::nothing }},/**/ }};// */ const TypedStateMachine< TypedStateMachine< Call::State , CallPrivate::DaemonState> , Call::State> CallPrivate::stateChangedStateMap = {{ // RINGING CURRENT BUSY HOLD HUNGUP FAILURE /**/ +/*NEW */ {{Call::State::ERROR , Call::State::ERROR , Call::State::ERROR , Call::State::ERROR , Call::State::ERROR , Call::State::ERROR }},/**/ /*INCOMING */ {{Call::State::INCOMING , Call::State::CURRENT , Call::State::BUSY , Call::State::HOLD , Call::State::OVER , Call::State::FAILURE }},/**/ /*RINGING */ {{Call::State::RINGING , Call::State::CURRENT , Call::State::BUSY , Call::State::HOLD , Call::State::OVER , Call::State::FAILURE }},/**/ /*CURRENT */ {{Call::State::CURRENT , Call::State::CURRENT , Call::State::BUSY , Call::State::HOLD , Call::State::OVER , Call::State::FAILURE }},/**/ @@ -126,11 +131,13 @@ const TypedStateMachine< TypedStateMachine< Call::State , CallPrivate::DaemonSta /*CONF */ {{Call::State::CURRENT , Call::State::CURRENT , Call::State::BUSY , Call::State::HOLD , Call::State::OVER , Call::State::FAILURE }},/**/ /*CONF_HOLD */ {{Call::State::HOLD , Call::State::CURRENT , Call::State::BUSY , Call::State::HOLD , Call::State::OVER , Call::State::FAILURE }},/**/ /*INIT */ {{Call::State::RINGING , Call::State::CURRENT , Call::State::BUSY , Call::State::HOLD , Call::State::OVER , Call::State::FAILURE }},/**/ +/*ABORTED */ {{Call::State::ERROR , Call::State::ERROR , Call::State::ERROR , Call::State::ERROR , Call::State::ERROR , Call::State::ERROR }},/**/ }};// */ const TypedStateMachine< TypedStateMachine< function , CallPrivate::DaemonState > , Call::State > CallPrivate::stateChangedFunctionMap = {{ -// RINGING CURRENT BUSY HOLD HUNGUP FAILURE /**/ +// RINGING CURRENT BUSY HOLD HUNGUP FAILURE /**/ +/*NEW */ {{CP::nothing , CP::nothing , CP::nothing , CP::nothing , CP::nothing , CP::nothing }},/**/ /*INCOMING */ {{CP::nothing , CP::start , CP::startWeird , CP::startWeird , CP::startStop , CP::failure }},/**/ /*RINGING */ {{CP::nothing , CP::start , CP::start , CP::start , CP::startStop , CP::failure }},/**/ /*CURRENT */ {{CP::nothing , CP::nothing , CP::warning , CP::nothing , CP::stop , CP::nothing }},/**/ @@ -145,16 +152,18 @@ const TypedStateMachine< TypedStateMachine< function , CallPrivate::DaemonState /*CONF */ {{CP::nothing , CP::nothing , CP::warning , CP::nothing , CP::stop , CP::nothing }},/**/ /*CONF_HOLD */ {{CP::nothing , CP::nothing , CP::warning , CP::nothing , CP::stop , CP::nothing }},/**/ /*INIT */ {{CP::nothing , CP::warning , CP::warning , CP::warning , CP::stop , CP::warning }},/**/ +/*ABORTED */ {{CP::error , CP::error , CP::error , CP::error , CP::error , CP::error }},/**/ }};// */ #undef CP const TypedStateMachine< Call::LifeCycleState , Call::State > CallPrivate::metaStateMap = {{ /* * Life cycle meta-state **/ +/*NEW */ Call::LifeCycleState::CREATION ,/**/ /*INCOMING */ Call::LifeCycleState::INITIALIZATION ,/**/ /*RINGING */ Call::LifeCycleState::INITIALIZATION ,/**/ /*CURRENT */ Call::LifeCycleState::PROGRESS ,/**/ -/*DIALING */ Call::LifeCycleState::INITIALIZATION ,/**/ +/*DIALING */ Call::LifeCycleState::CREATION ,/**/ /*HOLD */ Call::LifeCycleState::PROGRESS ,/**/ /*FAILURE */ Call::LifeCycleState::FINISHED ,/**/ /*BUSY */ Call::LifeCycleState::FINISHED ,/**/ @@ -165,25 +174,28 @@ const TypedStateMachine< Call::LifeCycleState , Call::State > CallPrivate::metaS /*CONF */ Call::LifeCycleState::PROGRESS ,/**/ /*CONF_HOLD */ Call::LifeCycleState::PROGRESS ,/**/ /*INIT */ Call::LifeCycleState::INITIALIZATION ,/**/ +/*ABORTED */ Call::LifeCycleState::FINISHED ,/**/ }};/* **/ const TypedStateMachine< TypedStateMachine< bool , Call::LifeCycleState > , Call::State > CallPrivate::metaStateTransitionValidationMap = {{ -/* * INITIALIZATION PROGRESS FINISHED **/ -/*INCOMING */ {{ true , false , false }},/**/ -/*RINGING */ {{ true , false , false }},/**/ -/*CURRENT */ {{ true , true , false }},/**/ -/*DIALING */ {{ true , false , false }},/**/ -/*HOLD */ {{ true , true , false }},/**/ -/*FAILURE */ {{ true , true , false }},/**/ -/*BUSY */ {{ true , false , false }},/**/ -/*TRANSFERT */ {{ false , true , false }},/**/ -/*TRANSFERT_HOLD */ {{ false , true , false }},/**/ -/*OVER */ {{ true , true , true }},/**/ -/*ERROR */ {{ true , true , false }},/**/ -/*CONF */ {{ true , false , false }},/**/ -/*CONF_HOLD */ {{ true , false , false }},/**/ -/*INIT */ {{ true , false , false }},/**/ +/* * CREATION INITIALIZATION PROGRESS FINISHED **/ +/*NEW */ {{ true , true , false , false }},/**/ +/*INCOMING */ {{ false , true , false , false }},/**/ +/*RINGING */ {{ true , true , false , false }},/**/ +/*CURRENT */ {{ false , true , true , false }},/**/ +/*DIALING */ {{ true , true , false , false }},/**/ +/*HOLD */ {{ false , true , true , false }},/**/ +/*FAILURE */ {{ false , true , true , false }},/**/ +/*BUSY */ {{ false , true , false , false }},/**/ +/*TRANSFERT */ {{ false , false , true , false }},/**/ +/*TRANSFERT_HOLD */ {{ false , false , true , false }},/**/ +/*OVER */ {{ false , true , true , true }},/**/ +/*ERROR */ {{ true , true , true , false }},/**/ +/*CONF */ {{ false , true , false , false }},/**/ +/*CONF_HOLD */ {{ false , true , false , false }},/**/ +/*INIT */ {{ true , true , false , false }},/**/ +/*ABORTED */ {{ true , true , false , false }},/**/ }};/* **/ /*^^ A call _can_ be created on hold (conference) and as over (peer hang up before pickup) the progress->failure one is an implementation bug*/ @@ -249,8 +261,6 @@ Call::Call(Call::State startState, const QString& peerName, ContactMethod* numbe d_ptr->m_PeerName = peerName; d_ptr->m_pPeerContactMethod = number; - d_ptr->changeCurrentState(startState); - emit changed(); emit changed(this); } @@ -274,7 +284,7 @@ Call::Call(const QString& confId, const QString& account) CallManagerInterface& callManager = DBus::CallManager::instance(); MapStringString details = callManager.getConferenceDetails(dringId()) ; d_ptr->m_CurrentState = d_ptr->confStatetoCallState(details[CallPrivate::ConfDetailsMapFields::CONF_STATE]); - emit stateChanged(); + emit stateChanged(state(),Call::State::NEW); } } @@ -341,7 +351,7 @@ Call* CallPrivate::buildExistingCall(const QString& callId) ///Build a call from a dialing call (a call that is about to exist) Call* CallPrivate::buildDialingCall(const QString & peerName, Account* account) { - Call* call = new Call(Call::State::DIALING, peerName, nullptr, account); + Call* call = new Call(Call::State::NEW, peerName, nullptr, account); call->d_ptr->m_Direction = Call::Direction::OUTGOING; if (Audio::Settings::instance()->isRoomToneEnabled()) { Audio::Settings::instance()->playRoomTone(); @@ -560,6 +570,9 @@ Call::State CallPrivate::confStatetoCallState(const QString& stateName) const QString Call::toHumanStateName(const Call::State cur) { switch (cur) { + case Call::State::NEW: + return tr( "New" ); + break; case Call::State::INCOMING: return tr( "Ringing (in)" ); break; @@ -602,6 +615,8 @@ const QString Call::toHumanStateName(const Call::State cur) return tr( "ERROR" ); case Call::State::INITIALIZATION: return tr( "Initialization" ); + case Call::State::ABORTED: + return tr( "Initialization" ); default: return QString::number(static_cast<int>(cur)); } @@ -633,7 +648,7 @@ const QString Call::transferNumber() const ///Get the call / peer number const QString Call::dialNumber() const { - if (d_ptr->m_CurrentState != Call::State::DIALING) return QString(); + if (lifeCycleState() != Call::LifeCycleState::CREATION) return QString(); if (!d_ptr->m_pDialNumber) { d_ptr->m_pDialNumber = new TemporaryContactMethod(); } @@ -655,7 +670,7 @@ const QString Call::dringId() const ContactMethod* Call::peerContactMethod() const { - if (d_ptr->m_CurrentState == Call::State::DIALING) { + if (lifeCycleState() == Call::LifeCycleState::CREATION) { if (!d_ptr->m_pTransferNumber) { d_ptr->m_pTransferNumber = new TemporaryContactMethod(d_ptr->m_pPeerContactMethod); } @@ -755,13 +770,15 @@ bool Call::hasRemote() const bool Call::hasVideo() const { #ifdef ENABLE_VIDEO + if (!hasRemote()) + return false; + return VideoRendererManager::instance()->getRenderer(this) != nullptr; #else return false; #endif } - ///Get the current state Call::State Call::state() const { @@ -846,11 +863,13 @@ void Call::setTransferNumber(const QString& number) void Call::setDialNumber(const QString& number) { //This is not supposed to happen, but this is not a serious issue if it does - if (d_ptr->m_CurrentState != Call::State::DIALING) { + if (lifeCycleState() != Call::LifeCycleState::CREATION) { qDebug() << "Trying to set a dial number to a non-dialing call, doing nothing"; return; } + const bool isEmpty = number.isEmpty(); + if (!d_ptr->m_pDialNumber) { d_ptr->m_pDialNumber = new TemporaryContactMethod(); } @@ -859,12 +878,18 @@ void Call::setDialNumber(const QString& number) emit dialNumberChanged(d_ptr->m_pDialNumber->uri()); emit changed(); emit changed(this); + + //Make sure the call is now in the right state + if ((!isEmpty) && state() == Call::State::NEW) + d_ptr->changeCurrentState(Call::State::DIALING); + else if (isEmpty && state() == Call::State::DIALING) + d_ptr->changeCurrentState(Call::State::NEW); } ///Set the dial number from a full phone number void Call::setDialNumber(const ContactMethod* number) { - if (d_ptr->m_CurrentState == Call::State::DIALING && !d_ptr->m_pDialNumber) { + if (lifeCycleState() == Call::LifeCycleState::CREATION && !d_ptr->m_pDialNumber) { d_ptr->m_pDialNumber = new TemporaryContactMethod(number); } if (d_ptr->m_pDialNumber && number) @@ -897,7 +922,7 @@ void Call::setPeerName(const QString& name) ///Set the account (DIALING only, may be ignored) void Call::setAccount( Account* account) { - if (state() == Call::State::DIALING) + if (lifeCycleState() == Call::LifeCycleState::CREATION) d_ptr->m_Account = account; } @@ -981,9 +1006,13 @@ Call::State CallPrivate::stateChanged(const QString& newStateName) //Until now, it does not worth using stateChangedStateMap, conferences are quite simple //update 2014: Umm... wrong m_CurrentState = confStatetoCallState(newStateName); //TODO don't do this - emit q_ptr->stateChanged(); + emit q_ptr->stateChanged(m_CurrentState,previousState); + + if (CallPrivate::metaStateMap[m_CurrentState] != CallPrivate::metaStateMap[previousState]) + emit q_ptr->lifeCycleStateChanged(CallPrivate::metaStateMap[m_CurrentState],CallPrivate::metaStateMap[previousState]); + } - if (m_CurrentState != Call::State::DIALING && m_pDialNumber) { + if (q_ptr->lifeCycleState() != Call::LifeCycleState::CREATION && m_pDialNumber) { if (!m_pPeerContactMethod) m_pPeerContactMethod = PhoneDirectoryModel::instance()->fromTemporary(m_pDialNumber); m_pDialNumber->deleteLater(); @@ -1064,9 +1093,21 @@ void CallPrivate::changeCurrentState(Call::State newState) throw newState; } + if (m_CurrentState == newState) { + qDebug() << "Origin and destination states are identical" << m_CurrentState << newState << "doing nothing" << q_ptr; + return; + } + + const Call::State previousState = m_CurrentState; + m_CurrentState = newState; + qDebug() << "State changing from"<<previousState << "to" << m_CurrentState << "on" << q_ptr; + + emit q_ptr->stateChanged(newState, previousState); + + if (CallPrivate::metaStateMap[newState] != CallPrivate::metaStateMap[previousState]) + emit q_ptr->lifeCycleStateChanged(CallPrivate::metaStateMap[newState],CallPrivate::metaStateMap[previousState]); - emit q_ptr->stateChanged(); emit q_ptr->changed(); emit q_ptr->changed(q_ptr); @@ -1229,11 +1270,17 @@ void CallPrivate::remove() callManager.hangUpConference(q_ptr->dringId()); emit q_ptr->isOver(q_ptr); - emit q_ptr->stateChanged(); + emit q_ptr->stateChanged(m_CurrentState, m_CurrentState); emit q_ptr->changed(); emit q_ptr->changed(q_ptr); } +///Abort this call (never notify the daemon there was a call) +void CallPrivate::abort() +{ + +} + ///Cancel this call void CallPrivate::cancel() { @@ -1284,7 +1331,6 @@ void CallPrivate::call() m_pDialNumber = nullptr; } q_ptr->setPeerName(tr("Failure")); - emit q_ptr->stateChanged(); emit q_ptr->changed(); } //Normal case @@ -1435,13 +1481,15 @@ void CallPrivate::warning() case Call::State::TRANSFERRED : case Call::State::TRANSF_HOLD : case Call::State::DIALING : - case Call::State::INITIALIZATION: + case Call::State::NEW : + case Call::State::INITIALIZATION : case Call::State::INCOMING : case Call::State::RINGING : case Call::State::CURRENT : case Call::State::HOLD : case Call::State::BUSY : case Call::State::OVER : + case Call::State::ABORTED : case Call::State::CONFERENCE : case Call::State::CONFERENCE_HOLD: default: @@ -1459,14 +1507,20 @@ void CallPrivate::warning() void Call::appendText(const QString& str) { TemporaryContactMethod* editNumber = nullptr; - switch (d_ptr->m_CurrentState) { case Call::State::TRANSFERRED : case Call::State::TRANSF_HOLD : editNumber = d_ptr->m_pTransferNumber; break; case Call::State::DIALING : + case Call::State::NEW : { + const bool wasEmpty = (!editNumber) ||editNumber->uri().isEmpty(); editNumber = d_ptr->m_pDialNumber; + const bool isEmpty = str.isEmpty(); + + if (wasEmpty != isEmpty) + d_ptr->changeCurrentState(isEmpty ? Call::State::NEW : Call::State::DIALING); + } break; case Call::State::INITIALIZATION: case Call::State::INCOMING: @@ -1476,6 +1530,7 @@ void Call::appendText(const QString& str) case Call::State::FAILURE: case Call::State::BUSY: case Call::State::OVER: + case Call::State::ABORTED: case Call::State::ERROR: case Call::State::CONFERENCE: case Call::State::CONFERENCE_HOLD: @@ -1487,7 +1542,7 @@ void Call::appendText(const QString& str) if (editNumber) { editNumber->setUri(editNumber->uri()+str); - if (state() == Call::State::DIALING) + if (lifeCycleState() == Call::LifeCycleState::CREATION) emit dialNumberChanged(editNumber->uri()); } else @@ -1508,8 +1563,16 @@ void Call::backspaceItemText() case Call::State::TRANSF_HOLD : editNumber = d_ptr->m_pTransferNumber; break; - case Call::State::DIALING : + case Call::State::NEW: + case Call::State::DIALING : { + const bool wasEmpty = (!editNumber) ||editNumber->uri().isEmpty(); editNumber = d_ptr->m_pDialNumber; + const bool isEmpty = editNumber->uri().isEmpty(); + + if (wasEmpty != isEmpty) + d_ptr->changeCurrentState(isEmpty ? Call::State::NEW : Call::State::DIALING); + + } break; case Call::State::INITIALIZATION: case Call::State::INCOMING: @@ -1518,6 +1581,7 @@ void Call::backspaceItemText() case Call::State::HOLD: case Call::State::FAILURE: case Call::State::BUSY: + case Call::State::ABORTED: case Call::State::OVER: case Call::State::ERROR: case Call::State::CONFERENCE: @@ -1536,7 +1600,7 @@ void Call::backspaceItemText() emit changed(this); } else { - d_ptr->changeCurrentState(Call::State::OVER); + d_ptr->changeCurrentState(Call::State::ABORTED); } } else @@ -1554,7 +1618,9 @@ void Call::reset() editNumber = d_ptr->m_pTransferNumber; break; case Call::State::DIALING : + case Call::State::NEW : editNumber = d_ptr->m_pDialNumber; + d_ptr->changeCurrentState( Call::State::NEW ); break; case Call::State::INITIALIZATION : case Call::State::INCOMING : @@ -1564,6 +1630,7 @@ void Call::reset() case Call::State::FAILURE : case Call::State::BUSY : case Call::State::OVER : + case Call::State::ABORTED : case Call::State::ERROR : case Call::State::CONFERENCE : case Call::State::CONFERENCE_HOLD : @@ -1669,7 +1736,7 @@ QVariant Call::roleData(int role) const case Qt::DisplayRole: if (type() == Call::Type::CONFERENCE) return tr("Conference"); - else if (state() == Call::State::DIALING) + else if (lifeCycleState() == Call::LifeCycleState::CREATION) return dialNumber(); else if (d_ptr->m_PeerName.isEmpty()) return ct?ct->formattedName():peerContactMethod()?peerContactMethod()->uri():dialNumber(); @@ -1766,7 +1833,7 @@ QVariant Call::roleData(int role) const case static_cast<int>(Call::Role::Missed): return isMissed(); case static_cast<int>(Call::Role::LifeCycleState): - return static_cast<int>(lifeCycleState()); //TODO Qt5, use the Q_ENUM + return QVariant::fromValue(lifeCycleState()); case static_cast<int>(Call::Role::DTMFAnimState): return property("DTMFAnimState"); break; diff --git a/src/call.h b/src/call.h index 26226603d2c79618983265dcb1f9201ca90d863c..137047db037195559726a61cf0e4ed96cd29d7f8 100644 --- a/src/call.h +++ b/src/call.h @@ -124,20 +124,22 @@ public: ///Possible call states enum class State : unsigned int{ - INCOMING = 0, /*!< Ringing incoming call */ - RINGING = 1, /*!< Ringing outgoing call */ - CURRENT = 2, /*!< Call to which the user can speak and hear */ - DIALING = 3, /*!< Call which numbers are being added by the user */ - HOLD = 4, /*!< Call is on hold */ - FAILURE = 5, /*!< Call has failed */ - BUSY = 6, /*!< Call is busy */ - TRANSFERRED = 7, /*!< Call is being transferred. During this state, the user can enter the new number. */ - TRANSF_HOLD = 8, /*!< Call is on hold for transfer */ - OVER = 9, /*!< Call is over and should not be used */ - ERROR = 10,/*!< This state should never be reached */ - CONFERENCE = 11,/*!< This call is the current conference */ - CONFERENCE_HOLD = 12,/*!< This call is a conference on hold */ - INITIALIZATION = 13,/*!< The call have been placed, but the peer hasn't confirmed yet */ + NEW = 0, /*!< The call has been created, but no dialing number been set */ + INCOMING = 1, /*!< Ringing incoming call */ + RINGING = 2, /*!< Ringing outgoing call */ + CURRENT = 3, /*!< Call to which the user can speak and hear */ + DIALING = 4, /*!< Call which numbers are being added by the user */ + HOLD = 5, /*!< Call is on hold */ + FAILURE = 6, /*!< Call has failed */ + BUSY = 7, /*!< Call is busy */ + TRANSFERRED = 8, /*!< Call is being transferred. During this state, the user can enter the new number. */ + TRANSF_HOLD = 9, /*!< Call is on hold for transfer */ + OVER = 10,/*!< Call is over and should not be used */ + ERROR = 11,/*!< This state should never be reached */ + CONFERENCE = 12,/*!< This call is the current conference */ + CONFERENCE_HOLD = 13,/*!< This call is a conference on hold */ + INITIALIZATION = 14,/*!< The call have been placed, but the peer hasn't confirmed yet */ + ABORTED = 15,/*!< The call was dropped before being sent to the daemon */ COUNT__, }; Q_ENUMS(State) @@ -176,11 +178,13 @@ public: * as BUSY OR FAILURE while also finished */ enum class LifeCycleState { - INITIALIZATION = 0, /*!< Anything before the media transfer start */ - PROGRESS = 1, /*!< The peers are in communication (or hold) */ - FINISHED = 2, /*!< Everything is over, there is no going back */ + CREATION = 0, /*!< Anything before creating the daemon call */ + INITIALIZATION = 1, /*!< Anything before the media transfer start */ + PROGRESS = 2, /*!< The peers are in communication (or hold) */ + FINISHED = 3, /*!< Everything is over, there is no going back */ COUNT__ }; + Q_ENUMS(LifeCycleState) ///TODO should be deprecated when a better factory system is implemented class HistoryMapFields { @@ -326,7 +330,9 @@ Q_SIGNALS: ///Notify that a DTMF have been played void dtmfPlayed(const QString& str); ///Notify of state change - void stateChanged(); + void stateChanged(Call::State newState, Call::State previousState); + ///Notify that the lifeCycleStateChanged + void lifeCycleStateChanged(Call::LifeCycleState newState, Call::LifeCycleState previousState); ///The call start timestamp changed, this usually indicate the call has started void startTimeStampChanged(time_t newTimeStamp); ///The dial number has changed diff --git a/src/callmodel.cpp b/src/callmodel.cpp index 86b5535cd077217e5bb6a01a58de0b514c9abcae..c1c79297b67c1734ca8c33e58613fd0dff9d3fc3 100644 --- a/src/callmodel.cpp +++ b/src/callmodel.cpp @@ -103,12 +103,9 @@ public: void slotAddPrivateCall ( Call* call ); void slotNewRecordingAvail ( const QString& callId , const QString& filePath); void slotCallChanged ( Call* call ); + void slotStateChanged ( Call::State newState, Call::State previousState ); void slotDTMFPlayed ( const QString& str ); void slotRecordStateChanged ( const QString& callId , bool state ); - #ifdef ENABLE_VIDEO - void slotStartedDecoding ( const QString& callId , const QString& shmKey ); - void slotStoppedDecoding ( const QString& callId , const QString& shmKey ); - #endif }; @@ -163,10 +160,6 @@ void CallModelPrivate::init() /**/connect(&callManager, SIGNAL(conferenceRemoved(QString)) , this , SLOT(slotConferenceRemoved(QString)) ); /**/connect(&callManager, SIGNAL(recordPlaybackFilepath(QString,QString)) , this , SLOT(slotNewRecordingAvail(QString,QString)) ); /**/connect(&callManager, SIGNAL(recordingStateChanged(QString,bool)) , this, SLOT(slotRecordStateChanged(QString,bool))); - #ifdef ENABLE_VIDEO - /**/connect(&interface , SIGNAL(startedDecoding(QString,QString,int,int,bool)), this , SLOT(slotStartedDecoding(QString,QString)) ); - /**/connect(&interface , SIGNAL(stoppedDecoding(QString,QString,bool)) , this , SLOT(slotStoppedDecoding(QString,QString)) ); - #endif /* */ connect(CategorizedHistoryModel::instance(),SIGNAL(newHistoryCall(Call*)),this,SLOT(slotAddPrivateCall(Call*))); @@ -415,6 +408,7 @@ Call* CallModelPrivate::addCall2(Call* call, Call* parentCall) const QModelIndex idx = q_ptr->index(m_lInternalModel.size()-1,0,QModelIndex()); emit q_ptr->dataChanged(idx, idx); connect(call,SIGNAL(changed(Call*)),this,SLOT(slotCallChanged(Call*))); + connect(call,&Call::stateChanged,this,&CallModelPrivate::slotStateChanged); connect(call,SIGNAL(dtmfPlayed(QString)),this,SLOT(slotDTMFPlayed(QString))); connect(call,&Call::videoStarted,[this,call](Video::Renderer* r){ emit q_ptr->rendererAdded(call, r); @@ -430,7 +424,7 @@ Call* CallModel::dialingCall(const QString& peerName, Account* account) //Having multiple dialing calls could be supported, but for now we decided not to //handle this corner case as it will create issues of its own foreach (Call* call, getActiveCalls()) { - if (call->state() == Call::State::DIALING) + if (call->lifeCycleState() == Call::LifeCycleState::CREATION) return call; } @@ -798,7 +792,7 @@ Qt::ItemFlags CallModel::flags( const QModelIndex& idx ) const return Qt::ItemIsEnabled|Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | ((c->type() != Call::Type::CONFERENCE)?(Qt::ItemIsDropEnabled):Qt::ItemIsEnabled) - | ((c->state() == Call::State::DIALING)?Qt::ItemIsEditable:Qt::NoItemFlags); + | ((c->lifeCycleState() == Call::LifeCycleState::CREATION)?Qt::ItemIsEditable:Qt::NoItemFlags); } return Qt::NoItemFlags; } @@ -894,6 +888,9 @@ bool CallModelPrivate::isPartOf(const QModelIndex& confIdx, Call* call) ///Try to isolate the MIME id from the dringId() to eventually use something else QByteArray CallModel::getMime(const Call* call) const { + if ((!call) || (!call->hasRemote())) + return {}; + return call->dringId().toLatin1(); } @@ -1014,11 +1011,12 @@ bool CallModel::dropMimeData(const QMimeData* mimedata, Qt::DropAction action, i ///When a call state change void CallModelPrivate::slotCallStateChanged(const QString& callID, const QString& stateName, int code) { + //This code is part of the CallModel interface too qDebug() << "Call State Changed for call " << callID << " . New state : " << stateName; InternalStruct* internal = m_shDringId[callID]; Call* call = nullptr; - Call::State previousState = Call::State::RINGING; + if(!internal) { qDebug() << "Call not found" << callID << "new state" << stateName; if(stateName == CallPrivate::StateChange::RINGING) { @@ -1031,7 +1029,7 @@ void CallModelPrivate::slotCallStateChanged(const QString& callID, const QString } else { call = internal->call_real; - previousState = call->state(); + qDebug() << "Call found" << call << call->state(); const Call::LifeCycleState oldLifeCycleState = call->lifeCycleState(); const Call::State oldState = call->state(); @@ -1054,8 +1052,6 @@ void CallModelPrivate::slotCallStateChanged(const QString& callID, const QString } } - emit q_ptr->callStateChanged(call,previousState); - } //slotCallStateChanged ///When a new call is incoming @@ -1190,21 +1186,14 @@ void CallModelPrivate::slotNewRecordingAvail( const QString& callId, const QStri q_ptr->getCall(callId)->setRecordingPath(filePath); } -#ifdef ENABLE_VIDEO -///Updating call state when video is added -void CallModelPrivate::slotStartedDecoding(const QString& callId, const QString& shmKey) +void CallModelPrivate::slotStateChanged(Call::State newState, Call::State previousState) { - Q_UNUSED(callId) - Q_UNUSED(shmKey) -} + Q_UNUSED(newState) -///Updating call state when video is removed -void CallModelPrivate::slotStoppedDecoding(const QString& callId, const QString& shmKey) -{ - Q_UNUSED(callId) - Q_UNUSED(shmKey) + Call* call = qobject_cast<Call*>(sender()); + if (call) + emit q_ptr->callStateChanged(call, previousState); } -#endif ///Update model if the data change void CallModelPrivate::slotCallChanged(Call* call) @@ -1221,6 +1210,7 @@ void CallModelPrivate::slotCallChanged(Call* call) removeCall(call); break; //Over can be caused by local events + case Call::State::ABORTED: case Call::State::OVER: removeCall(call); break; @@ -1230,6 +1220,7 @@ void CallModelPrivate::slotCallChanged(Call* call) case Call::State::INITIALIZATION: case Call::State::CURRENT: case Call::State::DIALING: + case Call::State::NEW: case Call::State::HOLD: case Call::State::FAILURE: case Call::State::BUSY: diff --git a/src/numbercompletionmodel.cpp b/src/numbercompletionmodel.cpp index e3a75d220a813c005e09b893c25c8442890a2d6a..ceb974f8a854a4dd3c495634b22bc24f43817348 100644 --- a/src/numbercompletionmodel.cpp +++ b/src/numbercompletionmodel.cpp @@ -212,7 +212,7 @@ void NumberCompletionModel::setCall(Call* call) void NumberCompletionModel::setPrefix(const QString& str) { d_ptr->m_Prefix = str; - const bool e = ((d_ptr->m_pCall && d_ptr->m_pCall->state() == Call::State::DIALING) || (!d_ptr->m_pCall)) && (!str.isEmpty()); + const bool e = ((d_ptr->m_pCall && d_ptr->m_pCall->lifeCycleState() == Call::LifeCycleState::CREATION) || (!d_ptr->m_pCall)) && (!str.isEmpty()); if (d_ptr->m_Enabled != e) { d_ptr->m_Enabled = e; emit enabled(e); diff --git a/src/private/call_p.h b/src/private/call_p.h index 17585cadf7ac4814cc98fe91a39bcf032f1e35b2..9cc9edf3981ba2abe7ff54361e89bdfb20b9b4bc 100644 --- a/src/private/call_p.h +++ b/src/private/call_p.h @@ -214,6 +214,7 @@ public: void startWeird (); void warning (); void remove (); + void abort (); //Helpers void changeCurrentState(Call::State newState); diff --git a/src/private/videorenderermanager.cpp b/src/private/videorenderermanager.cpp index aea07e358ea5ea85c6564e96c2a7e5e329df99aa..6d9ac4c9436fcfab95b5c44bb732ddceb4646699 100644 --- a/src/private/videorenderermanager.cpp +++ b/src/private/videorenderermanager.cpp @@ -110,7 +110,7 @@ int VideoRendererManager::size() const ///Return the call Renderer or nullptr Video::Renderer* VideoRendererManager::getRenderer(const Call* call) const { - if (!call) return nullptr; + if ((!call) || (!call->hasRemote())) return nullptr; return d_ptr->m_hRenderers[call->dringId().toLatin1()]; } diff --git a/src/useractionmodel.cpp b/src/useractionmodel.cpp index 6dab5a9c727ef7be562b7bebc6955078e24fe4c5..d354e5a1388401324de0f8722fe56065da20a0cc 100644 --- a/src/useractionmodel.cpp +++ b/src/useractionmodel.cpp @@ -104,18 +104,18 @@ public Q_SLOTS: //Enabled actions const TypedStateMachine< TypedStateMachine< bool , Call::State > , UserActionModel::Action > UserActionModelPrivate::availableActionMap = {{ - /* INCOMING RINGING CURRENT DIALING HOLD FAILURE BUSY TRANSFERRED TRANSF_HOLD OVER ERROR CONFERENCE CONFERENCE_HOLD INITIALIZATION*/ - /*ACCEPT */ {{ true , false, false, true , false, false, false, false, false, false, false, false, false, false}}, - /*HOLD */ {{ false , false, true , false, true , false, false, false, false, false, false, true , false, false}}, - /*MUTE_AUDIO */ {{ false , true , true , false, false, false, false, false, false, false, false, false, false, false}}, - /*MUTE_VIDEO */ {{ false , true , true , false, false, false, false, false, false, false, false, false, false, false}}, - /*SERVER_TRANSFER */ {{ false , false, true , false, true , false, false, false, false, false, false, false, false, false}}, - /*RECORD */ {{ false , true , true , false, true , false, false, true , true , false, false, true , true , false}}, - /*HANGUP */ {{ true , true , true , true , true , true , true , true , true , false, true , true , true , true }}, - - /*JOIN */ {{ false , true , true , false, true , false, false, true , true , false, false, true , true , false}}, - - /*ADD_NEW */ {{ false , false, false, false, false, false, false, false, false, false, false, false, false, false}}, + /* NEW INCOMING RINGING CURRENT DIALING HOLD FAILURE BUSY TRANSFERRED TRANSF_HOLD OVER ERROR CONFERENCE CONFERENCE_HOLD INITIALIZATION ABORTED*/ + /*ACCEPT */ {{ false , true , false, false, true , false, false, false, false, false, false, false, false, false, false, false}}, + /*HOLD */ {{ false , false , false, true , false, true , false, false, false, false, false, false, true , false, false, false}}, + /*MUTE_AUDIO */ {{ false , false , true , true , false, false, false, false, false, false, false, false, false, false, false, false}}, + /*MUTE_VIDEO */ {{ false , false , true , true , false, false, false, false, false, false, false, false, false, false, false, false}}, + /*SERVER_TRANSFER */ {{ false , false , false, true , false, true , false, false, false, false, false, false, false, false, false, false}}, + /*RECORD */ {{ false , false , true , true , false, true , false, false, true , true , false, false, true , true , false, false}}, + /*HANGUP */ {{ true , true , true , true , true , true , true , true , true , true , false, true , true , true , true , false}}, + + /*JOIN */ {{ false , false , true , true , false, true , false, false, true , true , false, false, true , true , false, false}}, + + /*ADD_NEW */ {{ false , false , false, false, false, false, false, false, false, false, false, false, false, false, false, false}}, }}; /** @@ -228,7 +228,7 @@ m_pCall(nullptr), m_pActiveModel(nullptr) /* JOIN */ QObject::tr("Join" ), - /* JOIN */ QObject::tr("Add new" ), + /* ADD_NEW */ QObject::tr("Add new" ), }}; } @@ -282,7 +282,7 @@ QHash<int,QByteArray> UserActionModel::roleNames() const QVariant UserActionModel::data(const QModelIndex& idx, int role ) const { - if (!idx.isValid() && (idx.row()>=0 && idx.row() < enum_class_size<UserActionModel::Action>())) + if ((!idx.isValid()) || !(idx.row()>=0 && idx.row() < enum_class_size<UserActionModel::Action>())) return QVariant(); UserActionModel::Action action = static_cast<UserActionModel::Action>(idx.row()); @@ -409,6 +409,7 @@ void UserActionModelPrivate::updateCheckMask(int& ret, UserActionModel::Action a case UserActionModel::Action::HANGUP : switch(c->state()) { case Call::State::DIALING : + case Call::State::NEW : m_ActionNames[UserActionModel::Action::HANGUP] = QObject::tr("Cancel"); break; case Call::State::FAILURE :