diff --git a/sflphone-client-gnome/src/codeclist.c b/sflphone-client-gnome/src/codeclist.c index 8887452247081200ed34155ca701900b38e6e205..88136547d4430a69c324425b91b2968826e1a768 100644 --- a/sflphone-client-gnome/src/codeclist.c +++ b/sflphone-client-gnome/src/codeclist.c @@ -290,8 +290,6 @@ void codec_list_update_to_daemon (account_t *acc) { int c = 0; unsigned int i = 0; - g_print ("List of active codecs :\n"); - for(i = 0; i < length; i++) { codec_t* currentCodec = codec_list_get_nth (i, acc->codecs); @@ -301,7 +299,6 @@ void codec_list_update_to_daemon (account_t *acc) { // Save only if active if(currentCodec->is_active) { - g_print ("Codec %s\n", currentCodec->name); // Reallocate memory each time more than one active codec is found if(c!=0) codecList = (void*)realloc(codecList, (c+1)*sizeof(void*)); @@ -311,7 +308,6 @@ void codec_list_update_to_daemon (account_t *acc) { // Put payload string in char array sprintf(payload, "%d", currentCodec->_payload); strcpy((char*)*(codecList+c), payload); - g_print(" %s", *(codecList+c)); c++; } } diff --git a/sflphone-client-gnome/src/uimanager.c b/sflphone-client-gnome/src/uimanager.c index 1042bf0c13682a5aef2eee6a5d1a4bfc8c174bab..26b35661b5ae22367fe6d355df1360cbd3d79cf4 100644 --- a/sflphone-client-gnome/src/uimanager.c +++ b/sflphone-client-gnome/src/uimanager.c @@ -115,6 +115,7 @@ update_actions() gtk_widget_set_sensitive(GTK_WIDGET (holdToolbar), FALSE); gtk_widget_set_sensitive(GTK_WIDGET (offHoldToolbar), FALSE); gtk_action_set_sensitive(GTK_ACTION (recordAction), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET (recordWidget), FALSE); gtk_action_set_sensitive(GTK_ACTION (copyAction), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(contactButton), FALSE); gtk_widget_set_tooltip_text(GTK_WIDGET (contactButton), @@ -145,9 +146,9 @@ update_actions() } } - // g_signal_handler_block (GTK_OBJECT (transferToolbar), transfertButtonConnId); - // gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (transferToolbar), FALSE); - // g_signal_handler_unblock ( GTK_OBJECT (transferToolbar), transfertButtonConnId); + // g_signal_handler_block (GTK_OBJECT (recordWidget), recordButtonConnId); + // gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (recordWidget), FALSE); + // g_signal_handler_unblock ( GTK_OBJECT (recordWidget), recordButtonConnId); callable_obj_t * selectedCall = calltab_get_selected_call(active_calltree); conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree); @@ -211,9 +212,7 @@ update_actions() 1); gtk_widget_set_sensitive(GTK_WIDGET (holdMenu), TRUE); gtk_widget_set_sensitive(GTK_WIDGET (holdToolbar), TRUE); - //gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (holdMenu), gtk_image_new_from_stock (GTK_STOCK_ONHOLD, GTK_ICON_SIZE_MENU)); gtk_widget_set_sensitive(GTK_WIDGET (transferToolbar), TRUE); - //gtk_action_set_sensitive( GTK_ACTION(newCallMenu),TRUE); gtk_action_set_sensitive(GTK_ACTION (recordAction), TRUE); gtk_toolbar_insert(GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (holdToolbar), 2); @@ -225,6 +224,7 @@ update_actions() gtk_toggle_tool_button_set_active( GTK_TOGGLE_TOOL_BUTTON (transferToolbar), FALSE); gtk_signal_handler_unblock (transferToolbar, transfertButtonConnId); + break; case CALL_STATE_BUSY: case CALL_STATE_FAILURE: @@ -546,7 +546,14 @@ call_pick_up(void * foo UNUSED) static void call_hang_up(void) { - sflphone_hang_up(); + /* + * [#3020] Restore the record toggle button + * We set it to FALSE, as when we hang up a call, the recording is stopped. + */ + gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (recordWidget), FALSE); + + sflphone_hang_up(); + } static void diff --git a/sflphone-client-kde/CMakeLists.txt b/sflphone-client-kde/CMakeLists.txt index 65b269cfd0d95d8477259389787519d1fa829449..c16efdcb6e584685facfd002d0a085e729deb982 100644 --- a/sflphone-client-kde/CMakeLists.txt +++ b/sflphone-client-kde/CMakeLists.txt @@ -8,7 +8,7 @@ SET(CMAKE_MODULE_PATH "${LOCAL_CMAKE_MODULE_PATH}") # --- custom targets: --- INCLUDE( ${LOCAL_CMAKE_MODULE_PATH}/TargetDistclean.cmake REQUIRED) -FIND_PACKAGE ( Kabc REQUIRED ) +#FIND_PACKAGE ( Kabc REQUIRED ) # FIND_PACKAGE ( PkgConfig REQUIRED ) FIND_PACKAGE ( KDE4 REQUIRED ) FIND_PACKAGE ( Qt4 REQUIRED ) diff --git a/sflphone-client-kde/src/conf/ConfigurationSkeleton.cpp b/sflphone-client-kde/src/conf/ConfigurationSkeleton.cpp index f2bcf04b8b75eb3dbe8eb9879187df0cf2c2807d..991571bbdf94a66c7a52495b38fe1a843bce0f47 100644 --- a/sflphone-client-kde/src/conf/ConfigurationSkeleton.cpp +++ b/sflphone-client-kde/src/conf/ConfigurationSkeleton.cpp @@ -61,7 +61,7 @@ void ConfigurationSkeleton::readConfig() //////////////////////// //Call history settings - setEnableHistory(configurationManager.getHistoryEnabled()); + //setEnableHistory(configurationManager.getHistoryEnabled()); //TODO uncomment setHistoryMax(configurationManager.getHistoryLimit()); //SIP port settings @@ -119,10 +119,10 @@ void ConfigurationSkeleton::readConfig() setAlsaPlugin(configurationManager.getCurrentAudioOutputPlugin()); bool ok; QStringList devices = configurationManager.getCurrentAudioDevicesIndex(); - qDebug() << "inputDevice = " << devices[1]; - int inputDevice = devices[1].toInt(& ok); - if(!ok) qDebug() << "inputDevice is not a number"; - setAlsaInputDevice(inputDevice); + //qDebug() << "inputDevice = " << devices[1]; //TODO uncomment + //int inputDevice = devices[1].toInt(& ok); //TODO uncomment + //if(!ok) qDebug() << "inputDevice is not a number"; //TODO uncomment + //setAlsaInputDevice(inputDevice); //TODO uncomment qDebug() << "outputDevice = " << devices[0]; int outputDevice = devices[0].toInt(& ok); @@ -191,7 +191,7 @@ void ConfigurationSkeleton::writeConfig() qDebug() << "Writing General settings"; //Call history settings - if(enableHistory() != configurationManager.getHistoryEnabled()) configurationManager.setHistoryEnabled(); + //TODO if(enableHistory() != configurationManager.getHistoryEnabled()) configurationManager.setHistoryEnabled(); configurationManager.setHistoryLimit(historyMax()); //SIP port settings configurationManager.setSipPort(sIPPort()); diff --git a/sflphone-client-kde/src/conf/dlgaccounts.cpp b/sflphone-client-kde/src/conf/dlgaccounts.cpp index 78ac4cf34fb28e9e3577f5106b58520c2739a61e..f5d15522b01ea9b6999b81ee76075787f657b03c 100644 --- a/sflphone-client-kde/src/conf/dlgaccounts.cpp +++ b/sflphone-client-kde/src/conf/dlgaccounts.cpp @@ -40,35 +40,66 @@ DlgAccounts::DlgAccounts(KConfigDialog *parent) accountList = new AccountList(false); loadAccountList(); accountListHasChanged = false; - toolButton_accountsApply->setEnabled(false); + //toolButton_accountsApply->setEnabled(false); - connect(edit1_alias, SIGNAL(textEdited(const QString &)), - this, SLOT(changedAccountList())); - connect(edit2_protocol, SIGNAL(activated(int)), - this, SLOT(changedAccountList())); - connect(edit3_server, SIGNAL(textEdited(const QString &)), - this, SLOT(changedAccountList())); - connect(edit4_user, SIGNAL(textEdited(const QString &)), - this, SLOT(changedAccountList())); - connect(edit5_password, SIGNAL(textEdited(const QString &)), - this, SLOT(changedAccountList())); - connect(edit6_mailbox, SIGNAL(textEdited(const QString &)), - this, SLOT(changedAccountList())); - connect(spinbox_regExpire, SIGNAL(editingFinished()), - this, SLOT(changedAccountList())); - connect(checkBox_conformRFC, SIGNAL(clicked(bool)), - this, SLOT(changedAccountList())); - connect(button_accountUp, SIGNAL(clicked()), - this, SLOT(changedAccountList())); - connect(button_accountDown, SIGNAL(clicked()), - this, SLOT(changedAccountList())); - connect(button_accountAdd, SIGNAL(clicked()), - this, SLOT(changedAccountList())); - connect(button_accountRemove, SIGNAL(clicked()), - this, SLOT(changedAccountList())); + connect(edit1_alias, SIGNAL(textEdited(const QString &)), + this, SLOT(changedAccountList())); + connect(edit2_protocol, SIGNAL(activated(int)), + this, SLOT(changedAccountList())); + connect(edit3_server, SIGNAL(textEdited(const QString &)), + this, SLOT(changedAccountList())); + connect(edit4_user, SIGNAL(textEdited(const QString &)), + this, SLOT(changedAccountList())); + connect(edit5_password, SIGNAL(textEdited(const QString &)), + this, SLOT(changedAccountList())); + connect(edit6_mailbox, SIGNAL(textEdited(const QString &)), + this, SLOT(changedAccountList())); + connect(spinbox_regExpire, SIGNAL(editingFinished()), + this, SLOT(changedAccountList())); + connect(checkBox_conformRFC, SIGNAL(clicked(bool)), + this, SLOT(changedAccountList())); + connect(button_accountUp, SIGNAL(clicked()), + this, SLOT(changedAccountList())); + connect(button_accountDown, SIGNAL(clicked()), + this, SLOT(changedAccountList())); + connect(button_accountAdd, SIGNAL(clicked()), + this, SLOT(changedAccountList())); + connect(button_accountRemove, SIGNAL(clicked()), + this, SLOT(changedAccountList())); + connect(edit_tls_private_key_password, SIGNAL(textEdited(const QString &)), + this, SLOT(changedAccountList())); + connect(spinbox_tls_listener, SIGNAL(editingFinished()), + this, SLOT(changedAccountList())); + connect(file_tls_authority, SIGNAL(textChanged(const QString &)), + this, SLOT(changedAccountList())); + connect(file_tls_endpoint, SIGNAL(textChanged(const QString &)), + this, SLOT(changedAccountList())); + connect(file_tls_private_key, SIGNAL(textChanged(const QString &)), + this, SLOT(changedAccountList())); + connect(combo_tls_method, SIGNAL(currentIndexChanged(int)), + this, SLOT(changedAccountList())); + connect(edit_tls_cipher, SIGNAL(textEdited(const QString &)), + this, SLOT(changedAccountList())); + connect(edit_tls_outgoing, SIGNAL(textEdited(const QString &)), + this, SLOT(changedAccountList())); + connect(spinbox_tls_timeout_sec, SIGNAL(editingFinished()), + this, SLOT(changedAccountList())); + connect(spinbox_tls_timeout_msec, SIGNAL(editingFinished()), + this, SLOT(changedAccountList())); + connect(check_tls_incoming, SIGNAL(clicked(bool)), + this, SLOT(changedAccountList())); + connect(check_tls_answer, SIGNAL(clicked(bool)), + this, SLOT(changedAccountList())); + connect(check_tls_requier_cert, SIGNAL(clicked(bool)), + this, SLOT(changedAccountList())); + connect(group_security_tls, SIGNAL(clicked(bool)), + this, SLOT(changedAccountList())); - connect(&configurationManager, SIGNAL(accountsChanged()), - this, SLOT(updateAccountStates())); + connect(&configurationManager, SIGNAL(accountsChanged()), + this, SLOT(updateAccountStates())); + + connect(edit_tls_private_key_password, SIGNAL(textEdited(const QString &)), + this, SLOT(changedAccountList())); connect(this, SIGNAL(updateButtons()), parent, SLOT(updateButtons())); @@ -156,6 +187,24 @@ void DlgAccounts::saveAccount(QListWidgetItem * item) account->setAccountDetail(ACCOUNT_RESOLVE_ONCE, checkBox_conformRFC->isChecked() ? "FALSE" : "TRUE"); account->setAccountDetail(ACCOUNT_EXPIRE, QString::number(spinbox_regExpire->value())); account->setAccountDetail(ACCOUNT_ENABLED, account->isChecked() ? ACCOUNT_ENABLED_TRUE : ACCOUNT_ENABLED_FALSE); + + //Security + account->setAccountDetail(TLS_PASSWORD,edit_tls_private_key_password->text()); + account->setAccountDetail(TLS_LISTENER_PORT,QString::number(spinbox_tls_listener->value())); + account->setAccountDetail(TLS_CA_LIST_FILE,file_tls_authority->text()); + account->setAccountDetail(TLS_CERTIFICATE_FILE,file_tls_endpoint->text()); + account->setAccountDetail(TLS_PRIVATE_KEY_FILE,file_tls_private_key->text()); + //qDebug() << "\n\n\n\nSET: " << combo_tls_method->currentText() << "\n\n\n"; + account->setAccountDetail(TLS_METHOD,combo_tls_method->currentText()); + account->setAccountDetail(TLS_CIPHERS,edit_tls_cipher->text()); + account->setAccountDetail(TLS_SERVER_NAME,edit_tls_outgoing->text()); + account->setAccountDetail(TLS_NEGOTIATION_TIMEOUT_SEC,QString::number(spinbox_tls_timeout_sec->value())); + account->setAccountDetail(TLS_NEGOTIATION_TIMEOUT_MSEC,QString::number(spinbox_tls_timeout_msec->value())); + account->setAccountDetail(TLS_VERIFY_SERVER,check_tls_incoming->isChecked()?"true":"false"); + account->setAccountDetail(TLS_VERIFY_CLIENT,check_tls_answer->isChecked()?"true":"false"); + account->setAccountDetail(TLS_REQUIRE_CLIENT_CERTIFICATE,check_tls_requier_cert->isChecked()?"true":"false"); + account->setAccountDetail(TLS_ENABLE,group_security_tls->isChecked()?"true":"false"); + account->setAccountDetail(TLS_METHOD, QString::number(combo_security_STRP->currentIndex())); } void DlgAccounts::loadAccount(QListWidgetItem * item) @@ -186,6 +235,27 @@ void DlgAccounts::loadAccount(QListWidgetItem * item) bool ok; int val = account->getAccountDetail(ACCOUNT_EXPIRE).toInt(&ok); spinbox_regExpire->setValue(ok ? val : ACCOUNT_EXPIRE_DEFAULT); + + //Security + edit_tls_private_key_password->setText( account->getAccountDetail(TLS_PASSWORD )); + spinbox_tls_listener->setValue( account->getAccountDetail(TLS_LISTENER_PORT ).toInt()); + file_tls_authority->setText( account->getAccountDetail(TLS_CA_LIST_FILE )); + file_tls_endpoint->setText( account->getAccountDetail(TLS_CERTIFICATE_FILE )); + file_tls_private_key->setText( account->getAccountDetail(TLS_PRIVATE_KEY_FILE )); + //qDebug() << "\n\n\n\nTHIS: " << account->getAccountDetail(TLS_METHOD ) << "\n\n\n"; + combo_tls_method->setCurrentIndex( combo_tls_method->findText(account->getAccountDetail(TLS_METHOD ))); + edit_tls_cipher->setText( account->getAccountDetail(TLS_CIPHERS )); + edit_tls_outgoing->setText( account->getAccountDetail(TLS_SERVER_NAME )); + spinbox_tls_timeout_sec->setValue( account->getAccountDetail(TLS_NEGOTIATION_TIMEOUT_SEC ).toInt()); + spinbox_tls_timeout_msec->setValue( account->getAccountDetail(TLS_NEGOTIATION_TIMEOUT_MSEC ).toInt()); + check_tls_incoming->setChecked( (account->getAccountDetail(TLS_VERIFY_SERVER ) == "true")?1:0); + check_tls_answer->setChecked( (account->getAccountDetail(TLS_VERIFY_CLIENT ) == "true")?1:0); + check_tls_requier_cert->setChecked( (account->getAccountDetail(TLS_REQUIRE_CLIENT_CERTIFICATE ) == "true")?1:0); + group_security_tls->setChecked( (account->getAccountDetail(TLS_ENABLE ) == "true")?1:0); + + combo_security_STRP->setCurrentIndex(account->getAccountDetail(TLS_METHOD ).toInt()); + + updateStatusLabel(account); frame2_editAccounts->setEnabled(true); } @@ -220,7 +290,7 @@ void DlgAccounts::changedAccountList() qDebug() << "changedAccountList"; accountListHasChanged = true; emit updateButtons(); - toolButton_accountsApply->setEnabled(true); + //toolButton_accountsApply->setEnabled(true); } @@ -288,12 +358,12 @@ void DlgAccounts::on_button_accountRemove_clicked() listWidget_accountList->setCurrentRow( (r >= listWidget_accountList->count()) ? r-1 : r ); } -void DlgAccounts::on_toolButton_accountsApply_clicked() -{ - qDebug() << "on_toolButton_accountsApply_clicked"; - updateSettings(); - updateWidgets(); -} +// void DlgAccounts::on_toolButton_accountsApply_clicked() //This button have been removed, coded kept for potential reversal +// { +// qDebug() << "on_toolButton_accountsApply_clicked"; +// updateSettings(); +// updateWidgets(); +// } void DlgAccounts::on_edit1_alias_textChanged(const QString & text) { @@ -365,7 +435,7 @@ void DlgAccounts::updateSettings() if(accountListHasChanged) { saveAccountList(); - toolButton_accountsApply->setEnabled(false); + //toolButton_accountsApply->setEnabled(false); accountListHasChanged = false; } } @@ -374,7 +444,7 @@ void DlgAccounts::updateWidgets() { qDebug() << "DlgAccounts::updateWidgets"; loadAccountList(); - toolButton_accountsApply->setEnabled(false); + //toolButton_accountsApply->setEnabled(false); accountListHasChanged = false; } diff --git a/sflphone-client-kde/src/conf/dlgaccounts.h b/sflphone-client-kde/src/conf/dlgaccounts.h index 32743689175be525b94fb91aab1bd98eb694a9db..2eff977fb2b3f5551f1e21e05c351dd2b496012d 100644 --- a/sflphone-client-kde/src/conf/dlgaccounts.h +++ b/sflphone-client-kde/src/conf/dlgaccounts.h @@ -78,7 +78,7 @@ private slots: void on_button_accountRemove_clicked(); void on_edit1_alias_textChanged(const QString & text); void on_listWidget_accountList_currentItemChanged ( QListWidgetItem * current, QListWidgetItem * previous ); - void on_toolButton_accountsApply_clicked(); + //void on_toolButton_accountsApply_clicked(); //Disabled for future removal void updateAccountStates(); void addAccountToAccountList(Account * account); void updateAccountListCommands(); diff --git a/sflphone-client-kde/src/conf/dlgaccountsbase.ui b/sflphone-client-kde/src/conf/dlgaccountsbase.ui index eafe181482ff650951b73e6f5f9ab1781cf4c1b8..a794240e5a4d840c83d7c9b795cfec75f651467a 100644 --- a/sflphone-client-kde/src/conf/dlgaccountsbase.ui +++ b/sflphone-client-kde/src/conf/dlgaccountsbase.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>603</width> - <height>455</height> + <width>748</width> + <height>447</height> </rect> </property> <property name="windowTitle"> @@ -29,8 +29,8 @@ <item> <widget class="QFrame" name="frame1_accountList"> <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>1</horstretch> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> @@ -46,6 +46,12 @@ <height>16777215</height> </size> </property> + <property name="sizeIncrement"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> <property name="frameShape"> <enum>QFrame::StyledPanel</enum> </property> @@ -212,16 +218,6 @@ </property> </spacer> </item> - <item> - <widget class="QToolButton" name="toolButton_accountsApply"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>Apply</string> - </property> - </widget> - </item> </layout> </widget> </item> @@ -232,7 +228,7 @@ <widget class="QTabWidget" name="frame2_editAccounts"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> + <horstretch>3</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> @@ -419,6 +415,445 @@ </item> </layout> </widget> + <widget class="QWidget" name="tab"> + <attribute name="title"> + <string>Credential</string> + </attribute> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0" rowspan="2" colspan="3"> + <widget class="QListWidget" name="list_credential"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="2" column="0"> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>327</width> + <height>23</height> + </size> + </property> + </spacer> + </item> + <item row="3" column="0" colspan="3"> + <widget class="QGroupBox" name="group_credential"> + <property name="title"> + <string>Details</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QLabel" name="label_credential_realm"> + <property name="text"> + <string>Realm</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="labe_credential_auth"> + <property name="text"> + <string>Auth. name</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_credential_password"> + <property name="text"> + <string>Password</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="KLineEdit" name="edit_credential_realm"/> + </item> + <item row="1" column="1"> + <widget class="KLineEdit" name="edit_credential_auth"/> + </item> + <item row="2" column="1"> + <widget class="KLineEdit" name="edit_credential_password"/> + </item> + </layout> + </widget> + </item> + <item row="2" column="1"> + <widget class="QToolButton" name="button_add_credential"> + <property name="text"> + <string>Add</string> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QToolButton" name="button_remove_credential"> + <property name="text"> + <string>Remove</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_2"> + <attribute name="title"> + <string>Security</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> + <widget class="QScrollArea" name="scrollArea"> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <widget class="QWidget" name="scrollAreaWidgetContents"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>426</width> + <height>588</height> + </rect> + </property> + <layout class="QGridLayout" name="gridLayout_5"> + <item row="0" column="0"> + <widget class="QLabel" name="label_security_STRP"> + <property name="text"> + <string>STRP key exchange</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="combo_security_STRP"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <item> + <property name="text"> + <string>Disabled</string> + </property> + </item> + <item> + <property name="text"> + <string>ZRTP</string> + </property> + </item> + <item> + <property name="text"> + <string>SDES</string> + </property> + </item> + </widget> + </item> + <item row="0" column="2"> + <widget class="QToolButton" name="button_security_STRP"> + <property name="text"> + <string>Edit</string> + </property> + </widget> + </item> + <item row="1" column="0" colspan="3"> + <widget class="QLabel" name="label_tls_info"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>TLS transport can be used along with UDP for those calls that would require secure sip transactions (aka SIPS). You can configure a different TLS transport for each account. However each of them will run on a dedicated port, different one from each other.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="0" colspan="3"> + <widget class="QGroupBox" name="group_security_tls"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Enable TLS</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> + <widget class="QLabel" name="label_tls_listener"> + <property name="text"> + <string>Global TLS listener*</string> + </property> + </widget> + </item> + <item row="0" column="1" colspan="3"> + <widget class="KIntSpinBox" name="spinbox_tls_listener"> + <property name="maximum"> + <number>65535</number> + </property> + </widget> + </item> + <item row="0" column="4" colspan="5"> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_tls_authority"> + <property name="text"> + <string>Authority certificate list</string> + </property> + </widget> + </item> + <item row="1" column="1" colspan="8"> + <widget class="KUrlRequester" name="file_tls_authority"/> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_tls_endpoint"> + <property name="text"> + <string>Public endpoint certificate</string> + </property> + </widget> + </item> + <item row="2" column="1" colspan="8"> + <widget class="KUrlRequester" name="file_tls_endpoint"/> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_tls_private_key"> + <property name="text"> + <string>Private key</string> + </property> + </widget> + </item> + <item row="3" column="1" colspan="8"> + <widget class="KUrlRequester" name="file_tls_private_key"/> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_tls_private_key_password"> + <property name="text"> + <string>Private key password</string> + </property> + </widget> + </item> + <item row="4" column="1" colspan="8"> + <widget class="KLineEdit" name="edit_tls_private_key_password"/> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="label_tls_method"> + <property name="text"> + <string>TLS protocol method</string> + </property> + </widget> + </item> + <item row="5" column="1" colspan="3"> + <widget class="QComboBox" name="combo_tls_method"> + <item> + <property name="text"> + <string>Default</string> + </property> + </item> + <item> + <property name="text"> + <string>TLSv1</string> + </property> + </item> + <item> + <property name="text"> + <string>SSLv2</string> + </property> + </item> + <item> + <property name="text"> + <string>SSLv3</string> + </property> + </item> + <item> + <property name="text"> + <string>SSLv23</string> + </property> + </item> + </widget> + </item> + <item row="5" column="4" colspan="5"> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="label_tls_cipher"> + <property name="text"> + <string>TLS cipher list</string> + </property> + </widget> + </item> + <item row="6" column="1" colspan="8"> + <widget class="KLineEdit" name="edit_tls_cipher"/> + </item> + <item row="7" column="0"> + <widget class="QLabel" name="label_tls_outgoing"> + <property name="text"> + <string>Outgoing TLS server name</string> + </property> + </widget> + </item> + <item row="7" column="1" colspan="8"> + <widget class="KLineEdit" name="edit_tls_outgoing"/> + </item> + <item row="8" column="0"> + <widget class="QLabel" name="label_tls_timeout"> + <property name="text"> + <string>Negotiation timeout (s:ms)</string> + </property> + </widget> + </item> + <item row="8" column="1"> + <widget class="KIntSpinBox" name="spinbox_tls_timeout_sec"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + </widget> + </item> + <item row="9" column="0" colspan="5"> + <widget class="QCheckBox" name="check_tls_incoming"> + <property name="text"> + <string>Verify incoming certificates (server side)</string> + </property> + </widget> + </item> + <item row="10" column="0" colspan="5"> + <widget class="QCheckBox" name="check_tls_answer"> + <property name="text"> + <string>Verify answer certificates (client side)</string> + </property> + </widget> + </item> + <item row="11" column="0" colspan="5"> + <widget class="QCheckBox" name="check_tls_requier_cert"> + <property name="text"> + <string>Require a certificate for incoming TLS connections</string> + </property> + </widget> + </item> + <item row="12" column="0"> + <widget class="QLabel" name="label_tls_details"> + <property name="text"> + <string>*Apply to all accounts</string> + </property> + </widget> + </item> + <item row="13" column="0"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item row="8" column="4" colspan="5"> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="8" column="3"> + <widget class="KIntSpinBox" name="spinbox_tls_timeout_msec"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + </widget> + </item> + <item row="8" column="2"> + <widget class="QLabel" name="label_timeout2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>10</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>10</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string><center>:</center></string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> </widget> </item> </layout> @@ -484,6 +919,11 @@ <extends>QSpinBox</extends> <header>knuminput.h</header> </customwidget> + <customwidget> + <class>KUrlRequester</class> + <extends>QFrame</extends> + <header>kurlrequester.h</header> + </customwidget> <customwidget> <class>KLineEdit</class> <extends>QLineEdit</extends> diff --git a/sflphone-client-kde/src/sflphone_const.h b/sflphone-client-kde/src/sflphone_const.h index 356a2e5755c5300b06bc4707172f84fe09daa9b8..c26ce8ed0341d863b7a4a24707f9f138b504425e 100644 --- a/sflphone-client-kde/src/sflphone_const.h +++ b/sflphone-client-kde/src/sflphone_const.h @@ -205,6 +205,35 @@ #define CONST_ALSA 0 #define CONST_PULSEAUDIO 1 - +/** TLS */ +#define TLS_LISTENER_PORT "TLS.listenerPort" +#define TLS_ENABLE "TLS.enable" +#define TLS_PORT "TLS.port" +#define TLS_CA_LIST_FILE "TLS.certificateListFile" +#define TLS_CERTIFICATE_FILE "TLS.certificateFile" +#define TLS_PRIVATE_KEY_FILE "TLS.privateKeyFile" +#define TLS_PASSWORD "TLS.password" +#define TLS_METHOD "TLS.method" +#define TLS_CIPHERS "TLS.ciphers" +#define TLS_SERVER_NAME "TLS.serverName" +#define TLS_VERIFY_SERVER "TLS.verifyServer" +#define TLS_VERIFY_CLIENT "TLS.verifyClient" +#define TLS_REQUIRE_CLIENT_CERTIFICATE "TLS.requireClientCertificate" +#define TLS_NEGOTIATION_TIMEOUT_SEC "TLS.negotiationTimeoutSec" +#define TLS_NEGOTIATION_TIMEOUT_MSEC "TLS.negotiationTimemoutMsec" + +#define ACCOUNT_PASSWORD "password" +#define ACCOUNT_AUTHENTICATION_USERNAME "authenticationUsername" +#define ACCOUNT_REALM "realm" +#define ACCOUNT_KEY_EXCHANGE "SRTP.keyExchange" +#define ACCOUNT_SRTP_ENABLED "SRTP.enable" +#define ACCOUNT_SRTP_RTP_FALLBACK "SRTP.rtpFallback" +#define ACCOUNT_ZRTP_DISPLAY_SAS "ZRTP.displaySAS" +#define ACCOUNT_ZRTP_NOT_SUPP_WARNING "ZRTP.notSuppWarning" +#define ACCOUNT_ZRTP_HELLO_HASH "ZRTP.helloHashEnable" +#define ACCOUNT_DISPLAY_SAS_ONCE "ZRTP.displaySasOnce" +#define KEY_EXCHANGE_NONE "0" +#define ZRTP "1" +#define SDES "2" #endif diff --git a/sflphone-common/Makefile.am b/sflphone-common/Makefile.am index 6d464df1bf37e8d39e06d4e3e91f6ecc220143b6..c5de2501fbb765d640061938f15ce4b259270a3a 100644 --- a/sflphone-common/Makefile.am +++ b/sflphone-common/Makefile.am @@ -18,6 +18,12 @@ unittest: @echo " -- You need the cppunit devel package to compile the unitary tests." endif +doc: + @(cd doc; make) + @echo "" + @echo "D-Bus API HTML documentation has been generated in doc/dbus-api/doc/spec" + @echo "" + indent: @echo "Indenting code:" if [ -f $(ASTYLERC) ] ; then \ diff --git a/sflphone-common/configure.ac b/sflphone-common/configure.ac index 96434834b6f544fc4da4751b583e5d54f003584a..5a412e3c47302b2eb152fa88d4ad860404b9945f 100644 --- a/sflphone-common/configure.ac +++ b/sflphone-common/configure.ac @@ -70,12 +70,12 @@ AC_CONFIG_FILES([Makefile]) dnl Unitary test section AC_CONFIG_FILES([test/Makefile]) - AC_CONFIG_FILES([ringtones/Makefile]) AC_CONFIG_FILES([man/Makefile]) AC_CONFIG_FILES([doc/Makefile \ + doc/dbus-api/Makefile \ doc/doxygen/Makefile]) dnl the file stamp-h.in should be there before (instead of AC_CONFIG_HEADERS(config.h)) diff --git a/sflphone-common/doc/Makefile.am b/sflphone-common/doc/Makefile.am index bbe34b9b1a6c74986447496e5d138d4902d5f937..f742c26ce5b69235cbafa55a31bf5292ffffa0e7 100644 --- a/sflphone-common/doc/Makefile.am +++ b/sflphone-common/doc/Makefile.am @@ -1,6 +1,6 @@ -SUBDIRS = doxygen +SUBDIRS = doxygen dbus-api .PHONY: doc doc: - $(MAKE) -C doxygen doc \ No newline at end of file + $(MAKE) -C doxygen doc diff --git a/sflphone-common/doc/dbus-api/Makefile.am b/sflphone-common/doc/dbus-api/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..ced9bceb9dcbb3635220042dfdc8cacd9f35fe13 --- /dev/null +++ b/sflphone-common/doc/dbus-api/Makefile.am @@ -0,0 +1,28 @@ +include $(top_srcdir)/globals.mak + +XSLTPROC=xsltproc --xinclude --nonet +PYTHON=python + +XMLS= $(wildcard $(top_srcdir)/src/dbus/spec/*.xml) +TEMPLATES= $(wildcard doc/templates/*) + +GENERATED_FILES = \ + doc/spec.html \ + doc/spec/index.html + +doc/spec.html: $(XMLS) tools/doc-generator.xsl + @install -d tmp/doc + $(XSLTPROC) tools/doc-generator.xsl spec/all.xml > tmp/$@ + mv tmp/$@ $@ + +doc/spec/index.html: $(XMLS) tools/doc-generator.py tools/specparser.py $(TEMPLATES) + @install -d tmp/doc + $(PYTHON) tools/doc-generator.py spec/all.xml doc/spec sflphone-spec org.sflphone.SFLphone + +all: $(GENERATED_FILES) + +clean: + rm -rf $(GENERATED_FILES) + rm -rf doc/spec + rm -rf tmp + diff --git a/sflphone-common/doc/dbus-api/README b/sflphone-common/doc/dbus-api/README new file mode 100644 index 0000000000000000000000000000000000000000..3adb69af24b6160d4339180ba0d31cc003ab850e --- /dev/null +++ b/sflphone-common/doc/dbus-api/README @@ -0,0 +1,7 @@ +SFLphone D-Bus API documentation. Generated with xsltproc. + +Wiki reference: https://projects.savoirfairelinux.com/wiki/sflphone/Dbus-API + +Run Makefile to generate the HTML API documentation, from the xml interfaces in *sflphone-common/src/dbus*. + +The documentation is generated in *sflphone-common/doc/dbus-api/doc/spec* diff --git a/sflphone-common/doc/dbus-api/doc/templates/devhelp.devhelp2 b/sflphone-common/doc/dbus-api/doc/templates/devhelp.devhelp2 new file mode 100644 index 0000000000000000000000000000000000000000..af327fa6d99be647dc588b574b489ab6f6bf8ace --- /dev/null +++ b/sflphone-common/doc/dbus-api/doc/templates/devhelp.devhelp2 @@ -0,0 +1,18 @@ +<?xml version="1.0"?> +<book xmlns="http://www.devhelp.net/book" title="$spec.title" name="$name" link="index.html"> + <chapters> +#for $interface in $spec.interfaces + <sub name="$interface.name" link="$interface.get_url()"/> +#end for + <sub name="Generic Types" link="generic-types.html"/> + <sub name="Errors" link="errors.html"/> + <sub name="Full Index" link="fullindex.html"/> + </chapters> + <functions> +#for $obj in $spec.everything.values() + $spec.types.values() + $spec.errors.values() + <keyword type="$obj.devhelp_name" name="$obj.get_title()" link="$obj.get_url()" #slurp +#if $obj.deprecated: deprecated="true" #slurp +/> +#end for + </functions> +</book> diff --git a/sflphone-common/doc/dbus-api/doc/templates/errors.html b/sflphone-common/doc/dbus-api/doc/templates/errors.html new file mode 100644 index 0000000000000000000000000000000000000000..907d6601c2145a5c825a82165b3cc493528076ca --- /dev/null +++ b/sflphone-common/doc/dbus-api/doc/templates/errors.html @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE html PUBLIC "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" ""> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> + <head> + <title>Errors</title> + <link rel="stylesheet" href="style.css" type="text/css"/> + </head> + <body> + <div class="header"> + <h1>Errors</h1> + <a href="index.html">Interface Index</a> + (<a href="interfaces.html">Compact</a>) + | <a href="#summary">Summary</a> + | <a href="#errors">Errors</a> + </div> + <div class="main"> + <div class="summary"> + <a name="summary"></a> + <h3>Errors</h3> + <table class="summary"> + #for $error in $spec.errors.values() + #if $error.deprecated + <tr class="deprecated"> + #else + <tr> + #end if + <td><a href="$error.get_url()">$error.short_name</a></td> + <td> + #if $error.deprecated: (deprecated) + </td> + </tr> + #end for + </table> + </div> + + <div class="outset errors error"> + <a name="errors"></a> + <h1>Errors</h1> + #for $error in $spec.errors.values() + <div class="inset error"> + <a name="$error.name"></a> + <span class="permalink">(<a href="$error.get_url()">Permalink</a>)</span> + <h2> + $error.short_name + </h2> + + <div class="indent"> + <code>$error.name</code> + </div> + + $error.get_added() + $error.get_deprecated() + $error.get_docstring() + </div> + #end for + </div> + </div> + + </body> +</html> diff --git a/sflphone-common/doc/dbus-api/doc/templates/fullindex.html b/sflphone-common/doc/dbus-api/doc/templates/fullindex.html new file mode 100644 index 0000000000000000000000000000000000000000..2c465e1dd71271750111de42d7c471f0d01686fd --- /dev/null +++ b/sflphone-common/doc/dbus-api/doc/templates/fullindex.html @@ -0,0 +1,60 @@ +#from itertools import groupby +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE html PUBLIC "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" ""> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> + <head> + <title>Full Index</title> + <link rel="stylesheet" href="style.css" type="text/css"/> + </head> + +#set $star = [] +#for $item in $spec.everything.values() + $spec.errors.values() + $spec.generic_types + #echo $star.append(($item.short_name, $item)) + #slurp +#end for +#echo $star.sort(key = lambda t: t[0].title()) +#slurp +## one use iterators... +#set $groups = [ (l, list(g)) for l, g in (groupby($star, key = lambda t: t[0][0].upper())) ] +#set $letters = set(map(lambda t: t[0], groups)) + + <body> + <div class="header"> + <h1>Full Index</h1> + <a href="index.html">Interface Index</a> + (<a href="interfaces.html">Compact</a>) + #for $a in map(chr, xrange(ord('A'), ord('Z')+1)) + #if $a in $letters + | <a href="#$a">$a</a> + #else + | $a + #end if + #end for + </div> + + <div class="main"> + <table class="summary"> + #for l, g in $groups + <tr><th colspan="3"><a name="$l"></a>$l</th></tr> + #for $n in $g + #if $n[1].deprecated + <tr class="deprecated"> + #else + <tr> + #end if + <td> + <a href="$n[1].get_url()" title="$n[1].get_title()">$n[0]</a> + #if $n[1].deprecated: (deprecated) + </td> + <td>$n[1].get_type_name()</td> + <td> + #if $n[1].parent.__class__.__name__ == 'Interface': $n[1].parent.name + </td> + </tr> + #end for + #end for + <table> + </div> + + </body> +</html> diff --git a/sflphone-common/doc/dbus-api/doc/templates/generic-types.html b/sflphone-common/doc/dbus-api/doc/templates/generic-types.html new file mode 100644 index 0000000000000000000000000000000000000000..0bb209e432210d364402ce23987000dbe66b7185 --- /dev/null +++ b/sflphone-common/doc/dbus-api/doc/templates/generic-types.html @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE html PUBLIC "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" ""> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> + <head> + <title>Generic Types</title> + <link rel="stylesheet" href="style.css" type="text/css"/> + </head> + <body> + <div class="header"> + <h1>Generic Types</h1> + <a href="index.html">Interface Index</a> + (<a href="interfaces.html">Compact</a>) + | <a href="#summary">Summary</a> + | <a href="#types">Types</a> + </div> + <div class="main"> + <div class="summary"> + <a name="summary"></a> + <h3>Generic Types</h3> + <table class="summary"> + #for $type in $spec.generic_types + #if $type.deprecated + <tr class="deprecated"> + #else + <tr> + #end if + <td><a href="$type.get_url()">$type.short_name</a></td> + <td>$type.get_type_name()</td> + <td>$type.dbus_type</td> + <td> + #if $type.deprecated: (deprecated) + </td> + </tr> + #end for + </table> + </div> + + <div class="outset types type"> + <a name="types"></a> + <h1>Generic Types</h1> + #for $type in $spec.generic_types + <div class="inset type"> + <a name="$type.name"></a> + <span class="permalink">$type.get_type_name() (<a href="$type.get_url()">Permalink</a>)</span> + <h2> + $type.short_name — $type.dbus_type + </h2> + + $type.get_added() + $type.get_deprecated() + $type.get_docstring() + $type.get_breakdown() + </div> + #end for + </div> + </div> + + </body> +</html> diff --git a/sflphone-common/doc/dbus-api/doc/templates/index.html b/sflphone-common/doc/dbus-api/doc/templates/index.html new file mode 100644 index 0000000000000000000000000000000000000000..efc38d4e8ec411eb9721c5e01f222f0c4d392913 --- /dev/null +++ b/sflphone-common/doc/dbus-api/doc/templates/index.html @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE html PUBLIC "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" ""> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> + <head> + <title>$spec.title &mdash v$spec.version</title> + <link rel="stylesheet" href="style.css" type="text/css"/> + </head> + <body> + <div class="header"> + <h1>$spec.title</h1> + <a href="#interfaces">Interfaces</a> + (<a href="interfaces.html">Compact</a>) + | <a href="generic-types.html">Generic Types</a> + | <a href="errors.html">Errors</a> + | <a href="fullindex.html">Full Index</a> + </div> + + <div class="main"> + <h3 class="version">Version $spec.version</h3> + <p class="copyrights"> + #echo '<br/>'.join($spec.copyrights) + </p> + $spec.license + + <a name="interfaces"></a> + <h3>Interfaces</h3> + <ul> + #def output($items) + #for $item in $items + #if $item.__class__.__name__ == 'Section' + <li class="chapter">$item.short_name</li> + $item.get_docstring() + <ul> + $output($item.items) + </ul> + #else + #if $item.causes_havoc + <li class="causes-havoc"> + #elif $item.deprecated + <li class="deprecated"> + #else + <li> + #end if + <a href="$item.get_url()">$item.name</a> + #if $item.causes_havoc + (unstable) + #elif $item.deprecated + (deprecated) + #end if + </li> + #end if + #end for + #end def + $output($spec.items) + </ul> + + <a name="other"></a> + <h3>Other</h3> + <ul> + <li><a href="generic-types.html">Generic Types</a></li> + <li><a href="errors.html">Errors</a></li> + </ul> + + </div> + </body> +</html> diff --git a/sflphone-common/doc/dbus-api/doc/templates/interface.html b/sflphone-common/doc/dbus-api/doc/templates/interface.html new file mode 100644 index 0000000000000000000000000000000000000000..79c35b201c8c6d001022567028311f38c8390dee --- /dev/null +++ b/sflphone-common/doc/dbus-api/doc/templates/interface.html @@ -0,0 +1,424 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE html PUBLIC "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" ""> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> + <head> + <title>$interface.name</title> + <link rel="stylesheet" href="style.css" type="text/css"/> + </head> + <body> + <div class="header"> + <h1>Interface $interface.name</h1> + <a href="index.html">Interface Index</a> + (<a href="interfaces.html">Compact</a>) + | <a href="#summary">Summary</a> + #if $interface.docstring: | <a href="#description">Description</a> + #if $interface.methods: | <a href="#methods">Methods</a> + #if $interface.signals: | <a href="#signals">Signals</a> + #if $interface.properties: | <a href="#properties">Properties</a> + #if $interface.tpproperties: | <a href="#tpproperties">Telepathy Properties</a> + #if $interface.contact_attributes: | <a href="#contact-attributes">Contact Attributes</a> + #if $interface.handler_capability_tokens: | <a href="#handler-capability-tokens">Handler Capability Tokens</a> + #if $interface.types: | <a href="#types">Types</a> + </div> + <div class="main"> + + #if $interface.methods or $interface.signals or $interface.properties or $interface.types or $interface.tpproperties + <div class="summary"> + <a name="summary"></a> + #if $interface.methods + <h3>Methods</h3> + <table class="summary"> + #for $method in $interface.methods + #if $method.deprecated + <tr class="deprecated"> + #else + <tr> + #end if + <td><a href="$method.get_url()">$method.short_name</a></td> + <td>($method.get_in_args())</td> + <td>→</td> + <td>$method.get_out_args()</td> + <td> + #if $method.deprecated: (deprecated) + </td> + </tr> + #end for + </table> + #end if + + #if $interface.signals + <h3>Signals</h3> + <table class="summary"> + #for $signal in $interface.signals + #if $signal.deprecated + <tr class="deprecated"> + #else + <tr> + #end if + <td><a href="$signal.get_url()">$signal.short_name</a></td> + <td>($signal.get_args())</td> + <td> + #if $signal.deprecated: (deprecated) + </td> + </tr> + #end for + </table> + #end if + + #if $interface.properties + <h3>Properties</h3> + <table class="summary"> + #for $property in $interface.properties + #if $property.deprecated + <tr class="deprecated"> + #else + <tr> + #end if + <td><a href="$property.get_url()">$property.short_name</a></td> + <td> + $property.dbus_type + #if $property.type: (<a href="$property.get_type_url()" title="$property.get_type_title()">$property.get_type().short_name</a>) + </td> + <td>$property.get_access()</td> + <td> + #if $property.deprecated: (deprecated) + </td> + </tr> + #end for + </table> + #end if + + #if $interface.tpproperties + <h3>Telepathy Properties</h3> + <table class="summary"> + #for $property in $interface.tpproperties + <tr class="deprecated"> + <td><a href="$property.get_url()">$property.short_name</a></td> + <td> + $property.dbus_type + #if $property.type: (<a href="$property.get_type_url()" title="$property.get_type_title()">$property.get_type().short_name</a>) + </td> + </tr> + #end for + </table> + #end if + + #if $interface.contact_attributes + <h3>Contact Attributes</h3> + <table class="summary"> + #for $token in $interface.contact_attributes + <tr class="contact-attribute"> + <td><a href="$token.get_url()">$token.name</a></td> + <td> + $token.dbus_type + #if $token.type: (<a href="$token.get_type_url()" title="$token.get_type_title()">$token.get_type().short_name</a>) + </td> + </tr> + #end for + </table> + #end if + + #if $interface.handler_capability_tokens + <h3>Handler Capability Tokens</h3> + <table class="summary"> + #for $token in $interface.handler_capability_tokens + <tr class="handler-capability-token"> + <td><a href="$token.get_url()">$token.name</a> + #if $token.is_family + (etc.) + #end if + </td> + <td> + </td> + </tr> + #end for + </table> + #end if + + #if $interface.types + <h3>Types</h3> + <table class="summary"> + #for $type in $interface.types + #if type.deprecated + <tr class="deprecated"> + #else + <tr> + #end if + <td><a href="$type.get_url()">$type.short_name</a></td> + <td>$type.get_type_name()</td> + <td>$type.dbus_type</td> + <td> + #if $type.deprecated: (deprecated) + </td> + </tr> + #end for + </table> + #end if + </div> + #end if + + #if $interface.causes_havoc + <div class="havoc"><span class="warning">WARNING:</span> + This interface is $interface.causes_havoc and is likely to cause havoc + to your API/ABI if bindings are generated. Do not include this interface + in libraries that care about compatibility. + </div> + #end if + $interface.get_added() + $interface.get_changed() + $interface.get_deprecated() + + #if $interface.requires + <div class="requires"> + Objects implementing this interface must also implement: + <ul> + #for $req in $interface.get_requires() + <li><a href="$req.get_url()" title="$req.get_title()">$req.name</a></li> + #end for + </ul> + </div> + #end if + + #if $interface.docstring + <a name="description"></a> + <h3>Description</h3> + $interface.get_docstring() + #end if + + #if $interface.methods + <div class="outset methods method"> + <a name="methods"></a> + <h1>Methods</h1> + #for $method in $interface.methods + <div class="inset method"> + <a name="$method.name"></a> + <span class="permalink">(<a href="$method.get_url()">Permalink</a>)</span> + <h2>$method.short_name ($method.get_in_args()) → $method.get_out_args()</h2> + + $method.get_added() + $method.get_changed() + $method.get_deprecated() + + #if $method.in_args + <div class="indent"> + <h3>Parameters</h3> + <ul> + #for $arg in $method.in_args + <li> + $arg.short_name — $arg.dbus_type + #if $arg.get_type(): (<a href="$arg.get_type_url()" title="$arg.get_type_title()">$arg.get_type().short_name</a>) + </li> + $arg.get_added() + $arg.get_changed() + $arg.get_deprecated() + $arg.get_docstring() + #end for + </ul> + </div> + #end if + + #if $method.out_args + <div class="indent"> + <h3>Returns</h3> + <ul> + #for $arg in $method.out_args + <li> + $arg.short_name — $arg.dbus_type + #if $arg.get_type(): (<a href="$arg.get_type_url()" title="$arg.get_type_title()">$arg.get_type().short_name</a>) + </li> + $arg.get_added() + $arg.get_changed() + $arg.get_deprecated() + $arg.get_docstring() + #end for + </ul> + </div> + #end if + + $method.get_docstring() + + #if $method.possible_errors + <hr/> + <div class="indent"> + <h3>Possible Errors</h3> + <ul> + #for $error in $method.possible_errors + <li><a href="$error.get_url()" title="$error.get_title()">$error.get_error().short_name</a></li> + $error.get_added() + $error.get_changed() + $error.get_deprecated() + $error.get_docstring() + #end for + </ul> + </div> + #end if + </div> + #end for + </div> + #end if + + #if $interface.signals + <div class="outset signals signal"> + <a name="signals"></a> + <h1>Signals</h1> + #for $signal in $interface.signals + <div class="inset signal"> + <a name="$signal.name"></a> + <span class="permalink">(<a href="$signal.get_url()">Permalink</a>)</span> + <h2>$signal.short_name ($signal.get_args())</h2> + + $signal.get_added() + $signal.get_changed() + $signal.get_deprecated() + + #if $signal.args + <div class="indent"> + <h3>Parameters</h3> + <ul> + #for $arg in $signal.args + <li> + $arg.short_name — $arg.dbus_type + #if $arg.get_type(): (<a href="$arg.get_type_url()" title="$arg.get_type_title()">$arg.get_type().short_name</a>) + </li> + $arg.get_added() + $arg.get_changed() + $arg.get_deprecated() + $arg.get_docstring() + #end for + </ul> + </div> + #end if + + $signal.get_docstring() + </div> + #end for + </div> + #end if + + #if $interface.properties + <div class="outset properties property"> + <a name="properties"></a> + <h1>Properties</h1> + <div> + Accessed using the org.freedesktop.DBus.Properties interface. + </div> + #for $property in $interface.properties + <div class="inset property"> + <a name="$property.name"></a> + <span class="permalink">(<a href="$property.get_url()">Permalink</a>)</span> + <h2> + $property.short_name — $property.dbus_type + #if $property.type: (<a href="$property.get_type_url()" title="$property.get_type_title()">$property.get_type().short_name</a>) + </h2> + <div class="access">$property.get_access()</div> + + $property.get_added() + $property.get_changed() + $property.get_deprecated() + $property.get_docstring() + </div> + #end for + </div> + #end if + + #if $interface.tpproperties + <div class="outset tpproperties tpproperty"> + <a name="tpproperties"></a> + <h1>Telepathy Properties</h1> + <div> + Accessed using the org.freedesktop.Telepathy.Properties interface. + </div> + #for $property in $interface.tpproperties + <div class="inset tpproperty"> + <a name="$property.name"></a> + <span class="permalink">(<a href="$property.get_url()">Permalink</a>)</span> + <h2> + $property.short_name — $property.dbus_type + #if $property.type: (<a href="$property.get_type_url()" title="$property.get_type_title()">$property.get_type().short_name</a>) + </h2> + $property.get_added() + $property.get_changed() + $property.get_deprecated() + $property.get_docstring() + </div> + #end for + </div> + #end if + + #if $interface.contact_attributes + <div class="outset contact-attributes"> + <a name="contact-attributes"></a> + <h1>Contact Attributes</h1> + <div> + Attributes that a contact can have, accessed with the + org.freedesktop.Telepathy.Connection.Interface.Contacts interface. + </div> + #for $token in $interface.contact_attributes + <div class="inset contact-attribute"> + <a name="$token.name"></a> + <span class="permalink">(<a href="$token.get_url()">Permalink</a>)</span> + <h2> + $token.name — $token.dbus_type + #if $token.type: (<a href="$token.get_type_url()" title="$token.get_type_title()">$token.get_type().short_name</a>) + </h2> + $token.get_added() + $token.get_changed() + $token.get_deprecated() + $token.get_docstring() + </div> + #end for + </div> + #end if + + #if $interface.handler_capability_tokens + <div class="outset handler-capability-tokens"> + <a name="handler-capability-tokens"></a> + <h1>Handler Capability Tokens</h1> + <div> + Tokens representing capabilities that a Client.Handler can have. + </div> + #for $token in $interface.handler_capability_tokens + <div class="inset handler-capability-token"> + <a name="$token.name"></a> + <span class="permalink">(<a href="$token.get_url()">Permalink</a>)</span> + <h2> + $token.name + #if $token.is_family + (etc.) + #end if + </h2> + $token.get_added() + $token.get_changed() + $token.get_deprecated() + $token.get_docstring() + </div> + #end for + </div> + #end if + + #if $interface.types + <div class="outset types type"> + <a name="types"></a> + <h1>Types</h1> + #for $type in $interface.types + <div class="inset type"> + <a name="$type.name"></a> + <span class="permalink">$type.get_type_name() (<a href="$type.get_url()">Permalink</a>)</span> + <h2> + $type.short_name — $type.dbus_type + </h2> + + $type.get_added() + $type.get_changed() + $type.get_deprecated() + $type.get_docstring() + $type.get_breakdown() + </div> + #end for + </div> + #end if + + </div> + + </body> +</html> diff --git a/sflphone-common/doc/dbus-api/doc/templates/interfaces.html b/sflphone-common/doc/dbus-api/doc/templates/interfaces.html new file mode 100644 index 0000000000000000000000000000000000000000..a93334c65de98f8e1a8933316778579d3e18d6a7 --- /dev/null +++ b/sflphone-common/doc/dbus-api/doc/templates/interfaces.html @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE html PUBLIC "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" ""> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> + <head> + <title>$spec.title &mdash v$spec.version</title> + <link rel="stylesheet" href="style.css" type="text/css"/> + </head> + <body> + <div class="header"> + <h1>$spec.title</h1> + <a href="index.html">Full</a> + | <a href="generic-types.html">Generic Types</a> + | <a href="errors.html">Errors</a> + | <a href="fullindex.html">Full Index</a> + </div> + + <div class="main"> + <b>Version $spec.version</b> + + <a name="interfaces"></a> + <h3>Interfaces</h3> + <ul> + #for $interface in $spec.interfaces + #if $interface.causes_havoc + <li class="causes-havoc"> + #elif $interface.deprecated + <li class="deprecated"> + #else + <li> + #end if + <a href="$interface.get_url()">$interface.name</a> + #if $interface.causes_havoc + (unstable) + #elif $interface.deprecated + (deprecated) + #end if + </li> + #end for + </ul> + + <a name="other"></a> + <h3>Other</h3> + <ul> + <li><a href="generic-types.html">Generic Types</a></li> + <li><a href="errors.html">Errors</a></li> + </ul> + + </div> + </body> +</html> diff --git a/sflphone-common/doc/dbus-api/doc/templates/style.css b/sflphone-common/doc/dbus-api/doc/templates/style.css new file mode 100644 index 0000000000000000000000000000000000000000..979ced8caee61b00d127e83feb7c5576fbf1c191 --- /dev/null +++ b/sflphone-common/doc/dbus-api/doc/templates/style.css @@ -0,0 +1,237 @@ +html, body, +h1, h2 { + font-family: "Georgia"; + margin: 0; + padding: 0; +} + +h3 { + margin-top: 2pt; + margin-bottom: 2pt; +} + +ul { + margin: 1ex; + margin-left: 1.5em; + padding: 0; +} + +hr { + border-style: none; + color: #cccccc; + background-color: #cccccc; + height: 1px; +} + +div.header { + position: fixed; + height: 4em; + background-color: AliceBlue; + width: 100%; + margin: 0; + padding: 0.5ex; + border-bottom: 1px solid black; + top: 0; + left: 0; + z-index: 1; +} + +div.header h1 { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} + +div.main { + margin-top: 5em; + margin-left: 1ex; + margin-right: 1ex; + margin-bottom: 1ex; +} + +div.main a[name] { + position: relative; + top: -4.5em; +} + +div.outset { + padding: 1ex; + margin-top: 1ex; + margin-bottom: 1ex; +} + +div.inset { + background-color: white; + margin-top: 1ex; + margin-bottom: 1ex; + padding: 0.5ex; +} + +div.indent { + margin-left: 1em; +} + +div.methods { + background-color: #fcaf3e; +} + +div.method { + border: 1px solid #f57900; +} + +div.signals { + background-color: #729fcf; +} + +div.signal { + border: 1px solid #3465a4; +} + +div.properties { + background-color: #ad7fa8; +} + +div.property { + border: 1px solid #75507b; +} + +div.tpproperties { + background-color: #999999; +} + +div.tpproperty { + border: 1px solid #333333; +} + +div.contact-attributes { + background-color: #ccccff; + border: 1px solid #9999cc; +} + +div.contact-attribute { + border: 1px solid #9999cc; +} + +div.handler-capability-tokens { + background-color: #339933; + border: 1px solid #228822; +} + +div.handler-capability-token { + border: 1px solid #228822; +} + +div.types { + background-color: #e9b96e; +} + +div.type { + border: 1px solid #c17d11; +} + +div.errors { + background-color: #ef2929; +} + +div.error { + border: 1px solid #cc0000; +} + +div.access { + font-weight: bold; + margin-left: 1ex; +} + +div.summary { + padding: 0.5ex; + background-color: #eeeeec; + border: 1px solid #d3d7cf; +} + +table.summary { + margin: 1ex; + font-size: small; +} + +table.summary td { + padding-right: 1ex; +} + +li.chapter { + margin-top: 1ex; + font-weight: bold; +} + +li.causes-havoc { + font-style: italic; +} + +li.deprecated, +li.deprecated a, +table.summary tr.deprecated td, +table.summary tr.deprecated td a { + color: gray; +} + +div.requires, +div.docstring { + margin: 1ex; +} + +div.added { + border-left: 2px solid #4e9a06; + margin: 1ex; + padding-left: 1ex; +} + +div.added span.version { + color: #4e9a06; + font-weight: bold; +} + +div.changed { + border-left: 2px solid #8f5902; + margin: 1ex; + padding-left: 1ex; +} + +div.changed span.version { + color: #8f5902; + font-weight: bold; +} + +div.deprecated, +div.havoc { + border-left: 2px solid #a40000; + margin: 1ex; + padding-left: 1ex; +} + +div.deprecated span.version, +span.warning { + color: #a40000; + font-weight: bold; +} + +div.rationale { + border-left: 2px solid gray; + margin: 1ex; + padding-left: 1ex; +} + +span.permalink { + float: right; + font-size: x-small; +} + +.license { + clear: both; + border: 1px solid #dedede; + font-style: italic; + padding: 15px; +} + +.copyrights { + clear: both; + float: right; +} diff --git a/sflphone-common/doc/dbus-api/spec/all.xml b/sflphone-common/doc/dbus-api/spec/all.xml new file mode 100644 index 0000000000000000000000000000000000000000..b87a0e1e41083510f2666fdb62b8c339087eef61 --- /dev/null +++ b/sflphone-common/doc/dbus-api/spec/all.xml @@ -0,0 +1,55 @@ +<tp:spec + xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" + xmlns:xi="http://www.w3.org/2001/XInclude"> + +<tp:title>SFLphone D-Bus Interface Specification</tp:title> +<tp:version>0.9.8</tp:version> + +<tp:copyright>Copyright © 2005-2010 Savoir-faire Linux Inc</tp:copyright> + +<tp:license xmlns="http://www.w3.org/1999/xhtml"> +<p>This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version.</p> + +<p>This library 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 +Lesser General Public License for more details.</p> + +<p>You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p> +</tp:license> + +<tp:section name="Instances Manager"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p> + An Instance Manager to handle multiple clients connections. Count the number of clients actually registered to the core. When initializing your client, you need to register it against the core by using this interface. + </p> + </tp:docstring> + <xi:include href="instance-introspec.xml"/> +</tp:section> + +<tp:section name="Call Manager"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p> + A Call Manager to handle call-related features. + </p> + </tp:docstring> + <xi:include href="callmanager-introspec.xml"/> +</tp:section> + +<tp:section name="Configuration Manager"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p> + A Configuration Manager to handle account configuration, user preferences, ... + </p> + </tp:docstring> + <xi:include href="configurationmanager-introspec.xml"/> +</tp:section> + +<xi:include href="generic-types.xml"/> + +</tp:spec> diff --git a/sflphone-common/doc/dbus-api/spec/callmanager-introspec.xml b/sflphone-common/doc/dbus-api/spec/callmanager-introspec.xml new file mode 120000 index 0000000000000000000000000000000000000000..2150eca25d2f7405bf1f7c8684247457538207c6 --- /dev/null +++ b/sflphone-common/doc/dbus-api/spec/callmanager-introspec.xml @@ -0,0 +1 @@ +../../../src/dbus/callmanager-introspec.xml \ No newline at end of file diff --git a/sflphone-common/doc/dbus-api/spec/configurationmanager-introspec.xml b/sflphone-common/doc/dbus-api/spec/configurationmanager-introspec.xml new file mode 120000 index 0000000000000000000000000000000000000000..d340519f1a8287c927fa3e8c516b256438dc2a63 --- /dev/null +++ b/sflphone-common/doc/dbus-api/spec/configurationmanager-introspec.xml @@ -0,0 +1 @@ +../../../src/dbus/configurationmanager-introspec.xml \ No newline at end of file diff --git a/sflphone-common/doc/dbus-api/spec/errors.xml b/sflphone-common/doc/dbus-api/spec/errors.xml new file mode 100644 index 0000000000000000000000000000000000000000..22a629baff276dbeb4439352acb7df7a90b319be --- /dev/null +++ b/sflphone-common/doc/dbus-api/spec/errors.xml @@ -0,0 +1,417 @@ +<?xml version="1.0" ?> +<tp:errors xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" namespace="org.freedesktop.Telepathy.Error"> + <tp:error name="Network Error"> + <tp:docstring> + Raised when there is an error reading from or writing to the network. + </tp:docstring> + </tp:error> + + <tp:error name="Not Implemented"> + <tp:docstring> + Raised when the requested method, channel, etc is not available on this connection. + </tp:docstring> + </tp:error> + + <tp:error name="Invalid Argument"> + <tp:docstring> + Raised when one of the provided arguments is invalid. + </tp:docstring> + </tp:error> + + <tp:error name="Not Available"> + <tp:docstring> + Raised when the requested functionality is temporarily unavailable. + </tp:docstring> + </tp:error> + + <tp:error name="Permission Denied"> + <tp:docstring> + The user is not permitted to perform the requested operation. + </tp:docstring> + </tp:error> + + <tp:error name="Disconnected"> + <tp:docstring> + The connection is not currently connected and cannot be used. + This error may also be raised when operations are performed on a + Connection for which + <tp:dbus-ref namespace="org.freedesktop.Telepathy.Connection">StatusChanged</tp:dbus-ref> + has signalled status Disconnected for reason None. + + <tp:rationale> + The second usage corresponds to None in the + <tp:type>Connection_Status_Reason</tp:type> enum; if a better reason + is available, the corresponding error should be used instead. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Invalid Handle"> + <tp:docstring> + The handle specified is unknown on this channel or connection. + </tp:docstring> + </tp:error> + + <tp:error name="Channel.Banned"> + <tp:docstring> + You are banned from the channel. + </tp:docstring> + </tp:error> + + <tp:error name="Channel.Full"> + <tp:docstring> + The channel is full. + </tp:docstring> + </tp:error> + + <tp:error name="Channel.Invite Only"> + <tp:docstring> + The requested channel is invite-only. + </tp:docstring> + </tp:error> + + <tp:error name="Not Yours"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>The requested channel or other resource already exists, and another + user interface in this session is responsible for it.</p> + + <p>User interfaces SHOULD handle this error unobtrusively, since it + indicates that some other user interface is already processing the + channel.</p> + </tp:docstring> + </tp:error> + + <tp:error name="Cancelled"> + <tp:docstring> + Raised by an ongoing request if it is cancelled by user request before + it has completed, or when operations are performed on an object which + the user has asked to close (for instance, a Connection where the user + has called Disconnect, or a Channel where the user has called Close). + + <tp:rationale> + The second form can be used to correspond to the Requested member in + the <tp:type>Connection_Status_Reason</tp:type> enum, or to + to represent the situation where disconnecting a Connection, + closing a Channel, etc. has been requested by the user but this + request has not yet been acted on, for instance because the + service will only act on the request when it has finished processing + an event queue. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Authentication Failed"> + <tp:docstring> + Raised when authentication with a service was unsuccessful. + <tp:rationale> + This corresponds to Authentication_Failed in the + <tp:type>Connection_Status_Reason</tp:type> enum. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Encryption Not Available"> + <tp:docstring> + Raised if a user request insisted that encryption should be used, + but encryption was not actually available. + + <tp:rationale> + This corresponds to part of Encryption_Error in the + <tp:type>Connection_Status_Reason</tp:type> enum. It's been separated + into a distinct error here because the two concepts that were part + of EncryptionError seem to be things that could reasonably appear + differently in the UI. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Encryption Error"> + <tp:docstring> + Raised if encryption appears to be available, but could not actually be + used (for instance if SSL/TLS negotiation fails). + <tp:rationale> + This corresponds to part of Encryption_Error in the + <tp:type>Connection_Status_Reason</tp:type> enum. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Cert.Not Provided"> + <tp:docstring> + Raised if the server did not provide a SSL/TLS certificate. This error + MUST NOT be used to represent the absence of a client certificate + provided by the Telepathy connection manager. + <tp:rationale> + This corresponds to Cert_Not_Provided in the + <tp:type>Connection_Status_Reason</tp:type> enum. That error + explicitly applied only to server SSL certificates, so this one + is similarly limited; having the CM present a client certificate + is a possible future feature, but it should have its own error + handling. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Cert.Untrusted"> + <tp:docstring> + Raised if the server provided a SSL/TLS certificate signed by an + untrusted certifying authority. This error SHOULD NOT be used to + represent a self-signed certificate: see the Self Signed error for that. + <tp:rationale> + This corresponds to Cert_Untrusted in the + <tp:type>Connection_Status_Reason</tp:type> enum, with a clarification + to avoid ambiguity. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Cert.Expired"> + <tp:docstring> + Raised if the server provided an expired SSL/TLS certificate. + <tp:rationale> + This corresponds to Cert_Expired in the + <tp:type>Connection_Status_Reason</tp:type> enum. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Cert.Not Activated"> + <tp:docstring> + Raised if the server provided an SSL/TLS certificate that will become + valid at some point in the future. + <tp:rationale> + This corresponds to Cert_Not_Activated in the + <tp:type>Connection_Status_Reason</tp:type> enum. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Cert.Fingerprint Mismatch"> + <tp:docstring> + Raised if the server provided an SSL/TLS certificate that did not have + the expected fingerprint. + <tp:rationale> + This corresponds to Cert_Fingerprint_Mismatch in the + <tp:type>Connection_Status_Reason</tp:type> enum. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Cert.Hostname Mismatch"> + <tp:docstring> + Raised if the server provided an SSL/TLS certificate that did not match + its hostname. + <tp:rationale> + This corresponds to Cert_Hostname_Mismatch in the + <tp:type>Connection_Status_Reason</tp:type> enum. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Cert.Self Signed"> + <tp:docstring> + Raised if the server provided an SSL/TLS certificate that is self-signed + and untrusted. + <tp:rationale> + This corresponds to Cert_Hostname_Mismatch in the + <tp:type>Connection_Status_Reason</tp:type> enum. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Cert.Invalid"> + <tp:docstring> + Raised if the server provided an SSL/TLS certificate that is + unacceptable in some way that does not have a more specific error. + <tp:rationale> + This corresponds to Cert_Other_Error in the + <tp:type>Connection_Status_Reason</tp:type> enum. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Not Capable"> + <tp:docstring> + Raised when requested functionality is unavailable due to contact + not having required capabilities. + </tp:docstring> + </tp:error> + + <tp:error name="Offline"> + <tp:docstring> + Raised when requested functionality is unavailable because a contact is + offline. + + <tp:rationale> + This corresponds to Offline in the + <tp:type>Channel_Group_Change_Reason</tp:type> enum. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Channel.Kicked"> + <tp:docstring> + Used to represent a user being ejected from a channel by another user, + for instance being kicked from a chatroom. + + <tp:rationale> + This corresponds to Kicked in the + <tp:type>Channel_Group_Change_Reason</tp:type> enum. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Busy"> + <tp:docstring> + Used to represent a user being removed from a channel because of a + "busy" indication. This error SHOULD NOT be used to represent a server + or other infrastructure being too busy to process a request - for that, + see ServerBusy. + + <tp:rationale> + This corresponds to Busy in the + <tp:type>Channel_Group_Change_Reason</tp:type> enum. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="No Answer"> + <tp:docstring> + Used to represent a user being removed from a channel because they did + not respond, e.g. to a StreamedMedia call. + + <tp:rationale> + This corresponds to No_Answer in the + <tp:type>Channel_Group_Change_Reason</tp:type> enum. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Does Not Exist"> + <tp:docstring> + Raised when the requested user does not, in fact, exist. + + <tp:rationale> + This corresponds to Invalid_Contact in the + <tp:type>Channel_Group_Change_Reason</tp:type> enum, but can also be + used to represent other things not existing (like chatrooms, perhaps). + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Terminated"> + <tp:docstring> + Raised when a channel is terminated for an unspecified reason. In + particular, this error SHOULD be used whenever normal termination of + a 1-1 StreamedMedia call by the remote user is represented as a D-Bus + error name. + + <tp:rationale> + This corresponds to None in the + <tp:type>Channel_Group_Change_Reason</tp:type> enum. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Connection Refused"> + <tp:docstring> + Raised when a connection is refused. + </tp:docstring> + </tp:error> + + <tp:error name="Connection Failed"> + <tp:docstring> + Raised when a connection can't be established. + </tp:docstring> + </tp:error> + + <tp:error name="Connection Lost"> + <tp:docstring> + Raised when a connection is broken. + </tp:docstring> + </tp:error> + + <tp:error name="Already Connected"> + <tp:docstring> + Raised when the user attempts to connect to an account but they are + already connected (perhaps from another client or computer), and the + protocol or account settings do not allow this. + + <tp:rationale> + XMPP can have this behaviour if the user chooses the same resource + in both clients (it is server-dependent whether the result is + AlreadyConnected on the new connection, ConnectionReplaced on the + old connection, or two successful connections). + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Connection Replaced"> + <tp:docstring> + Raised by an existing connection to an account if it is replaced by + a new connection (perhaps from another client or computer). + + <tp:rationale> + In MSNP, when connecting twice with the same Passport, the new + connection "wins" and the old one is automatically disconnected. + XMPP can also have this behaviour if the user chooses the same + resource in two clients (it is server-dependent whether the result is + AlreadyConnected on the new connection, ConnectionReplaced on the + old connection, or two successful connections). + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Registration Exists"> + <tp:docstring> + Raised during in-band registration if the server indicates that the + requested account already exists. + </tp:docstring> + </tp:error> + + <tp:error name="Service Busy"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + Raised if a server or some other piece of infrastructure cannot process + the request, e.g. due to resource limitations. Clients MAY try again + later. + + <tp:rationale> + This is not the same error as Busy, which indicates that a + <em>user</em> is busy. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:error name="Resource Unavailable"> + <tp:docstring> + Raised if a request cannot be satisfied because a process local to the + user has insufficient resources. Clients MAY try again + later. + + <tp:rationale> + For instance, the <tp:dbus-ref + namespace="org.freedesktop.Telepathy">ChannelDispatcher</tp:dbus-ref> + might raise this error for some or all channel requests if it has + detected that there is not enough free memory. + </tp:rationale> + </tp:docstring> + </tp:error> + + <tp:copyright>Copyright © 2005-2009 Collabora Limited</tp:copyright> + <tp:copyright>Copyright © 2005-2009 Nokia Corporation</tp:copyright> + <tp:license xmlns="http://www.w3.org/1999/xhtml"> +<p>This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version.</p> + +<p>This library 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 +Lesser General Public License for more details.</p> + +<p>You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p> + </tp:license> +</tp:errors> diff --git a/sflphone-common/doc/dbus-api/spec/generic-types.xml b/sflphone-common/doc/dbus-api/spec/generic-types.xml new file mode 100644 index 0000000000000000000000000000000000000000..d4dce1552dcaaf6fa37f61ffd499dfcb03ea49e8 --- /dev/null +++ b/sflphone-common/doc/dbus-api/spec/generic-types.xml @@ -0,0 +1,168 @@ +<tp:generic-types + xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> + + <tp:simple-type name="Unix_Timestamp" type="u"> + <tp:docstring>An unsigned 32-bit integer representing time as the number + of seconds elapsed since the Unix epoch + (1970-01-01T00:00:00Z)</tp:docstring> + </tp:simple-type> + + <tp:simple-type name="Unix_Timestamp64" type="x"> + <tp:docstring>An signed 64-bit integer representing time as the number + of seconds elapsed since the Unix epoch + (1970-01-01T00:00:00Z); negative for times before the epoch</tp:docstring> + + <tp:rationale>The Text interface is the only user of Unix_Timestamp so + far, and we'd like to be Y2038 compatible in future + interfaces.</tp:rationale> + </tp:simple-type> + + <tp:simple-type name="DBus_Bus_Name" type="s" + array-name="DBus_Bus_Name_List"> + <tp:docstring>A string representing a D-Bus bus name - either a well-known + name like "org.freedesktop.Telepathy.MissionControl" or a unique name + like ":1.123"</tp:docstring> + </tp:simple-type> + + <tp:simple-type name="DBus_Well_Known_Name" type="s" + array-name="DBus_Well_Known_Name_List"> + <tp:docstring>A string representing a D-Bus well-known + name like "org.freedesktop.Telepathy.MissionControl".</tp:docstring> + </tp:simple-type> + + <tp:simple-type name="DBus_Unique_Name" type="s" + array-name="DBus_Unique_Name_List"> + <tp:docstring>A string representing a D-Bus unique name, such as + ":1.123"</tp:docstring> + </tp:simple-type> + + <tp:simple-type name="DBus_Interface" type="s" + array-name="DBus_Interface_List"> + <tp:docstring>An ASCII string representing a D-Bus interface - two or more + elements separated by dots, where each element is a non-empty + string of ASCII letters, digits and underscores, not starting with + a digit. The maximum total length is 255 characters. For example, + "org.freedesktop.DBus.Peer".</tp:docstring> + </tp:simple-type> + + <tp:simple-type name="DBus_Error_Name" type="s"> + <tp:docstring>An ASCII string representing a D-Bus error. This is + syntactically the same as a <tp:type>DBus_Interface</tp:type>, but the + meaning is different.</tp:docstring> + </tp:simple-type> + + <tp:simple-type name="DBus_Signature" type="s"> + <tp:docstring>A string representing a D-Bus signature + (the 'g' type isn't used because of poor interoperability, particularly + with dbus-glib)</tp:docstring> + </tp:simple-type> + + <tp:simple-type name="DBus_Member" type="s"> + <tp:docstring>An ASCII string representing a D-Bus method, signal + or property name - a non-empty string of ASCII letters, digits and + underscores, not starting with a digit, with a maximum length of 255 + characters. For example, "Ping".</tp:docstring> + </tp:simple-type> + + <tp:simple-type name="DBus_Qualified_Member" type="s" + array-name="DBus_Qualified_Member_List"> + <tp:docstring>A string representing the full name of a D-Bus method, + signal or property, consisting of a DBus_Interface, followed by + a dot, followed by a DBus_Member. For example, + "org.freedesktop.DBus.Peer.Ping".</tp:docstring> + </tp:simple-type> + + <tp:mapping name="Qualified_Property_Value_Map" + array-name="Qualified_Property_Value_Map_List"> + <tp:docstring>A mapping from strings representing D-Bus + properties (by their namespaced names) to their values.</tp:docstring> + <tp:member type="s" name="Key" tp:type="DBus_Qualified_Member"> + <tp:docstring> + A D-Bus interface name, followed by a dot and a D-Bus property name. + </tp:docstring> + </tp:member> + <tp:member type="v" name="Value"> + <tp:docstring> + The value of the property. + </tp:docstring> + </tp:member> + </tp:mapping> + + <tp:mapping name="String_Variant_Map" array-name="String_Variant_Map_List"> + <tp:docstring>A mapping from strings to variants representing extra + key-value pairs.</tp:docstring> + <tp:member type="s" name="Key"/> + <tp:member type="v" name="Value"/> + </tp:mapping> + + <tp:mapping name="String_String_Map" array-name="String_String_Map_List"> + <tp:docstring>A mapping from strings to strings representing extra + key-value pairs.</tp:docstring> + <tp:member type="s" name="Key"/> + <tp:member type="s" name="Value"/> + </tp:mapping> + + <tp:struct name="Socket_Address_IP" array-name="Socket_Address_IP_List"> + <tp:docstring>An IP address and port.</tp:docstring> + <tp:member type="s" name="Address"> + <tp:docstring>Either a dotted-quad IPv4 address literal as for + <tp:type>Socket_Address_IPv4</tp:type>, or an RFC2373 IPv6 address + as for <tp:type>Socket_Address_IPv6</tp:type>. + </tp:docstring> + </tp:member> + <tp:member type="q" name="Port"> + <tp:docstring>The TCP or UDP port number.</tp:docstring> + </tp:member> + </tp:struct> + + <tp:struct name="Socket_Address_IPv4"> + <tp:docstring>An IPv4 address and port.</tp:docstring> + <tp:member type="s" name="Address"> + <tp:docstring>A dotted-quad IPv4 address literal: four ASCII decimal + numbers, each between 0 and 255 inclusive, e.g. + "192.168.0.1".</tp:docstring> + </tp:member> + <tp:member type="q" name="Port"> + <tp:docstring>The TCP or UDP port number.</tp:docstring> + </tp:member> + </tp:struct> + + <tp:struct name="Socket_Address_IPv6"> + <tp:docstring>An IPv6 address and port.</tp:docstring> + <tp:member type="s" name="Address"> + <tp:docstring>An IPv6 address literal as specified by RFC2373 + section 2.2, e.g. "2001:DB8::8:800:200C:4171".</tp:docstring> + </tp:member> + <tp:member type="q" name="Port"> + <tp:docstring>The TCP or UDP port number.</tp:docstring> + </tp:member> + </tp:struct> + + <tp:struct name="Socket_Netmask_IPv4"> + <tp:docstring>An IPv4 network or subnet.</tp:docstring> + <tp:member type="s" name="Address"> + <tp:docstring>A dotted-quad IPv4 address literal: four ASCII decimal + numbers, each between 0 and 255 inclusive, e.g. + "192.168.0.1".</tp:docstring> + </tp:member> + <tp:member type="y" name="Prefix_Length"> + <tp:docstring>The number of leading bits of the address that must + match, for this netmask to be considered to match an + address.</tp:docstring> + </tp:member> + </tp:struct> + + <tp:struct name="Socket_Netmask_IPv6"> + <tp:docstring>An IPv6 network or subnet.</tp:docstring> + <tp:member type="s" name="Address"> + <tp:docstring>An IPv6 address literal as specified by RFC2373 + section 2.2, e.g. "2001:DB8::8:800:200C:4171".</tp:docstring> + </tp:member> + <tp:member type="y" name="Prefix_Length"> + <tp:docstring>The number of leading bits of the address that must + match, for this netmask to be considered to match an + address.</tp:docstring> + </tp:member> + </tp:struct> + +</tp:generic-types> diff --git a/sflphone-common/doc/dbus-api/spec/instance-introspec.xml b/sflphone-common/doc/dbus-api/spec/instance-introspec.xml new file mode 120000 index 0000000000000000000000000000000000000000..2e02dfe7239982ae1df5ef975ddacafb9897839a --- /dev/null +++ b/sflphone-common/doc/dbus-api/spec/instance-introspec.xml @@ -0,0 +1 @@ +../../../src/dbus/instance-introspec.xml \ No newline at end of file diff --git a/sflphone-common/doc/dbus-api/tools/devhelp.xsl b/sflphone-common/doc/dbus-api/tools/devhelp.xsl new file mode 100644 index 0000000000000000000000000000000000000000..60f9e1c5304f68e8db9c6cb0cefc7db78d04398d --- /dev/null +++ b/sflphone-common/doc/dbus-api/tools/devhelp.xsl @@ -0,0 +1,91 @@ +<!-- Generate a Devhelp index from the Telepathy specification. +The master copy of this stylesheet is in the Telepathy spec repository - +please make any changes there. + +Copyright (C) 2006-2008 Collabora Limited + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +--> + +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> + <xsl:template match="/"> + <book xmlns="http://www.devhelp.net/book" title="Telepathy Specification" + name="telepathy-spec" link="spec.html"> + <xsl:text>
</xsl:text> + <chapters> + <xsl:text>
</xsl:text> + <xsl:apply-templates select="//interface" /> + </chapters> + <xsl:text>
</xsl:text> + <functions> + <xsl:text>
</xsl:text> + <xsl:apply-templates select="//method" /> + <xsl:apply-templates select="//signal" /> + <xsl:apply-templates select="//property" /> + <xsl:apply-templates select="//tp:enum" /> + <xsl:apply-templates select="//tp:simple-type" /> + <xsl:apply-templates select="//tp:mapping" /> + <xsl:apply-templates select="//tp:flags" /> + <xsl:apply-templates select="//tp:struct" /> + </functions> + <xsl:text>
</xsl:text> + </book> + </xsl:template> + + <xsl:template match="interface"> + <xsl:text> </xsl:text> + <sub xmlns="http://www.devhelp.net/book" name="{@name}" + link="{concat('spec.html#', @name)}" /> + <xsl:text>
</xsl:text> + </xsl:template> + + <xsl:template match="method"> + <xsl:text> </xsl:text> + <keyword type="function" xmlns="http://www.devhelp.net/book" name="{@name}" + link="spec.html#{../@name}.{@name}" /> + <xsl:text>
</xsl:text> + </xsl:template> + + <xsl:template match="signal | property"> + <xsl:text> </xsl:text> + <keyword type="" xmlns="http://www.devhelp.net/book" name="{@name}" + link="spec.html#{../@name}.{@name}" /> + <xsl:text>
</xsl:text> + </xsl:template> + + <xsl:template match="tp:simple-type"> + <xsl:text> </xsl:text> + <keyword type="typedef" xmlns="http://www.devhelp.net/book" name="{@name}" + link="spec.html#type-{@name}" /> + <xsl:text>
</xsl:text> + </xsl:template> + + <xsl:template match="tp:enum | tp:flags"> + <xsl:text> </xsl:text> + <keyword type="enum" xmlns="http://www.devhelp.net/book" name="{@name}" + link="spec.html#type-{@name}" /> + <xsl:text>
</xsl:text> + </xsl:template> + + <xsl:template match="tp:mapping | tp:struct"> + <xsl:text> </xsl:text> + <keyword type="struct" xmlns="http://www.devhelp.net/book" name="{@name}" + link="spec.html#type-{@name}" /> + <xsl:text>
</xsl:text> + </xsl:template> + +</xsl:stylesheet> diff --git a/sflphone-common/doc/dbus-api/tools/doc-generator.py b/sflphone-common/doc/dbus-api/tools/doc-generator.py new file mode 100755 index 0000000000000000000000000000000000000000..5fc19ce907435806cabd31baa75b05f0a9b76d82 --- /dev/null +++ b/sflphone-common/doc/dbus-api/tools/doc-generator.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python +# +# doc-generator.py +# +# Generates HTML documentation from the parsed spec using Cheetah templates. +# +# Copyright (C) 2009 Collabora Ltd. +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or (at +# your option) any later version. +# +# This library 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 Lesser General Public License +# for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# Authors: Davyd Madeley <davyd.madeley@collabora.co.uk> +# + +import sys +import os +import os.path +import shutil + +try: + from Cheetah.Template import Template +except ImportError, e: + print >> sys.stderr, e + print >> sys.stderr, "Install `python-cheetah'?" + sys.exit(-1) + +import specparser + +program, spec_file, output_path, project, namespace = sys.argv + +template_path = os.path.join(os.path.dirname(program), '../doc/templates') + +# make the output path +try: + os.mkdir(output_path) +except OSError: + pass +# copy in the CSS +shutil.copy(os.path.join(template_path, 'style.css'), output_path) + +def load_template(filename): + try: + file = open(os.path.join(template_path, filename)) + template_def = file.read() + file.close() + except IOError, e: + print >> sys.stderr, "Could not load template file `%s'" % filename + print >> sys.stderr, e + sys.exit(-1) + + return template_def + +spec = specparser.parse(spec_file, namespace) + +# write out HTML files for each of the interfaces + +# Not using render_template here to avoid recompiling it n times. +namespace = {} +template_def = load_template('interface.html') +t = Template(template_def, namespaces = [namespace]) +for interface in spec.interfaces: + namespace['interface'] = interface + + # open the output file + out = open(os.path.join(output_path, '%s.html' % interface.name), 'w') + print >> out, unicode(t).encode('utf-8') + out.close() + +def render_template(name, namespaces, target=None): + if target is None: + target = name + + namespace = { 'spec': spec } + template_def = load_template(name) + t = Template(template_def, namespaces=namespaces) + out = open(os.path.join(output_path, target), 'w') + print >> out, unicode(t).encode('utf-8') + out.close() + +namespaces = { 'spec': spec } + +render_template('generic-types.html', namespaces) +render_template('errors.html', namespaces) +render_template('interfaces.html', namespaces) +render_template('fullindex.html', namespaces) + +dh_namespaces = { 'spec': spec, 'name': project } +render_template('devhelp.devhelp2', dh_namespaces, + target=('%s.devhelp2' % project)) + +# write out the TOC last, because this is the file used as the target in the +# Makefile. +render_template('index.html', namespaces) diff --git a/sflphone-common/doc/dbus-api/tools/doc-generator.xsl b/sflphone-common/doc/dbus-api/tools/doc-generator.xsl new file mode 100644 index 0000000000000000000000000000000000000000..fe9cd9f08d193606f37f41259cb75601b431602f --- /dev/null +++ b/sflphone-common/doc/dbus-api/tools/doc-generator.xsl @@ -0,0 +1,1266 @@ +<!-- Generate HTML documentation from the Telepathy specification. +The master copy of this stylesheet is in the Telepathy spec repository - +please make any changes there. + +Copyright (C) 2006-2008 Collabora Limited + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +--> + +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" + xmlns:html="http://www.w3.org/1999/xhtml" + exclude-result-prefixes="tp html"> + <!--Don't move the declaration of the HTML namespace up here — XMLNSs + don't work ideally in the presence of two things that want to use the + absence of a prefix, sadly. --> + + <xsl:param name="allow-undefined-interfaces" select="false()"/> + + <xsl:template match="html:* | @*" mode="html"> + <xsl:copy> + <xsl:apply-templates mode="html" select="@*|node()"/> + </xsl:copy> + </xsl:template> + + <xsl:template match="tp:type" mode="html"> + <xsl:call-template name="tp-type"> + <xsl:with-param name="tp-type" select="string(.)"/> + </xsl:call-template> + </xsl:template> + + <!-- tp:dbus-ref: reference a D-Bus interface, signal, method or property --> + <xsl:template match="tp:dbus-ref" mode="html"> + <xsl:variable name="name"> + <xsl:choose> + <xsl:when test="@namespace"> + <xsl:value-of select="@namespace"/> + <xsl:text>.</xsl:text> + </xsl:when> + </xsl:choose> + <xsl:value-of select="string(.)"/> + </xsl:variable> + + <xsl:choose> + <xsl:when test="//interface[@name=$name] + or //interface/method[concat(../@name, '.', @name)=$name] + or //interface/signal[concat(../@name, '.', @name)=$name] + or //interface/property[concat(../@name, '.', @name)=$name] + or //interface[@name=concat($name, '.DRAFT')] + or //interface/method[ + concat(../@name, '.', @name)=concat($name, '.DRAFT')] + or //interface/signal[ + concat(../@name, '.', @name)=concat($name, '.DRAFT')] + or //interface/property[ + concat(../@name, '.', @name)=concat($name, '.DRAFT')] + "> + <a xmlns="http://www.w3.org/1999/xhtml" href="#{$name}"> + <xsl:value-of select="string(.)"/> + </a> + </xsl:when> + + <xsl:when test="$allow-undefined-interfaces"> + <span xmlns="http://www.w3.org/1999/xhtml" title="defined elsewhere"> + <xsl:value-of select="string(.)"/> + </span> + </xsl:when> + + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: cannot find D-Bus interface, method, </xsl:text> + <xsl:text>signal or property called '</xsl:text> + <xsl:value-of select="$name"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- tp:member-ref: reference a property of the current interface --> + <xsl:template match="tp:member-ref" mode="html"> + <xsl:variable name="prefix" select="concat(ancestor::interface/@name, + '.')"/> + <xsl:variable name="name" select="string(.)"/> + + <xsl:if test="not(ancestor::interface)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: Cannot use tp:member-ref when not in an</xsl:text> + <xsl:text> <interface> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:choose> + <xsl:when test="ancestor::interface/signal[@name=$name]"/> + <xsl:when test="ancestor::interface/method[@name=$name]"/> + <xsl:when test="ancestor::interface/property[@name=$name]"/> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: interface </xsl:text> + <xsl:value-of select="ancestor::interface/@name"/> + <xsl:text> has no signal/method/property called </xsl:text> + <xsl:value-of select="$name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + + <a xmlns="http://www.w3.org/1999/xhtml" href="#{$prefix}{$name}"> + <xsl:value-of select="$name"/> + </a> + </xsl:template> + + <xsl:template match="*" mode="identity"> + <xsl:copy> + <xsl:apply-templates mode="identity"/> + </xsl:copy> + </xsl:template> + + <xsl:template match="tp:docstring"> + <xsl:apply-templates mode="html"/> + </xsl:template> + + <xsl:template match="tp:added"> + <p class="added" xmlns="http://www.w3.org/1999/xhtml">Added in + version <xsl:value-of select="@version"/>. + <xsl:apply-templates select="node()" mode="html"/></p> + </xsl:template> + + <xsl:template match="tp:changed"> + <xsl:choose> + <xsl:when test="node()"> + <p class="changed" xmlns="http://www.w3.org/1999/xhtml">Changed in + version <xsl:value-of select="@version"/>: + <xsl:apply-templates select="node()" mode="html"/></p> + </xsl:when> + <xsl:otherwise> + <p class="changed">Changed in version + <xsl:value-of select="@version"/></p> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="tp:deprecated"> + <p class="deprecated" xmlns="http://www.w3.org/1999/xhtml">Deprecated + since version <xsl:value-of select="@version"/>. + <xsl:apply-templates select="node()" mode="html"/></p> + </xsl:template> + + <xsl:template match="tp:rationale" mode="html"> + <div xmlns="http://www.w3.org/1999/xhtml" class="rationale"> + <xsl:apply-templates select="node()" mode="html"/> + </div> + </xsl:template> + + <xsl:template match="tp:errors"> + <h1 xmlns="http://www.w3.org/1999/xhtml">Errors</h1> + <xsl:apply-templates/> + </xsl:template> + + <xsl:template match="tp:generic-types"> + <h1 xmlns="http://www.w3.org/1999/xhtml">Generic types</h1> + <xsl:call-template name="do-types"/> + </xsl:template> + + <xsl:template name="do-types"> + <xsl:if test="tp:simple-type"> + <h2 xmlns="http://www.w3.org/1999/xhtml">Simple types</h2> + <xsl:apply-templates select="tp:simple-type"/> + </xsl:if> + + <xsl:if test="tp:enum"> + <h2 xmlns="http://www.w3.org/1999/xhtml">Enumerated types:</h2> + <xsl:apply-templates select="tp:enum"/> + </xsl:if> + + <xsl:if test="tp:flags"> + <h2 xmlns="http://www.w3.org/1999/xhtml">Sets of flags:</h2> + <xsl:apply-templates select="tp:flags"/> + </xsl:if> + + <xsl:if test="tp:struct"> + <h2 xmlns="http://www.w3.org/1999/xhtml">Structure types</h2> + <xsl:apply-templates select="tp:struct"/> + </xsl:if> + + <xsl:if test="tp:mapping"> + <h2 xmlns="http://www.w3.org/1999/xhtml">Mapping types</h2> + <xsl:apply-templates select="tp:mapping"/> + </xsl:if> + + <xsl:if test="tp:external-type"> + <h2 xmlns="http://www.w3.org/1999/xhtml">Types defined elsewhere</h2> + <dl><xsl:apply-templates select="tp:external-type"/></dl> + </xsl:if> + </xsl:template> + + <xsl:template match="tp:error"> + <h2 xmlns="http://www.w3.org/1999/xhtml"><a name="{concat(../@namespace, '.', translate(@name, ' ', ''))}"></a><xsl:value-of select="concat(../@namespace, '.', translate(@name, ' ', ''))"/></h2> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </xsl:template> + + <xsl:template match="/tp:spec/tp:copyright"> + <div xmlns="http://www.w3.org/1999/xhtml"> + <xsl:apply-templates mode="text"/> + </div> + </xsl:template> + <xsl:template match="/tp:spec/tp:license"> + <div xmlns="http://www.w3.org/1999/xhtml" class="license"> + <xsl:apply-templates mode="html"/> + </div> + </xsl:template> + + <xsl:template match="tp:copyright"/> + <xsl:template match="tp:license"/> + + <xsl:template match="interface"> + <h1 xmlns="http://www.w3.org/1999/xhtml"><a name="{@name}"></a><xsl:value-of select="@name"/></h1> + + <xsl:if test="@tp:causes-havoc"> + <p xmlns="http://www.w3.org/1999/xhtml" class="causes-havoc"> + This interface is <xsl:value-of select="@tp:causes-havoc"/> + and is likely to cause havoc to your API/ABI if bindings are generated. + Don't include it in libraries that care about compatibility. + </p> + </xsl:if> + + <xsl:if test="tp:requires"> + <p>Implementations of this interface must also implement:</p> + <ul xmlns="http://www.w3.org/1999/xhtml"> + <xsl:for-each select="tp:requires"> + <li><code><a href="#{@interface}"><xsl:value-of select="@interface"/></a></code></li> + </xsl:for-each> + </ul> + </xsl:if> + + <xsl:apply-templates select="tp:docstring" /> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + + <xsl:choose> + <xsl:when test="method"> + <h2 xmlns="http://www.w3.org/1999/xhtml">Methods:</h2> + <xsl:apply-templates select="method"/> + </xsl:when> + <xsl:otherwise> + <p xmlns="http://www.w3.org/1999/xhtml">Interface has no methods.</p> + </xsl:otherwise> + </xsl:choose> + + <xsl:choose> + <xsl:when test="signal"> + <h2 xmlns="http://www.w3.org/1999/xhtml">Signals:</h2> + <xsl:apply-templates select="signal"/> + </xsl:when> + <xsl:otherwise> + <p xmlns="http://www.w3.org/1999/xhtml">Interface has no signals.</p> + </xsl:otherwise> + </xsl:choose> + + <xsl:choose> + <xsl:when test="tp:property"> + <h2 xmlns="http://www.w3.org/1999/xhtml">Telepathy Properties:</h2> + <p xmlns="http://www.w3.org/1999/xhtml">Accessed using the + <a href="#org.freedesktop.Telepathy.Properties">Telepathy + Properties</a> interface.</p> + <dl xmlns="http://www.w3.org/1999/xhtml"> + <xsl:apply-templates select="tp:property"/> + </dl> + </xsl:when> + <xsl:otherwise> + <p xmlns="http://www.w3.org/1999/xhtml">Interface has no Telepathy + properties.</p> + </xsl:otherwise> + </xsl:choose> + + <xsl:choose> + <xsl:when test="property"> + <h2 xmlns="http://www.w3.org/1999/xhtml">D-Bus core Properties:</h2> + <p xmlns="http://www.w3.org/1999/xhtml">Accessed using the + org.freedesktop.DBus.Properties interface.</p> + <dl xmlns="http://www.w3.org/1999/xhtml"> + <xsl:apply-templates select="property"/> + </dl> + </xsl:when> + <xsl:otherwise> + <p xmlns="http://www.w3.org/1999/xhtml">Interface has no D-Bus core + properties.</p> + </xsl:otherwise> + </xsl:choose> + + <xsl:call-template name="do-types"/> + + </xsl:template> + + <xsl:template match="tp:flags"> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a tp:flags type </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on tp:flags type</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <h3> + <a name="type-{@name}"> + <xsl:value-of select="@name"/> + </a> + </h3> + <xsl:apply-templates select="tp:docstring" /> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + <dl xmlns="http://www.w3.org/1999/xhtml"> + <xsl:variable name="value-prefix"> + <xsl:choose> + <xsl:when test="@value-prefix"> + <xsl:value-of select="@value-prefix"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@name"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:for-each select="tp:flag"> + <dt xmlns="http://www.w3.org/1999/xhtml"><code><xsl:value-of select="concat($value-prefix, '_', @suffix)"/> = <xsl:value-of select="@value"/></code></dt> + <xsl:choose> + <xsl:when test="tp:docstring"> + <dd xmlns="http://www.w3.org/1999/xhtml"> + <xsl:apply-templates select="tp:docstring" /> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </dd> + </xsl:when> + <xsl:otherwise> + <dd xmlns="http://www.w3.org/1999/xhtml">(Undocumented)</dd> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + </dl> + </xsl:template> + + <xsl:template match="tp:enum"> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a tp:enum type </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on tp:enum type</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <h3 xmlns="http://www.w3.org/1999/xhtml"> + <a name="type-{@name}"> + <xsl:value-of select="@name"/> + </a> + </h3> + <xsl:apply-templates select="tp:docstring" /> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + <dl xmlns="http://www.w3.org/1999/xhtml"> + <xsl:variable name="value-prefix"> + <xsl:choose> + <xsl:when test="@value-prefix"> + <xsl:value-of select="@value-prefix"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@name"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:for-each select="tp:enumvalue"> + <dt xmlns="http://www.w3.org/1999/xhtml"><code><xsl:value-of select="concat($value-prefix, '_', @suffix)"/> = <xsl:value-of select="@value"/></code></dt> + <xsl:choose> + <xsl:when test="tp:docstring"> + <dd xmlns="http://www.w3.org/1999/xhtml"> + <xsl:apply-templates select="tp:docstring" /> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </dd> + </xsl:when> + <xsl:otherwise> + <dd xmlns="http://www.w3.org/1999/xhtml">(Undocumented)</dd> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + </dl> + </xsl:template> + + <xsl:template name="binding-name-check"> + <xsl:if test="not(@tp:name-for-bindings)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: Binding name missing from </xsl:text> + <xsl:value-of select="parent::interface/@name"/> + <xsl:text>.</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="translate(@tp:name-for-bindings, '_', '') != @name"> + <xsl:message terminate="yes"> + <xsl:text>ERR: Binding name </xsl:text> + <xsl:value-of select="@tp:name-for-bindings"/> + <xsl:text> doesn't correspond to D-Bus name </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + </xsl:template> + + <xsl:template match="property"> + + <xsl:call-template name="binding-name-check"/> + + <xsl:if test="not(parent::interface)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: property </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> does not have an interface as parent </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a property of </xsl:text> + <xsl:value-of select="../@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on property </xsl:text> + <xsl:value-of select="concat(../@name, '.', @name)"/> + <xsl:text>: '</xsl:text> + <xsl:value-of select="@access"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:if> + + <dt xmlns="http://www.w3.org/1999/xhtml"> + <a name="{concat(../@name, '.', @name)}"> + <code><xsl:value-of select="@name"/></code> + </a> + <xsl:text> − </xsl:text> + <code><xsl:value-of select="@type"/></code> + <xsl:call-template name="parenthesized-tp-type"/> + <xsl:text>, </xsl:text> + <xsl:choose> + <xsl:when test="@access = 'read'"> + <xsl:text>read-only</xsl:text> + </xsl:when> + <xsl:when test="@access = 'write'"> + <xsl:text>write-only</xsl:text> + </xsl:when> + <xsl:when test="@access = 'readwrite'"> + <xsl:text>read/write</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: unknown or missing value for </xsl:text> + <xsl:text>@access on property </xsl:text> + <xsl:value-of select="concat(../@name, '.', @name)"/> + <xsl:text>: '</xsl:text> + <xsl:value-of select="@access"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </dt> + <dd xmlns="http://www.w3.org/1999/xhtml"> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </dd> + </xsl:template> + + <xsl:template match="tp:property"> + <dt xmlns="http://www.w3.org/1999/xhtml"> + <xsl:if test="@name"> + <code><xsl:value-of select="@name"/></code> − + </xsl:if> + <code><xsl:value-of select="@type"/></code> + </dt> + <dd xmlns="http://www.w3.org/1999/xhtml"> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </dd> + </xsl:template> + + <xsl:template match="tp:mapping"> + <div xmlns="http://www.w3.org/1999/xhtml" class="struct"> + <h3> + <a name="type-{@name}"> + <xsl:value-of select="@name"/> + </a> − a{ + <xsl:for-each select="tp:member"> + <xsl:value-of select="@type"/> + <xsl:text>: </xsl:text> + <xsl:value-of select="@name"/> + <xsl:if test="position() != last()"> → </xsl:if> + </xsl:for-each> + } + </h3> + <div class="docstring"> + <xsl:apply-templates select="tp:docstring"/> + <xsl:if test="string(@array-name) != ''"> + <p>In bindings that need a separate name, arrays of + <xsl:value-of select="@name"/> should be called + <xsl:value-of select="@array-name"/>.</p> + </xsl:if> + </div> + <div> + <h4>Members</h4> + <dl> + <xsl:apply-templates select="tp:member" mode="members-in-docstring"/> + </dl> + </div> + </div> + </xsl:template> + + <xsl:template match="tp:docstring" mode="in-index"/> + + <xsl:template match="tp:simple-type | tp:enum | tp:flags | tp:external-type" + mode="in-index"> + − <xsl:value-of select="@type"/> + </xsl:template> + + <xsl:template match="tp:simple-type"> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a tp:simple-type </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on tp:simple-type</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <div xmlns="http://www.w3.org/1999/xhtml" class="simple-type"> + <h3> + <a name="type-{@name}"> + <xsl:value-of select="@name"/> + </a> − <xsl:value-of select="@type"/> + </h3> + <div class="docstring"> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </div> + </div> + </xsl:template> + + <xsl:template match="tp:external-type"> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a tp:external-type </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on tp:external-type</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <div xmlns="http://www.w3.org/1999/xhtml" class="external-type"> + <dt> + <a name="type-{@name}"> + <xsl:value-of select="@name"/> + </a> − <xsl:value-of select="@type"/> + </dt> + <dd>Defined by: <xsl:value-of select="@from"/></dd> + </div> + </xsl:template> + + <xsl:template match="tp:struct" mode="in-index"> + − ( <xsl:for-each select="tp:member"> + <xsl:value-of select="@type"/> + <xsl:if test="position() != last()">, </xsl:if> + </xsl:for-each> ) + </xsl:template> + + <xsl:template match="tp:mapping" mode="in-index"> + − a{ <xsl:for-each select="tp:member"> + <xsl:value-of select="@type"/> + <xsl:if test="position() != last()"> → </xsl:if> + </xsl:for-each> } + </xsl:template> + + <xsl:template match="tp:struct"> + <div xmlns="http://www.w3.org/1999/xhtml" class="struct"> + <h3> + <a name="type-{@name}"> + <xsl:value-of select="@name"/> + </a> − ( + <xsl:for-each select="tp:member"> + <xsl:value-of select="@type"/> + <xsl:text>: </xsl:text> + <xsl:value-of select="@name"/> + <xsl:if test="position() != last()">, </xsl:if> + </xsl:for-each> + ) + </h3> + <div class="docstring"> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </div> + <xsl:choose> + <xsl:when test="string(@array-name) != ''"> + <p>In bindings that need a separate name, arrays of + <xsl:value-of select="@name"/> should be called + <xsl:value-of select="@array-name"/>.</p> + </xsl:when> + <xsl:otherwise> + <p>Arrays of <xsl:value-of select="@name"/> don't generally + make sense.</p> + </xsl:otherwise> + </xsl:choose> + <div> + <h4>Members</h4> + <dl> + <xsl:apply-templates select="tp:member" mode="members-in-docstring"/> + </dl> + </div> + </div> + </xsl:template> + + <xsl:template match="method"> + + <xsl:call-template name="binding-name-check"/> + + <xsl:if test="not(parent::interface)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: method </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> does not have an interface as parent </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a method of </xsl:text> + <xsl:value-of select="../@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:for-each select="arg"> + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of method </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no type</xsl:text> + </xsl:message> + </xsl:if> + <xsl:choose> + <xsl:when test="@direction='in'"> + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: an 'in' arg of method </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no name</xsl:text> + </xsl:message> + </xsl:if> + </xsl:when> + <xsl:when test="@direction='out'"> + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="no"> + <xsl:text>WARNING: an 'out' arg of method </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no name</xsl:text> + </xsl:message> + </xsl:if> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of method </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has direction neither 'in' nor 'out'</xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + + <div xmlns="http://www.w3.org/1999/xhtml" class="method"> + <h3 xmlns="http://www.w3.org/1999/xhtml"> + <a name="{concat(../@name, concat('.', @name))}"> + <xsl:value-of select="@name"/> + </a> ( + <xsl:for-each xmlns="" select="arg[@direction='in']"> + <xsl:value-of select="@type"/>: <xsl:value-of select="@name"/> + <xsl:if test="position() != last()">, </xsl:if> + </xsl:for-each> + ) → + <xsl:choose> + <xsl:when test="arg[@direction='out']"> + <xsl:for-each xmlns="" select="arg[@direction='out']"> + <xsl:value-of select="@type"/> + <xsl:if test="position() != last()">, </xsl:if> + </xsl:for-each> + </xsl:when> + <xsl:otherwise>nothing</xsl:otherwise> + </xsl:choose> + </h3> + <div xmlns="http://www.w3.org/1999/xhtml" class="docstring"> + <xsl:apply-templates select="tp:docstring" /> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </div> + + <xsl:if test="arg[@direction='in']"> + <div xmlns="http://www.w3.org/1999/xhtml"> + <h4>Parameters</h4> + <dl xmlns="http://www.w3.org/1999/xhtml"> + <xsl:apply-templates select="arg[@direction='in']" + mode="parameters-in-docstring"/> + </dl> + </div> + </xsl:if> + + <xsl:if test="arg[@direction='out']"> + <div xmlns="http://www.w3.org/1999/xhtml"> + <h4>Returns</h4> + <dl xmlns="http://www.w3.org/1999/xhtml"> + <xsl:apply-templates select="arg[@direction='out']" + mode="returns-in-docstring"/> + </dl> + </div> + </xsl:if> + + <xsl:if test="tp:possible-errors"> + <div xmlns="http://www.w3.org/1999/xhtml"> + <h4>Possible errors</h4> + <dl xmlns="http://www.w3.org/1999/xhtml"> + <xsl:apply-templates select="tp:possible-errors/tp:error"/> + </dl> + </div> + </xsl:if> + + </div> + </xsl:template> + + <xsl:template name="tp-type"> + <xsl:param name="tp-type"/> + <xsl:param name="type"/> + + <xsl:variable name="single-type"> + <xsl:choose> + <xsl:when test="contains($tp-type, '[]')"> + <xsl:value-of select="substring-before($tp-type, '[]')"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$tp-type"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:variable name="type-of-single-tp-type"> + <xsl:choose> + <xsl:when test="//tp:simple-type[@name=$single-type]"> + <xsl:value-of select="string(//tp:simple-type[@name=$single-type]/@type)"/> + </xsl:when> + <xsl:when test="//tp:struct[@name=$single-type]"> + <xsl:text>(</xsl:text> + <xsl:for-each select="//tp:struct[@name=$single-type]/tp:member"> + <xsl:value-of select="@type"/> + </xsl:for-each> + <xsl:text>)</xsl:text> + </xsl:when> + <xsl:when test="//tp:enum[@name=$single-type]"> + <xsl:value-of select="string(//tp:enum[@name=$single-type]/@type)"/> + </xsl:when> + <xsl:when test="//tp:flags[@name=$single-type]"> + <xsl:value-of select="string(//tp:flags[@name=$single-type]/@type)"/> + </xsl:when> + <xsl:when test="//tp:mapping[@name=$single-type]"> + <xsl:text>a{</xsl:text> + <xsl:for-each select="//tp:mapping[@name=$single-type]/tp:member"> + <xsl:value-of select="@type"/> + </xsl:for-each> + <xsl:text>}</xsl:text> + </xsl:when> + <xsl:when test="//tp:external-type[@name=$single-type]"> + <xsl:value-of select="string(//tp:external-type[@name=$single-type]/@type)"/> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: Unable to find type '</xsl:text> + <xsl:value-of select="$tp-type"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:variable name="type-of-tp-type"> + <xsl:if test="contains($tp-type, '[]')"> + <!-- one 'a', plus one for each [ after the [], and delete all ] --> + <xsl:value-of select="concat('a', + translate(substring-after($tp-type, '[]'), '[]', 'a'))"/> + </xsl:if> + <xsl:value-of select="$type-of-single-tp-type"/> + </xsl:variable> + + <xsl:if test="string($type) != '' and + string($type-of-tp-type) != string($type)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: tp:type '</xsl:text> + <xsl:value-of select="$tp-type"/> + <xsl:text>' has D-Bus type '</xsl:text> + <xsl:value-of select="$type-of-tp-type"/> + <xsl:text>' but has been used with type='</xsl:text> + <xsl:value-of select="$type"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="contains($tp-type, '[]')"> + <xsl:call-template name="tp-type-array-usage-check"> + <xsl:with-param name="single-type" select="$single-type"/> + <xsl:with-param name="type-of-single-tp-type" + select="$type-of-single-tp-type"/> + </xsl:call-template> + </xsl:if> + + <a href="#type-{$single-type}"><xsl:value-of select="$tp-type"/></a> + + </xsl:template> + + <xsl:template name="tp-type-array-usage-check"> + <xsl:param name="single-type"/> + <xsl:param name="type-of-single-tp-type"/> + + <xsl:variable name="array-name"> + <xsl:choose> + <xsl:when test="//tp:struct[@name=$single-type]"> + <xsl:value-of select="//tp:struct[@name=$single-type]/@array-name"/> + </xsl:when> + <xsl:when test="//tp:mapping[@name=$single-type]"> + <xsl:value-of select="//tp:mapping[@name=$single-type]/@array-name"/> + </xsl:when> + <xsl:when test="//tp:external-type[@name=$single-type]"> + <xsl:value-of select="//tp:external-type[@name=$single-type]/@array-name"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="''"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:if test="not(contains('ybnqiuxtdsvog', $type-of-single-tp-type))"> + <xsl:if test="not($array-name) or $array-name=''"> + <xsl:message terminate="yes"> + <xsl:text>No array-name specified for complex type </xsl:text> + <xsl:value-of select="$single-type"/> + <xsl:text>, but array used </xsl:text> + </xsl:message> + </xsl:if> + </xsl:if> + </xsl:template> + + <xsl:template name="parenthesized-tp-type"> + <xsl:if test="@tp:type"> + <xsl:text> (</xsl:text> + <xsl:call-template name="tp-type"> + <xsl:with-param name="tp-type" select="@tp:type"/> + <xsl:with-param name="type" select="@type"/> + </xsl:call-template> + <xsl:text>)</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="tp:member" mode="members-in-docstring"> + <dt xmlns="http://www.w3.org/1999/xhtml"> + <code><xsl:value-of select="@name"/></code> − + <code><xsl:value-of select="@type"/></code> + <xsl:call-template name="parenthesized-tp-type"/> + </dt> + <dd xmlns="http://www.w3.org/1999/xhtml"> + <xsl:choose> + <xsl:when test="tp:docstring"> + <xsl:apply-templates select="tp:docstring" /> + </xsl:when> + <xsl:otherwise> + <em>(undocumented)</em> + </xsl:otherwise> + </xsl:choose> + </dd> + </xsl:template> + + <xsl:template match="arg" mode="parameters-in-docstring"> + <dt xmlns="http://www.w3.org/1999/xhtml"> + <code><xsl:value-of select="@name"/></code> − + <code><xsl:value-of select="@type"/></code> + <xsl:call-template name="parenthesized-tp-type"/> + </dt> + <dd xmlns="http://www.w3.org/1999/xhtml"> + <xsl:apply-templates select="tp:docstring" /> + </dd> + </xsl:template> + + <xsl:template match="arg" mode="returns-in-docstring"> + <dt xmlns="http://www.w3.org/1999/xhtml"> + <xsl:if test="@name"> + <code><xsl:value-of select="@name"/></code> − + </xsl:if> + <code><xsl:value-of select="@type"/></code> + <xsl:call-template name="parenthesized-tp-type"/> + </dt> + <dd xmlns="http://www.w3.org/1999/xhtml"> + <xsl:apply-templates select="tp:docstring"/> + </dd> + </xsl:template> + + <xsl:template match="tp:possible-errors/tp:error"> + <dt xmlns="http://www.w3.org/1999/xhtml"> + <code><xsl:value-of select="@name"/></code> + </dt> + <dd xmlns="http://www.w3.org/1999/xhtml"> + <xsl:variable name="name" select="@name"/> + <xsl:choose> + <xsl:when test="tp:docstring"> + <xsl:apply-templates select="tp:docstring"/> + </xsl:when> + <xsl:when test="//tp:errors/tp:error[concat(../@namespace, '.', translate(@name, ' ', ''))=$name]/tp:docstring"> + <xsl:apply-templates select="//tp:errors/tp:error[concat(../@namespace, '.', translate(@name, ' ', ''))=$name]/tp:docstring"/> <em xmlns="http://www.w3.org/1999/xhtml">(generic description)</em> + </xsl:when> + <xsl:otherwise> + (Undocumented.) + </xsl:otherwise> + </xsl:choose> + </dd> + </xsl:template> + + <xsl:template match="signal"> + + <xsl:call-template name="binding-name-check"/> + + <xsl:if test="not(parent::interface)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: signal </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> does not have an interface as parent </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a signal of </xsl:text> + <xsl:value-of select="../@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:for-each select="arg"> + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of signal </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no type</xsl:text> + </xsl:message> + </xsl:if> + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of signal </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no name</xsl:text> + </xsl:message> + </xsl:if> + <xsl:choose> + <xsl:when test="not(@direction)"/> + <xsl:when test="@direction='in'"> + <xsl:message terminate="no"> + <xsl:text>INFO: an arg of signal </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has unnecessary direction 'in'</xsl:text> + </xsl:message> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of signal </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has direction other than 'in'</xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + + <div xmlns="http://www.w3.org/1999/xhtml" class="signal"> + <h3 xmlns="http://www.w3.org/1999/xhtml"> + <a name="{concat(../@name, concat('.', @name))}"> + <xsl:value-of select="@name"/> + </a> ( + <xsl:for-each xmlns="" select="arg"> + <xsl:value-of select="@type"/>: <xsl:value-of select="@name"/> + <xsl:if test="position() != last()">, </xsl:if> + </xsl:for-each> + )</h3> + + <div xmlns="http://www.w3.org/1999/xhtml" class="docstring"> + <xsl:apply-templates select="tp:docstring"/> + <xsl:apply-templates select="tp:added"/> + <xsl:apply-templates select="tp:changed"/> + <xsl:apply-templates select="tp:deprecated"/> + </div> + + <xsl:if test="arg"> + <div xmlns="http://www.w3.org/1999/xhtml"> + <h4>Parameters</h4> + <dl xmlns="http://www.w3.org/1999/xhtml"> + <xsl:apply-templates select="arg" mode="parameters-in-docstring"/> + </dl> + </div> + </xsl:if> + </div> + </xsl:template> + + <xsl:output method="xml" indent="no" encoding="ascii" + omit-xml-declaration="yes" + doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" + doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" /> + + <xsl:template match="/tp:spec"> + <html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title> + <xsl:value-of select="tp:title"/> + <xsl:if test="tp:version"> + <xsl:text> version </xsl:text> + <xsl:value-of select="tp:version"/> + </xsl:if> + </title> + <style type="text/css"> + + body { + font-family: sans-serif; + margin: 2em; + height: 100%; + font-size: 1.2em; + } + h1 { + padding-top: 5px; + padding-bottom: 5px; + font-size: 1.6em; + background: #dadae2; + } + h2 { + font-size: 1.3em; + } + h3 { + font-size: 1.2em; + } + a:link, a:visited, a:link:hover, a:visited:hover { + font-weight: bold; + } + .topbox { + padding-top: 10px; + padding-left: 10px; + border-bottom: black solid 1px; + padding-bottom: 10px; + background: #dadae2; + font-size: 2em; + font-weight: bold; + color: #5c5c5c; + } + .topnavbox { + padding-left: 10px; + padding-top: 5px; + padding-bottom: 5px; + background: #abacba; + border-bottom: black solid 1px; + font-size: 1.2em; + } + .topnavbox a{ + color: black; + font-weight: normal; + } + .sidebar { + float: left; + /* width:9em; + border-right:#abacba solid 1px; + border-left: #abacba solid 1px; + height:100%; */ + border: #abacba solid 1px; + padding-left: 10px; + margin-left: 10px; + padding-right: 10px; + margin-right: 10px; + color: #5d5d5d; + background: #dadae2; + } + .sidebar a { + text-decoration: none; + border-bottom: #e29625 dotted 1px; + color: #e29625; + font-weight: normal; + } + .sidebar h1 { + font-size: 1.2em; + color: black; + } + .sidebar ul { + padding-left: 25px; + padding-bottom: 10px; + border-bottom: #abacba solid 1px; + } + .sidebar li { + padding-top: 2px; + padding-bottom: 2px; + } + .sidebar h2 { + font-style:italic; + font-size: 0.81em; + padding-left: 5px; + padding-right: 5px; + font-weight: normal; + } + .date { + font-size: 0.6em; + float: right; + font-style: italic; + } + .method, .signal, .property { + margin-left: 1em; + margin-right: 4em; + } + .rationale { + font-style: italic; + border-left: 0.25em solid #808080; + padding-left: 0.5em; + } + + .added { + color: #006600; + background: #ffffff; + } + .deprecated { + color: #ff0000; + background: #ffffff; + } + table, tr, td, th { + border: 1px solid #666; + } + + </style> + </head> + <body> + <h1 class="topbox"> + <xsl:value-of select="tp:title" /> + </h1> + <xsl:if test="tp:version"> + <h2>Version <xsl:value-of select="string(tp:version)"/></h2> + </xsl:if> + <xsl:apply-templates select="tp:copyright"/> + <xsl:apply-templates select="tp:license"/> + <xsl:apply-templates select="tp:docstring"/> + + <h2>Interfaces</h2> + <ul> + <xsl:for-each select="//node/interface"> + <li><code><a href="#{@name}"><xsl:value-of select="@name"/></a></code></li> + </xsl:for-each> + </ul> + + <xsl:apply-templates select="//node"/> + <xsl:apply-templates select="tp:generic-types"/> + <xsl:apply-templates select="tp:errors"/> + + <h1>Index</h1> + <h2>Index of interfaces</h2> + <ul> + <xsl:for-each select="//node/interface"> + <li><code><a href="#{@name}"><xsl:value-of select="@name"/></a></code></li> + </xsl:for-each> + </ul> + <h2>Index of types</h2> + <ul> + <xsl:for-each select="//tp:simple-type | //tp:enum | //tp:flags | //tp:mapping | //tp:struct | //tp:external-type"> + <xsl:sort select="@name"/> + <li> + <code> + <a href="#type-{@name}"> + <xsl:value-of select="@name"/> + </a> + </code> + <xsl:apply-templates mode="in-index" select="."/> + </li> + </xsl:for-each> + </ul> + </body> + </html> + </xsl:template> + + <xsl:template match="node"> + <xsl:apply-templates /> + </xsl:template> + + <xsl:template match="text()"> + <xsl:if test="normalize-space(.) != ''"> + <xsl:message terminate="yes"> + <xsl:text>Stray text: {{{</xsl:text> + <xsl:value-of select="." /> + <xsl:text>}}} </xsl:text> + </xsl:message> + </xsl:if> + </xsl:template> + + <xsl:template match="*"> + <xsl:message terminate="yes"> + <xsl:text>Unrecognised element: {</xsl:text> + <xsl:value-of select="namespace-uri(.)" /> + <xsl:text>}</xsl:text> + <xsl:value-of select="local-name(.)" /> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:template> +</xsl:stylesheet> + +<!-- vim:set sw=2 sts=2 et: --> diff --git a/sflphone-common/doc/dbus-api/tools/specparser.py b/sflphone-common/doc/dbus-api/tools/specparser.py new file mode 100644 index 0000000000000000000000000000000000000000..4208ad4104cab3c2a73aa75c71e05b3a53541b43 --- /dev/null +++ b/sflphone-common/doc/dbus-api/tools/specparser.py @@ -0,0 +1,866 @@ +# +# specparser.py +# +# Reads in a spec document and generates pretty data structures from it. +# +# Copyright (C) 2009 Collabora Ltd. +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or (at +# your option) any later version. +# +# This library 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 Lesser General Public License +# for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# Authors: Davyd Madeley <davyd.madeley@collabora.co.uk> +# + +import sys +import xml.dom.minidom + +import xincludator + +XMLNS_TP = 'http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0' + +class UnknownAccess(Exception): pass +class UnknownDirection(Exception): pass +class UnknownType(Exception): pass +class UnnamedItem(Exception): pass +class UntypedItem(Exception): pass +class UnsupportedArray(Exception): pass + +def getText(dom): + try: + if dom.childNodes[0].nodeType == dom.TEXT_NODE: + return dom.childNodes[0].data + else: + return '' + except IndexError: + return '' + +def getChildrenByName(dom, namespace, name): + return filter(lambda n: n.nodeType == n.ELEMENT_NODE and \ + n.namespaceURI == namespace and \ + n.localName == name, + dom.childNodes) + +def build_name(namespace, name): + """Returns a name by appending `name' to the namespace of this object. + """ + return '.'.join( + filter(lambda n: n is not None and n != '', + [namespace, name.replace(' ', '')]) + ) + +class Base(object): + """The base class for any type of XML node in the spec that implements the + 'name' attribute. + + Don't instantiate this class directly. + """ + devhelp_name = "" + + def __init__(self, parent, namespace, dom): + self.short_name = name = dom.getAttribute('name') + self.namespace = namespace + self.name = build_name(namespace, name) + self.parent = parent + + try: + self.docstring = getChildrenByName(dom, XMLNS_TP, 'docstring')[0] + except IndexError: + self.docstring = None + + try: + self.added = getChildrenByName(dom, XMLNS_TP, 'added')[0] + except IndexError: + self.added = None + + try: + self.deprecated = getChildrenByName(dom, XMLNS_TP, 'deprecated')[0] + except IndexError: + self.deprecated = None + + self.changed = getChildrenByName(dom, XMLNS_TP, 'changed') + + self.validate() + + def validate(self): + if self.short_name == '': + raise UnnamedItem("Node %s of %s has no name" % ( + self.__class__.__name__, self.parent)) + + def get_type_name(self): + return self.__class__.__name__ + + def get_spec(self): + return self.parent.get_spec() + + def get_root_namespace(self): + return self.get_interface().name + + def get_interface(self): + return self.parent.get_interface() + + def get_url(self): + return "%s#%s" % (self.get_interface().get_url(), self.name) + + def _get_generic_with_ver(self, nnode, htmlclass, txt): + if nnode is None: + return '' + else: + # make a copy of this node, turn it into a HTML <div> tag + node = nnode.cloneNode(True) + node.tagName = 'div' + node.baseURI = None + node.setAttribute('class', htmlclass) + + try: + node.removeAttribute('version') + + span = xml.dom.minidom.parseString( + ('<span class="version">%s\n</span>' % txt) % + nnode.getAttribute('version')).firstChild + node.insertBefore(span, node.firstChild) + except xml.dom.NotFoundErr: + print >> sys.stderr, \ + 'WARNING: %s was %s, but gives no version' % (self, htmlclass) + + self._convert_to_html(node) + + return node.toxml().encode('ascii', 'xmlcharrefreplace') + + def get_added(self): + return self._get_generic_with_ver(self.added, 'added', + "Added in %s.") + + def get_deprecated(self): + return self._get_generic_with_ver(self.deprecated, 'deprecated', + "Deprecated since %s.") + + def get_changed(self): + return '\n'.join(map(lambda n: + self._get_generic_with_ver(n, 'changed', "Changed in %s."), + self.changed)) + + def get_docstring(self): + """Get the docstring for this node, but do node substitution to + rewrite types, interfaces, etc. as links. + """ + if self.docstring is None: + return '' + else: + # make a copy of this node, turn it into a HTML <div> tag + node = self.docstring.cloneNode(True) + node.tagName = 'div' + node.baseURI = None + node.setAttribute('class', 'docstring') + + self._convert_to_html(node) + + return node.toxml().encode('ascii', 'xmlcharrefreplace') + + def _convert_to_html(self, node): + spec = self.get_spec() + namespace = self.get_root_namespace() + + # rewrite <tp:rationale> + for n in node.getElementsByTagNameNS(XMLNS_TP, 'rationale'): + n.tagName = 'div' + n.namespaceURI = None + n.setAttribute('class', 'rationale') + + # rewrite <tp:type> + for n in node.getElementsByTagNameNS(XMLNS_TP, 'type'): + t = spec.lookup_type(getText(n)) + n.tagName = 'a' + n.namespaceURI = None + n.setAttribute('href', t.get_url()) + + # rewrite <tp:member-ref> + for n in node.getElementsByTagNameNS(XMLNS_TP, 'member-ref'): + key = getText(n) + try: + o = spec.lookup(key, namespace=namespace) + except KeyError: + print >> sys.stderr, \ + "WARNING: Key '%s' not known in namespace '%s'" % ( + key, namespace) + continue + + n.tagName = 'a' + n.namespaceURI = None + n.setAttribute('href', o.get_url()) + n.setAttribute('title', o.get_title()) + + # rewrite <tp:dbus-ref> + for n in node.getElementsByTagNameNS(XMLNS_TP, 'dbus-ref'): + namespace = n.getAttribute('namespace') + key = getText(n) + try: + o = spec.lookup(key, namespace=namespace) + except KeyError: + print >> sys.stderr, \ + "WARNING: Key '%s' not known in namespace '%s'" % ( + key, namespace) + continue + + n.tagName = 'a' + n.namespaceURI = None + n.setAttribute('href', o.get_url()) + n.setAttribute('title', o.get_title()) + + def get_title(self): + return '%s %s' % (self.get_type_name(), self.name) + + def __repr__(self): + return '%s(%s)' % (self.__class__.__name__, self.name) + +class PossibleError(Base): + def __init__(self, parent, namespace, dom): + super(PossibleError, self).__init__(parent, namespace, dom) + + def get_error(self): + spec = self.get_spec() + try: + return spec.errors[self.name] + except KeyError: + return External(self.name) + + def get_url(self): + return self.get_error().get_url() + + def get_title(self): + return self.get_error().get_title() + + def get_docstring(self): + d = super(PossibleError, self).get_docstring() + if d == '': + return self.get_error().get_docstring() + else: + return d + +class Method(Base): + devhelp_name = "function" + + def __init__(self, parent, namespace, dom): + super(Method, self).__init__(parent, namespace, dom) + + args = build_list(self, Arg, self.name, + dom.getElementsByTagName('arg')) + + # separate arguments as input and output arguments + self.in_args = filter(lambda a: a.direction == Arg.DIRECTION_IN, args) + self.out_args = filter(lambda a: a.direction == Arg.DIRECTION_OUT, args) + + for arg in args: + if arg.direction == Arg.DIRECTION_IN or \ + arg.direction == Arg.DIRECTION_OUT: + continue + + print >> sys.stderr, "WARNING: '%s' of method '%s' does not specify a suitable direction" % (arg, self) + + self.possible_errors = build_list(self, PossibleError, None, + dom.getElementsByTagNameNS(XMLNS_TP, 'error')) + + def get_in_args(self): + return ', '.join(map(lambda a: a.spec_name(), self.in_args)) + + def get_out_args(self): + if len(self.out_args) > 0: + return ', '.join(map(lambda a: a.spec_name(), self.out_args)) + else: + return 'nothing' + +class Typed(Base): + """The base class for all typed nodes (i.e. Arg and Property). + + Don't instantiate this class directly. + """ + + def __init__(self, parent, namespace, dom): + super(Typed, self).__init__(parent, namespace, dom) + + self.type = dom.getAttributeNS(XMLNS_TP, 'type') + self.dbus_type = dom.getAttribute('type') + + # check we have a dbus type + if self.dbus_type == '': + raise UntypedItem("Node referred to by '%s' has no type" % dom.toxml()) + def get_type(self): + return self.get_spec().lookup_type(self.type) + + def get_type_url(self): + t = self.get_type() + if t is None: return '' + else: return t.get_url() + + def get_type_title(self): + t = self.get_type() + if t is None: return '' + else: return t.get_title() + + def spec_name(self): + return '%s: %s' % (self.dbus_type, self.short_name) + + def __repr__(self): + return '%s(%s:%s)' % (self.__class__.__name__, self.name, self.dbus_type) + +class Property(Typed): + ACCESS_READ = 1 + ACCESS_WRITE = 2 + + ACCESS_READWRITE = ACCESS_READ | ACCESS_WRITE + + def __init__(self, parent, namespace, dom): + super(Property, self).__init__(parent, namespace, dom) + + access = dom.getAttribute('access') + if access == 'read': + self.access = self.ACCESS_READ + elif access == 'write': + self.access = self.ACCESS_WRITE + elif access == 'readwrite': + self.access = self.ACCESS_READWRITE + else: + raise UnknownAccess("Unknown access '%s' on %s" % (access, self)) + + def get_access(self): + if self.access & self.ACCESS_READ and self.access & self.ACCESS_WRITE: + return 'Read/Write' + elif self.access & self.ACCESS_READ: + return 'Read only' + elif self.access & self.ACCESS_WRITE: + return 'Write only' + +class AwkwardTelepathyProperty(Typed): + def get_type_name(self): + return 'Telepathy Property' + +class Arg(Typed): + DIRECTION_IN, DIRECTION_OUT, DIRECTION_UNSPECIFIED = range(3) + + def __init__(self, parent, namespace, dom): + super(Arg, self).__init__(parent, namespace, dom) + + direction = dom.getAttribute('direction') + if direction == 'in': + self.direction = self.DIRECTION_IN + elif direction == 'out': + self.direction = self.DIRECTION_OUT + elif direction == '': + self.direction = self.DIRECTION_UNSPECIFIED + else: + raise UnknownDirection("Unknown direction '%s' on %s" % ( + direction, self.parent)) + +class Signal(Base): + def __init__(self, parent, namespace, dom): + super(Signal, self).__init__(parent, namespace, dom) + + self.args = build_list(self, Arg, self.name, + dom.getElementsByTagName('arg')) + + for arg in self.args: + if arg.direction == Arg.DIRECTION_UNSPECIFIED: + continue + + print >> sys.stderr, "WARNING: '%s' of signal '%s' does not specify a suitable direction" % (arg, self) + + def get_args(self): + return ', '.join(map(lambda a: a.spec_name(), self.args)) + +class External(object): + """External objects are objects that are referred to in another spec. + + We have to attempt to look them up if at all possible. + """ + + def __init__(self, name): + self.name = self.short_name = name + + def get_url(self): + return None + + def get_title(self): + return 'External %s' % self.name + + def get_docstring(self): + return None + + def __repr__(self): + return '%s(%s)' % (self.__class__.__name__, self.name) + +class Interface(Base): + def __init__(self, parent, namespace, dom, spec_namespace): + super(Interface, self).__init__(parent, namespace, dom) + + # If you're writing a spec with more than one top-level namespace, you + # probably want to replace spec_namespace with a list. + if self.name.startswith(spec_namespace + "."): + self.short_name = self.name[len(spec_namespace) + 1:] + else: + self.short_name = self.name + + # build lists of methods, etc., in this interface + self.methods = build_list(self, Method, self.name, + dom.getElementsByTagName('method')) + self.properties = build_list(self, Property, self.name, + dom.getElementsByTagName('property')) + self.signals = build_list(self, Signal, self.name, + dom.getElementsByTagName('signal')) + self.tpproperties = build_list(self, AwkwardTelepathyProperty, + self.name, dom.getElementsByTagNameNS(XMLNS_TP, 'property')) + self.handler_capability_tokens = build_list(self, + HandlerCapabilityToken, self.name, + dom.getElementsByTagNameNS(XMLNS_TP, + 'handler-capability-token')) + self.contact_attributes = build_list(self, ContactAttribute, self.name, + dom.getElementsByTagNameNS(XMLNS_TP, 'contact-attribute')) + + # build a list of types in this interface + self.types = parse_types(self, dom, self.name) + + # find out if this interface causes havoc + self.causes_havoc = dom.getAttributeNS(XMLNS_TP, 'causes-havoc') + if self.causes_havoc == '': self.causes_havoc = None + + # find out what we're required to also implement + self.requires = map(lambda n: n.getAttribute('interface'), + getChildrenByName(dom, XMLNS_TP, 'requires')) + + def get_interface(self): + return self + + def get_requires(self): + spec = self.get_spec() + + def lookup(r): + try: + return spec.lookup(r) + except KeyError: + return External(r) + + return map(lookup, self.requires) + + def get_url(self): + return '%s.html' % self.name + +class Error(Base): + def get_url(self): + return 'errors.html#%s' % self.name + + def get_root_namespace(self): + return self.namespace + +class DBusList(object): + """Stores a list of a given DBusType. Provides some basic validation to + determine whether or not the type is sane. + """ + def __init__(self, child): + self.child = child + + if isinstance(child, DBusType): + self.ultimate = child + self.depth = 1 + + if self.child.array_name == '': + raise UnsupportedArray("Type '%s' does not support being " + "used in an array" % self.child.name) + else: + self.name = build_name(self.child.namespace, + self.child.array_name) + self.short_name = self.child.array_name + + elif isinstance(child, DBusList): + self.ultimate = child.ultimate + self.depth = child.depth + 1 + self.name = self.child.name + '_List' + self.short_name = self.child.short_name + '_List' + + # check that our child can operate at this depth + maxdepth = int(self.ultimate.array_depth) + if self.depth > maxdepth: + raise TypeError("Type '%s' has exceeded its maximum depth (%i)" % (self, maxdepth)) + + else: + raise TypeError("DBusList can contain only a DBusType or DBusList not '%s'" % child) + + self.dbus_type = 'a' + self.child.dbus_type + + def get_url(self): + return self.ultimate.get_url() + + def get_title(self): + return "Array of %s" % self.child.get_title() + + def __repr__(self): + return 'Array(%s)' % self.child + +class DBusType(Base): + """The base class for all D-Bus types referred to in the spec. + + Don't instantiate this class directly. + """ + + devhelp_name = "typedef" + + def __init__(self, parent, namespace, dom): + super(DBusType, self).__init__(parent, namespace, dom) + + self.dbus_type = dom.getAttribute('type') + self.array_name = dom.getAttribute('array-name') + self.array_depth = dom.getAttribute('array-depth') + + def get_root_namespace(self): + return self.namespace + + def get_breakdown(self): + return '' + + def get_url(self): + if isinstance(self.parent, Interface): + html = self.parent.get_url() + else: + html = 'generic-types.html' + + return '%s#%s' % (html, self.name) + +class SimpleType(DBusType): + def get_type_name(self): + return 'Simple Type' + +class ExternalType(DBusType): + def __init__(self, parent, namespace, dom): + super(ExternalType, self).__init__(parent, namespace, dom) + + # FIXME: until we are able to cross reference external types to learn + # about their array names, we're just going to assume they work like + # this + self.array_name = self.short_name + '_List' + + def get_type_name(self): + return 'External Type' + +class StructLike(DBusType): + """Base class for all D-Bus types that look kind of like Structs + + Don't instantiate this class directly. + """ + + class StructMember(Typed): + def get_root_namespace(self): + return self.parent.get_root_namespace() + + def __init__(self, parent, namespace, dom): + super(StructLike, self).__init__(parent, namespace, dom) + + self.members = build_list(self, StructLike.StructMember, None, + dom.getElementsByTagNameNS(XMLNS_TP, 'member')) + + def get_breakdown(self): + str = '' + str += '<ul>\n' + for member in self.members: + # attempt to lookup the member up in the type system + t = member.get_type() + + str += '<li>%s — %s' % (member.name, member.dbus_type) + if t: str += ' (<a href="%s" title="%s">%s</a>)' % ( + t.get_url(), t.get_title(), t.short_name) + str += '</li>\n' + str += member.get_docstring() + str += '</ul>\n' + + return str + +class Mapping(StructLike): + def __init__(self, parent, namespace, dom): + super(Mapping, self).__init__(parent, namespace, dom) + + # rewrite the D-Bus type + self.dbus_type = 'a{%s}' % ''.join(map(lambda m: m.dbus_type, self.members)) + +class Struct(StructLike): + + devhelp_name = "struct" + + def __init__(self, parent, namespace, dom): + super(Struct, self).__init__(parent, namespace, dom) + + # rewrite the D-Bus type + self.dbus_type = '(%s)' % ''.join(map(lambda m: m.dbus_type, self.members)) + +class EnumLike(DBusType): + """Base class for all D-Bus types that look kind of like Enums + + Don't instantiate this class directly. + """ + class EnumValue(Base): + def __init__(self, parent, namespace, dom): + super(EnumLike.EnumValue, self).__init__(parent, namespace, dom) + + # rewrite self.name + self.short_name = dom.getAttribute('suffix') + self.name = build_name(namespace, self.short_name) + + self.value = dom.getAttribute('value') + + super(EnumLike.EnumValue, self).validate() + + def validate(self): + pass + + def get_root_namespace(self): + return self.parent.get_root_namespace() + + def get_breakdown(self): + str = '' + str += '<ul>\n' + for value in self.values: + # attempt to lookup the member.name as a type in the type system + str += '<li>%s (%s)</li>\n' % (value.short_name, value.value) + str += value.get_added() + str += value.get_changed() + str += value.get_deprecated() + str += value.get_docstring() + str += '</ul>\n' + + return str + +class Enum(EnumLike): + + devhelp_name = "enum" + + def __init__(self, parent, namespace, dom): + super(Enum, self).__init__(parent, namespace, dom) + + self.values = build_list(self, EnumLike.EnumValue, self.name, + dom.getElementsByTagNameNS(XMLNS_TP, 'enumvalue')) + +class Flags(EnumLike): + def __init__(self, parent, namespace, dom): + super(Flags, self).__init__(parent, namespace, dom) + + self.values = build_list(self, EnumLike.EnumValue, self.name, + dom.getElementsByTagNameNS(XMLNS_TP, 'flag')) + self.flags = self.values # in case you're looking for it + +class TokenBase(Base): + + devhelp_name = "macro" # it's a constant, which is near enough... + separator = '/' + + def __init__(self, parent, namespace, dom): + super(TokenBase, self).__init__(parent, namespace, dom) + self.name = namespace + '/' + self.short_name + +class ContactAttribute(TokenBase, Typed): + + def get_type_name(self): + return 'Contact Attribute' + +class HandlerCapabilityToken(TokenBase): + + def get_type_name(self): + return 'Handler Capability Token' + + def __init__(self, parent, namespace, dom): + super(HandlerCapabilityToken, self).__init__(parent, namespace, dom) + + is_family = dom.getAttribute('is-family') + assert is_family in ('yes', 'no', '') + self.is_family = (is_family == 'yes') + +class SectionBase(object): + """A SectionBase is an abstract base class for any type of node that can + contain a <tp:section>, which means the top-level Spec object, or any + Section object. + + It should not be instantiated directly. + """ + + def __init__(self, dom, spec_namespace): + + self.items = [] + + def recurse(nodes): + # iterate through the list of child nodes + for node in nodes: + if node.nodeType != node.ELEMENT_NODE: continue + + if node.tagName == 'node': + # recurse into this level for interesting items + recurse(node.childNodes) + elif node.namespaceURI == XMLNS_TP and \ + node.localName == 'section': + self.items.append(Section(self, None, node, + spec_namespace)) + elif node.tagName == 'interface': + self.items.append(Interface(self, None, node, + spec_namespace)) + + recurse(dom.childNodes) + +class Section(Base, SectionBase): + def __init__(self, parent, namespace, dom, spec_namespace): + Base.__init__(self, parent, namespace, dom) + SectionBase.__init__(self, dom, spec_namespace) + + def get_root_namespace(self): + return None + +class Spec(SectionBase): + def __init__(self, dom, spec_namespace): + # build a dictionary of errors in this spec + try: + errorsnode = dom.getElementsByTagNameNS(XMLNS_TP, 'errors')[0] + self.errors = build_dict(self, Error, + errorsnode.getAttribute('namespace'), + errorsnode.getElementsByTagNameNS(XMLNS_TP, 'error')) + except IndexError: + self.errors = {} + + # build a list of generic types + self.generic_types = reduce (lambda a, b: a + b, + map(lambda l: parse_types(self, l), + dom.getElementsByTagNameNS(XMLNS_TP, 'generic-types')), + []) + + # create a top-level section for this Spec + SectionBase.__init__(self, dom.documentElement, spec_namespace) + + # build a list of interfaces in this spec + self.interfaces = [] + def recurse(items): + for item in items: + if isinstance(item, Section): recurse(item.items) + elif isinstance(item, Interface): self.interfaces.append(item) + recurse(self.items) + + # build a giant dictionary of everything (interfaces, methods, signals + # and properties); also build a dictionary of types + self.everything = {} + self.types = {} + + for type in self.generic_types: self.types[type.short_name] = type + + for interface in self.interfaces: + self.everything[interface.name] = interface + + for method in interface.methods: + self.everything[method.name] = method + for signal in interface.signals: + self.everything[signal.name] = signal + for property in interface.properties: + self.everything[property.name] = property + for property in interface.tpproperties: + self.everything[property.name] = property + for token in interface.contact_attributes: + self.everything[token.name] = token + for token in interface.handler_capability_tokens: + self.everything[token.name] = token + + for type in interface.types: + self.types[type.short_name] = type + + # get some extra bits for the HTML + node = dom.getElementsByTagNameNS(XMLNS_TP, 'spec')[0] + self.title = getText(getChildrenByName(node, XMLNS_TP, 'title')[0]) + + try: + self.version = getText(getChildrenByName(node, XMLNS_TP, 'version')[0]) + except IndexError: + self.version = None + + self.copyrights = map(getText, + getChildrenByName(node, XMLNS_TP, 'copyright')) + + try: + license = getChildrenByName(node, XMLNS_TP, 'license')[0] + license.tagName = 'div' + license.namespaceURI = None + license.setAttribute('class', 'license') + self.license = license.toxml() + except IndexError: + self.license = '' + + # FIXME: we need to check all args for type correctness + + def get_spec(self): + return self + + def lookup(self, name, namespace=None): + key = build_name(namespace, name) + return self.everything[key] + + def lookup_type(self, type_): + if type_.endswith('[]'): + return DBusList(self.lookup_type(type_[:-2])) + + if type_ == '': return None + elif type_ in self.types: + return self.types[type_] + + raise UnknownType("Type '%s' is unknown" % type_) + + def __repr__(self): + return '%s(%s)' % (self.__class__.__name__, self.title) + +def build_dict(parent, type_, namespace, nodes): + """Build a dictionary of D-Bus names to Python objects representing that + name using the XML node for that item in the spec. + + e.g. 'org.freedesktop.Telepathy.Channel' : Interface(Channel) + + Works for any Python object inheriting from 'Base' whose XML node + implements the 'name' attribute. + """ + + def build_tuple(node): + o = type_(parent, namespace, node) + return(o.name, o) + + return dict(build_tuple(n) for n in nodes) + +def build_list(parent, type_, namespace, nodes): + return map(lambda node: type_(parent, namespace, node), nodes) + +def parse_types(parent, dom, namespace = None): + """Parse all of the types of type nodes mentioned in 't' from the node + 'dom' and insert them into the dictionary 'd'. + """ + t = [ + (SimpleType, 'simple-type'), + (Enum, 'enum'), + (Flags, 'flags'), + (Mapping, 'mapping'), + (Struct, 'struct'), + (ExternalType, 'external-type'), + ] + + types = [] + + for (type_, tagname) in t: + types += build_list(parent, type_, namespace, + dom.getElementsByTagNameNS(XMLNS_TP, tagname)) + + return types + +def parse(filename, spec_namespace): + dom = xml.dom.minidom.parse(filename) + xincludator.xincludate(dom, filename) + + spec = Spec(dom, spec_namespace) + + return spec + +if __name__ == '__main__': + parse(sys.argv[1]) diff --git a/sflphone-common/doc/dbus-api/tools/specparser.pyc b/sflphone-common/doc/dbus-api/tools/specparser.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a26b0bf150ae052a840cee27735b00ecd9ea6b0 Binary files /dev/null and b/sflphone-common/doc/dbus-api/tools/specparser.pyc differ diff --git a/sflphone-common/doc/dbus-api/tools/xincludator.py b/sflphone-common/doc/dbus-api/tools/xincludator.py new file mode 100644 index 0000000000000000000000000000000000000000..63e106ace13664eb71571342bec39780175e25bd --- /dev/null +++ b/sflphone-common/doc/dbus-api/tools/xincludator.py @@ -0,0 +1,39 @@ +#!/usr/bin/python + +from sys import argv, stdout, stderr +import codecs, locale +import os +import xml.dom.minidom + +stdout = codecs.getwriter('utf-8')(stdout) + +NS_XI = 'http://www.w3.org/2001/XInclude' + +def xincludate(dom, base, dropns = []): + remove_attrs = [] + for i in xrange(dom.documentElement.attributes.length): + attr = dom.documentElement.attributes.item(i) + if attr.prefix == 'xmlns': + if attr.localName in dropns: + remove_attrs.append(attr) + else: + dropns.append(attr.localName) + for attr in remove_attrs: + dom.documentElement.removeAttributeNode(attr) + for include in dom.getElementsByTagNameNS(NS_XI, 'include'): + href = include.getAttribute('href') + # FIXME: assumes Unixy paths + filename = os.path.join(os.path.dirname(base), href) + subdom = xml.dom.minidom.parse(filename) + xincludate(subdom, filename, dropns) + if './' in href: + subdom.documentElement.setAttribute('xml:base', href) + include.parentNode.replaceChild(subdom.documentElement, include) + +if __name__ == '__main__': + argv = argv[1:] + dom = xml.dom.minidom.parse(argv[0]) + xincludate(dom, argv[0]) + xml = dom.toxml() + stdout.write(xml) + stdout.write('\n') diff --git a/sflphone-common/doc/dbus-api/tools/xincludator.pyc b/sflphone-common/doc/dbus-api/tools/xincludator.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1172f2daf89056937b733fe218beea72eb72f4fa Binary files /dev/null and b/sflphone-common/doc/dbus-api/tools/xincludator.pyc differ diff --git a/sflphone-common/doc/misc/debian-package.txt b/sflphone-common/doc/misc/debian-package.txt deleted file mode 100644 index 23409b79dfb4227ac49caad79578864f0db85c38..0000000000000000000000000000000000000000 --- a/sflphone-common/doc/misc/debian-package.txt +++ /dev/null @@ -1,33 +0,0 @@ -***************************** HOW_TO DEBIAN PACKAGE ******************************** - -This document aims at explaining how to build a binary debian package. - -- Identify the dependencies at the runtime. You can describe them in the control file. -- Build the directory tree - - packagename_version - | - | - _____|______ - | | - \|/ \|/ - /usr DEBIAN - -- Write the control file in the DEBIAN directory (you must have at least this one file), and prerm, postinst scripts,.. -- Describe the files you need in the package, that is the files you need to make run the program (executables, libraries), docs, images, etc... and where you need it. For instance, the binary executables should be in /usr/bin, images in /usr/share, ... -- Build the debian package: - dpkg --build packagename packagename.deb . -Note: Be careful to debian package naming conventions (packagename_version_arch.deb) - -- Install the package: - dpkg --install packagename.deb (as a root) -If the dependant packages are not automatically configured, launch sudo apt-get -f install. It will configure the package you need to make run the application. -Note: The graphical interface of the debian package manager does configures the missing dependant packages automatically. - -- To remove the package, run : dpkg --remove packagename (must be root) - - - - - - diff --git a/sflphone-common/doc/misc/echange.txt b/sflphone-common/doc/misc/echange.txt deleted file mode 100644 index ee2058e56b2423aace9d6a577012cfd4ee30b0cb..0000000000000000000000000000000000000000 --- a/sflphone-common/doc/misc/echange.txt +++ /dev/null @@ -1,21 +0,0 @@ - --> INVITE (20) --> 0 0 IN IP4 192.168.1.172 c=IN IP4 192.168.1.172 m=audio 56198 - <-- 407 Proxy Auth - --> ACK 20 - --> INVITE (21) 0 0 IN IP4 192.168.1.172 c=IN IP4 192.168.1.172 m=audio 56198 (proxy-auth) - <-- 100 Trying (21 INVITE) - <-- 180 Ringing (21 INVITE) - <-- 200 OK root 26195 26195 IN IP4 192.168.1.10 c=IN IP4 192.168.1.10 m=audio 15792 - --> ACK 21 - <-- INVITE (102) root 26195 26196 IN IP4 192.168.1.124 c=IN IP4 192.168.1.124 m=audio 53628 - --> 100 Trying (102 INVITE) - --> 403 Forbidden (102 INVITE) - --> ACK (192.168.1.172) (102 ACK) - --> INVITE (103) root 26195 26197 IN IP4 192.168.1.10 c=IN IP4 192.168.1.10 m=audio 15792 - <-- 100 Trying (103 INVITE) - <-- 500 Retry Later (103 INVITE) -# -U 192.168.1.172:5060 -> 192.168.1.10:5060 - SIP/2.0 500 Retry Later..Via: SIP/2.0/UDP 192.168.1.10:5060;branch=z9hG4bK2af68dba;rport=5060..From - : <sip:124@savoirfairelinux.net>;tag=as46619d38..To: "Yan Morin 2" <sip:sfl-127@savoirfairelinux.ne - t>;tag=785584300..Call-ID: 1746410696@192.168.1.172..CSeq: 103 INVITE..Retry-After: 10..Allow: INVI - TE, ACK, OPTIONS, CANCEL, BYE, SUBSCRIBE, NOTIFY, MESSAGE, INFO, REFER, UPDATE..Content-Length: 0.. \ No newline at end of file diff --git a/sflphone-common/doc/misc/libsamplerate.png b/sflphone-common/doc/misc/libsamplerate.png deleted file mode 100644 index 4d918b85924c7934527adcaf5d744e42e47030fc..0000000000000000000000000000000000000000 Binary files a/sflphone-common/doc/misc/libsamplerate.png and /dev/null differ diff --git a/sflphone-common/doc/misc/matrice-comparaison.ods b/sflphone-common/doc/misc/matrice-comparaison.ods deleted file mode 100644 index 4543641697d34036c785a0991a5ab26b8918ec09..0000000000000000000000000000000000000000 Binary files a/sflphone-common/doc/misc/matrice-comparaison.ods and /dev/null differ diff --git a/sflphone-common/doc/misc/outgoingcall.txt b/sflphone-common/doc/misc/outgoingcall.txt deleted file mode 100644 index b08053381261641d87ab6995b748c971bfc66a86..0000000000000000000000000000000000000000 --- a/sflphone-common/doc/misc/outgoingcall.txt +++ /dev/null @@ -1,15 +0,0 @@ -1. outgoingCall() -1.1 generateNewCallId() (short) -1.2 pushBackNewCall() -1.2.1 new Call(id, type, _voIPLinkVector.at(DFT_VOIP_LINK)) -1.2.1.1 _state = NotExist; -1.2.1.2 _voIPLink->newOutgoingCall(_id); -1.2.1.2.1 new SipCall(callid, Manager::instance().getCodecDescVector())); -1.2.1.2.2 _sipcallVector.push_back(sipcall); -1.2.1.2.3 sipcall->setStandBy(true); -1.2.2 _callVector.push_back(call); -1.3 call->setStatus(string(TRYING_STATUS)); -1.4 call->setState(Progressing); -1.5 call->setCallerIdNumber(to); -1.6 call->outgoingCall(to); - diff --git a/sflphone-common/doc/misc/playtone.txt b/sflphone-common/doc/misc/playtone.txt deleted file mode 100644 index f8efb9212fd25fbdd0dd73ffa8e79d65b6608b11..0000000000000000000000000000000000000000 --- a/sflphone-common/doc/misc/playtone.txt +++ /dev/null @@ -1,9 +0,0 @@ -Appel: -playtone s1 [joue tant que playtone = false] -playdtmf s2 1 [si playtone = true ( playtone = false) flush, start playdtmf] -playdtmf s3 0 [] -playdtmf s4 3 [] - - - - diff --git a/sflphone-common/doc/misc/sflphoneqt-startup.txt b/sflphone-common/doc/misc/sflphoneqt-startup.txt deleted file mode 100644 index 5b2af9b903d9f53eec081a8969d88993112853db..0000000000000000000000000000000000000000 --- a/sflphone-common/doc/misc/sflphoneqt-startup.txt +++ /dev/null @@ -1,61 +0,0 @@ -main.cpp: main() --> app = new SFLPhoneApp - -> new SessionIO, 3999 - -> new session - -> new SessionId - -> new SessionIO (create) - -> Requester::registerSession() - -> envoie session a ConfigurationManager - -> envoie session a PhoneLineManager(initialize) - -> new Session(session) - -> new Account <-- supprimé - -> configure le nombre de ligne de PhoneLineManager::setNbLines - -> new PhoneLine - - -> new Request Object (commande) - -> new NumericKeypad --> new and show splash --> sfl = new SFLPhoneWindow - -> positionne fenêtre - -> new ConfigurationPanel - -> connection updates au panel - -> connection bouton panel a la fenetre - -> peinture apres 50 milli-seconde - -> initialisation graphique - --> initConnections(sfl) - -> associe les PhoneLineButton au PhoneLine - -> associe needRegister - -> associe soundDriverChanged - -> connecte les boutons de la fenetre au phonelinemanager - -> associe phonelinemanager au lcd (messages texet) - -> associe evenement daemon - -> associe lauching (daemon) - -> associe status - phone line - -> associe evenement update, setup --> launch - -> Launcher->start() --> PhoneLineManager::connect et attend "connected" --> loadSkin --> exec - -Evenement: --Lorsque le PhoneLineManager est connectée (connected) - le splash disparait splash.hide() --Lorsque le PhoneLineManager gère le getEvents - app.handleArg() - -TCPSessionIOCreator::create --> TCPSessionIO::connected| - PhoneLineManagerImpl::connected| - -> PhoneLineManagerImpl::readyToSendStatus| - -> PhoneLineManagerImpl::startSession() - -> mSession::getCallStatus() - -> SFLPhoneWindow::show - -> splash::hide - -CallStatusRequest - -> onSuccess -> PhoneLineManager::selectLine() - -> PhoneLineManager::handleEvents() - -> onEntry -> CallStatus::execute() -> PhoneLineManager::addCall() - -> onError -> PhoneLineManager::errorOnCallStatus() diff --git a/sflphone-common/doc/screenshots/accounts.png b/sflphone-common/doc/screenshots/accounts.png deleted file mode 100644 index 2a1d033892ad357faf1e79c20141ffb9b6bd1d80..0000000000000000000000000000000000000000 Binary files a/sflphone-common/doc/screenshots/accounts.png and /dev/null differ diff --git a/sflphone-common/doc/screenshots/audio-parameters.png b/sflphone-common/doc/screenshots/audio-parameters.png deleted file mode 100644 index 7be7badab519fd06a3c5ef00f9c2916f12511f4b..0000000000000000000000000000000000000000 Binary files a/sflphone-common/doc/screenshots/audio-parameters.png and /dev/null differ diff --git a/sflphone-common/doc/screenshots/desktop-notif-voice mail.png b/sflphone-common/doc/screenshots/desktop-notif-voice mail.png deleted file mode 100644 index 4d2899877f696477da49f7cee1935e52d43189bf..0000000000000000000000000000000000000000 Binary files a/sflphone-common/doc/screenshots/desktop-notif-voice mail.png and /dev/null differ diff --git a/sflphone-common/doc/screenshots/desktop-notification.png b/sflphone-common/doc/screenshots/desktop-notification.png deleted file mode 100644 index c854b8252253f8fdb9c89ee41fc02b2ef2ca9c3a..0000000000000000000000000000000000000000 Binary files a/sflphone-common/doc/screenshots/desktop-notification.png and /dev/null differ diff --git a/sflphone-common/doc/screenshots/gtk gui.png b/sflphone-common/doc/screenshots/gtk gui.png deleted file mode 100644 index 958beb4ee40b156630d41ecb7c5ce77f35cb4256..0000000000000000000000000000000000000000 Binary files a/sflphone-common/doc/screenshots/gtk gui.png and /dev/null differ diff --git a/sflphone-common/doc/screenshots/several-calls.png b/sflphone-common/doc/screenshots/several-calls.png deleted file mode 100644 index 65dc12dbcbba742c04f3d974bca9fe660a004756..0000000000000000000000000000000000000000 Binary files a/sflphone-common/doc/screenshots/several-calls.png and /dev/null differ diff --git a/sflphone-common/doc/screenshots/sflphoneDialpad_gtk_0.8.png b/sflphone-common/doc/screenshots/sflphoneDialpad_gtk_0.8.png deleted file mode 100644 index 00d6ce8a0620d1a81244146884b22cf641a26906..0000000000000000000000000000000000000000 Binary files a/sflphone-common/doc/screenshots/sflphoneDialpad_gtk_0.8.png and /dev/null differ diff --git a/sflphone-common/doc/screenshots/sflphone_gtk_0.8.png b/sflphone-common/doc/screenshots/sflphone_gtk_0.8.png deleted file mode 100644 index 39b01d78d6c16ed71c20c13b548b7f5f2db9ff33..0000000000000000000000000000000000000000 Binary files a/sflphone-common/doc/screenshots/sflphone_gtk_0.8.png and /dev/null differ diff --git a/sflphone-common/doc/screenshots/sflphone_metal.png b/sflphone-common/doc/screenshots/sflphone_metal.png deleted file mode 100644 index ed34ee700257aa068667d3ebf6db1966f7cbd1c9..0000000000000000000000000000000000000000 Binary files a/sflphone-common/doc/screenshots/sflphone_metal.png and /dev/null differ diff --git a/sflphone-common/doc/screenshots/sflphone_qt3_0.6.2.png b/sflphone-common/doc/screenshots/sflphone_qt3_0.6.2.png deleted file mode 100644 index 3b53ce3190013f36ff1a4dc8bb54b051f51ca865..0000000000000000000000000000000000000000 Binary files a/sflphone-common/doc/screenshots/sflphone_qt3_0.6.2.png and /dev/null differ diff --git a/sflphone-common/doc/sflphone_video/abstract.odt b/sflphone-common/doc/sflphone_video/abstract.odt deleted file mode 100644 index e9263f9cff27f087345e37418b363eba096349b0..0000000000000000000000000000000000000000 Binary files a/sflphone-common/doc/sflphone_video/abstract.odt and /dev/null differ diff --git a/sflphone-common/doc/sflphone_video/ressources.odt b/sflphone-common/doc/sflphone_video/ressources.odt deleted file mode 100644 index 1c9cfed4cc410d060e1f4fc2bc4b959ccf66764b..0000000000000000000000000000000000000000 Binary files a/sflphone-common/doc/sflphone_video/ressources.odt and /dev/null differ diff --git a/sflphone-common/libs/pjproject/autogen.sh b/sflphone-common/libs/pjproject/autogen.sh old mode 100644 new mode 100755 diff --git a/sflphone-common/src/audio/audiortp/AudioRtpSession.h b/sflphone-common/src/audio/audiortp/AudioRtpSession.h index 9213eefad2698f2a266d60b27e54a6f0c187a86c..ad271a61989e6dee80d4669935f0d4cd8295fe6e 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpSession.h +++ b/sflphone-common/src/audio/audiortp/AudioRtpSession.h @@ -249,7 +249,7 @@ namespace sfl { template <typename D> AudioRtpSession<D>::~AudioRtpSession() { - _debug ("Rtp: Delete AudioRtpSession instance"); + _debug ("RTP: Delete AudioRtpSession instance"); try { terminate(); @@ -273,11 +273,9 @@ namespace sfl { void AudioRtpSession<D>::initBuffers() { // Set sampling rate, main buffer choose the highest one - // _audiolayer->getMainBuffer()->setInternalSamplingRate(_codecSampleRate); _manager->getAudioDriver()->getMainBuffer()->setInternalSamplingRate(_codecSampleRate); // may be different than one already setted - // converterSamplingRate = _audiolayer->getMainBuffer()->getInternalSamplingRate(); _converterSamplingRate = _manager->getAudioDriver()->getMainBuffer()->getInternalSamplingRate(); // initialize SampleRate converter using AudioLayer's sampling rate @@ -311,20 +309,23 @@ namespace sfl { { _audiocodec = audiocodec; - _debug ("Init audio RTP session: codec payload %i", _audiocodec->getPayload()); + _debug ("RTP: Init codec payload %i", _audiocodec->getPayload()); _codecSampleRate = _audiocodec->getClockRate(); _codecFrameSize = _audiocodec->getFrameSize(); + _debug("RTP: Codec sampling rate: %d", _codecSampleRate); + _debug("RTP: Codec frame size: %d", _codecFrameSize); + //TODO: figure out why this is necessary. if (_audiocodec->getPayload() == 9) { - _debug ("Setting payload format to G722"); + _debug ("RTP: Setting payload format to G722"); static_cast<D*>(this)->setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) _audiocodec->getPayload(), _audiocodec->getClockRate())); } else if (_audiocodec->hasDynamicPayload()) { - _debug ("Setting a dynamic payload format"); + _debug ("RTP: Setting a dynamic payload format"); static_cast<D*>(this)->setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) _audiocodec->getPayload(), _audiocodec->getClockRate())); } else if (!_audiocodec->hasDynamicPayload() && _audiocodec->getPayload() != 9) { - _debug ("Setting a static payload format"); + _debug ("RTP: Setting a static payload format"); static_cast<D*>(this)->setPayloadFormat (ost::StaticPayloadFormat ( (ost::StaticPayloadType) _audiocodec->getPayload())); } } @@ -333,7 +334,7 @@ namespace sfl { void AudioRtpSession<D>::setDestinationIpAddress(void) { if (_ca == NULL) { - _warn ("Rtp: Sipcall is gone."); + _error ("RTP: Sipcall is gone."); throw AudioRtpSessionException(); } @@ -343,7 +344,7 @@ namespace sfl { _remote_ip = ost::InetHostAddress(_ca->getLocalSDP()->get_remote_ip().c_str()); if (!_remote_ip) { - _warn("Rtp: Target IP address (%s) is not correct!", + _warn("RTP: Target IP address (%s) is not correct!", _ca->getLocalSDP()->get_remote_ip().data()); return; } @@ -355,7 +356,7 @@ namespace sfl { _ca->getLocalSDP()->get_remote_ip().data(), _remote_port); if (! static_cast<D*>(this)->addDestination (_remote_ip, _remote_port)) { - _warn("Rtp: Can't add new destination to session!"); + _warn("RTP: Can't add new destination to session!"); return; } } @@ -367,7 +368,7 @@ namespace sfl { // This method remove the current destination entry if(!static_cast<D*>(this)->forgetDestination(_remote_ip, _remote_port, _remote_port+1)) - _warn("Rtp: Could not remove previous destination"); + _warn("RTP: Could not remove previous destination"); // new destination is stored in call // we just need to recall this method @@ -611,56 +612,58 @@ namespace sfl { template <typename D> int AudioRtpSession<D>::startRtpThread (AudioCodec* audiocodec) { - _debug("Starting main thread"); + _debug("RTP: Starting main thread"); setSessionTimeouts(); setSessionMedia(audiocodec); - initBuffers(); + initBuffers(); return start(_mainloopSemaphore); } template <typename D> void AudioRtpSession<D>::run () { - // Timestamp must be initialized randomly - _timestamp = static_cast<D*>(this)->getCurrentTimestamp(); + // Timestamp must be initialized randomly + _timestamp = static_cast<D*>(this)->getCurrentTimestamp(); int sessionWaiting; int threadSleep = 0; - if (_codecSampleRate != 0) - { threadSleep = (_codecFrameSize * 1000) / _codecSampleRate; } - else - { threadSleep = _layerFrameSize; } + if (_codecSampleRate != 0){ + threadSleep = (_codecFrameSize * 1000) / _codecSampleRate; + } + else { + threadSleep = _layerFrameSize; + } TimerPort::setTimer (threadSleep); if (_audiolayer == NULL) { - _debug("For some unknown reason, audiolayer is null, just as \ - we were about to start the audio stream"); + _error("RTP: Error: Audiolayer is null, cannot start the audio stream"); throw AudioRtpSessionException(); } - _ca->setRecordingSmplRate(_audiocodec->getClockRate()); + _ca->setRecordingSmplRate(_audiocodec->getClockRate()); - // Start audio stream (if not started) AND flush all buffers (main and urgent) - _manager->getAudioDriver()->startStream(); + // Start audio stream (if not started) AND flush all buffers (main and urgent) + _manager->getAudioDriver()->startStream(); static_cast<D*>(this)->startRunning(); - _debug ("Entering RTP mainloop for callid %s",_ca->getCallId().c_str()); + _debug ("RTP: Entering mainloop for call %s",_ca->getCallId().c_str()); while (!testCancel()) { - // ost::MutexLock lock(*(_manager->getAudioLayerMutex())); + // ost::MutexLock lock(*(_manager->getAudioLayerMutex())); - _manager->getAudioLayerMutex()->enter(); + _manager->getAudioLayerMutex()->enter(); - // converterSamplingRate = _audiolayer->getMainBuffer()->getInternalSamplingRate(); - _manager->getAudioDriver()->getMainBuffer()->getInternalSamplingRate(); + // converterSamplingRate = _audiolayer->getMainBuffer()->getInternalSamplingRate(); + _converterSamplingRate = _manager->getAudioDriver()->getMainBuffer()->getInternalSamplingRate(); - // Send session - sessionWaiting = static_cast<D*>(this)->isWaiting(); + sessionWaiting = static_cast<D*>(this)->isWaiting(); + + // Send session if(_eventQueue.size() > 0) { sendDtmfEvent(_eventQueue.front()); } @@ -687,7 +690,7 @@ namespace sfl { TimerPort::incTimer (threadSleep); } - _debug ("Left RTP main loop for callid %s",_ca->getCallId().c_str()); + _debug ("RTP: Left main loop for call%s", _ca->getCallId().c_str()); } } diff --git a/sflphone-common/src/audio/codecs/Makefile.am b/sflphone-common/src/audio/codecs/Makefile.am index 230ee7bbc0dce19ecfd5f02f18236afefb84965d..e338dc3fb5f898a86039e174c6705370fc20b91a 100644 --- a/sflphone-common/src/audio/codecs/Makefile.am +++ b/sflphone-common/src/audio/codecs/Makefile.am @@ -49,7 +49,7 @@ CELT_LIB = libcodec_celt.so libcodec_celt_so_SOURCES = celtcodec.cpp libcodec_celt_so_CFLAGS = -fPIC -g -Wall libcodec_celt_so_CXXFLAGS = -fPIC -g -Wall -libcodec_celt_so_LDFLAGS = --shared -lc -lcelt $(CELT_NIMP) +libcodec_celt_so_LDFLAGS = --shared -lc -lcelt0 $(CELT_NIMP) INSTALL_CELT_RULE = install-libcodec_celt_so endif diff --git a/sflphone-common/src/audio/codecs/celtcodec.cpp b/sflphone-common/src/audio/codecs/celtcodec.cpp index 8787bd6b6b3f7c8bfeec6fbf31464de24e31816c..ad7a4eac100e24ce25e3e9a5a10f3df12fdc2801 100644 --- a/sflphone-common/src/audio/codecs/celtcodec.cpp +++ b/sflphone-common/src/audio/codecs/celtcodec.cpp @@ -26,27 +26,59 @@ class Celt : public AudioCodec { public: - Celt (int payload=0) - : AudioCodec (payload, "celt") { - _clockRate = 44100; - _frameSize = 512; // fixed frameSize, TODO: support variable size from 64 to 512 + Celt (int payload=0) : AudioCodec (payload, "celt") { + + _clockRate = 32000; + _frameSize = 320; // fixed frameSize, TODO: support variable size from 64 to 512 _channel = 1; _bitrate = 0; _bandwidth = 0; + initCelt(); + } Celt (const Celt&); Celt& operator= (const Celt&); void initCelt() { - printf ("init celt"); + printf ("Celt: Init Celt codec"); + + int error = 0; + + _mode = celt_mode_create (_clockRate, _frameSize, &error); + + if(error != CELT_OK) { + switch(error) { + case CELT_BAD_ARG: + printf("Celt: Error: An (or more) invalid argument (e.g. out of range)\n"); + break; + case CELT_INVALID_MODE: + printf("Celt: Error: The mode struct passed is invalid\n"); + break; + case CELT_INTERNAL_ERROR: + printf("Celt: Error: An internal error was detected\n"); + break; + case CELT_CORRUPTED_DATA: + printf("Celt: Error: The data passed (e.g. compressed data to decoder) is corrupted\n"); + break; + case CELT_UNIMPLEMENTED: + printf("Celt: Error: Invalid/unsupported request numbe\n"); + break; + case CELT_INVALID_STATE: + printf("Celt: Error: An encoder or decoder structure is invalid or already freed\n"); + break; + case CELT_ALLOC_FAIL: + printf("Celt: Error: Memory allocation has failed\n"); + break; + default: + printf("Celt: Error"); + } - mode = celt_mode_create (_clockRate, _channel, _frameSize, NULL); - // celt_mode_info(mode, CELT_GET_LOOKAHEAD, &skip); + } - if (mode == NULL) { - printf ("failed to create a mode"); + if (_mode == NULL) { + printf ("Celt: Error: Failed to create Celt mode"); } // bytes_per_packet = 1024; @@ -58,11 +90,12 @@ class Celt : public AudioCodec // celt_mode_info(mode, CELT_GET_FRAME_SIZE, &frame_size); // celt_mode_info(mode, CELT_GET_NB_CHANNELS, &_channel); - enc = celt_encoder_create (mode); + _enc = celt_encoder_create (_mode, _channel, &error); - dec = celt_decoder_create (mode); + _dec = celt_decoder_create (_mode, _channel, &error); - celt_encoder_ctl (enc,CELT_SET_COMPLEXITY (10)); + celt_encoder_ctl (_enc, CELT_SET_COMPLEXITY (10)); + celt_decoder_ctl(_dec, CELT_SET_COMPLEXITY (10)); } @@ -72,32 +105,34 @@ class Celt : public AudioCodec void terminateCelt() { - celt_encoder_destroy (enc); - celt_decoder_destroy (dec); + celt_encoder_destroy (_enc); + celt_decoder_destroy (_dec); + + celt_mode_destroy(_mode); } virtual int codecDecode (short *dst, unsigned char *src, unsigned int size) { int err = 0; - err = celt_decode (dec, src, size, (celt_int16_t*) dst); - return _frameSize * sizeof (celt_int16_t); + err = celt_decode (_dec, src, size, (celt_int16*) dst); + return _frameSize * sizeof (celt_int16); } virtual int codecEncode (unsigned char *dst, short *src, unsigned int size) { int len = 0; - len = celt_encode (enc, (celt_int16_t *) src, (celt_int16_t *) src, dst, 512); + len = celt_encode (_enc, (celt_int16*) src, (celt_int16 *) src, dst, 512); // returns the number of bytes writen return len; } private: - CELTMode *mode; + CELTMode *_mode; - CELTEncoder *enc; - CELTDecoder *dec; + CELTEncoder *_enc; + CELTDecoder *_dec; - celt_int32_t _celt_frame_size; - celt_int32_t skip; + celt_int32 _celt_frame_size; + celt_int32 skip; }; diff --git a/sflphone-common/src/audio/codecs/speexcodec_nb.cpp b/sflphone-common/src/audio/codecs/speexcodec_nb.cpp index a2603fc8271e1430ca664edce67d07e3205b3ad4..9099dca71fbc7a69d71982394794c59f1d95492e 100644 --- a/sflphone-common/src/audio/codecs/speexcodec_nb.cpp +++ b/sflphone-common/src/audio/codecs/speexcodec_nb.cpp @@ -39,7 +39,7 @@ class Speex : public AudioCodec _clockRate = 8000; _frameSize = 160; // samples, 20 ms at 8kHz _channel = 1; - _bitrate = 0; + _bitrate = 24; _bandwidth = 0; initSpeex(); } diff --git a/sflphone-common/src/audio/codecs/speexcodec_wb.cpp b/sflphone-common/src/audio/codecs/speexcodec_wb.cpp index 9d3b618674d016fdd939b08e30e833aa70d47bf0..28e099791f511dd838fdedc5c37dd4e4f20d4265 100644 --- a/sflphone-common/src/audio/codecs/speexcodec_wb.cpp +++ b/sflphone-common/src/audio/codecs/speexcodec_wb.cpp @@ -39,7 +39,7 @@ class Speex : public AudioCodec _clockRate = 16000; _frameSize = 320; // 20 ms at 16 kHz _channel = 1; - _bitrate = 0; + _bitrate = 42; _bandwidth = 0; initSpeex(); } diff --git a/sflphone-common/src/dbus/callmanager-introspec.xml b/sflphone-common/src/dbus/callmanager-introspec.xml index 83a5c32acf22c3086a8f347113bc5733c2ab3be6..534bde252d506dcda4b622b0667c7b86005d8510 100644 --- a/sflphone-common/src/dbus/callmanager-introspec.xml +++ b/sflphone-common/src/dbus/callmanager-introspec.xml @@ -1,506 +1,699 @@ <?xml version="1.0" encoding="UTF-8" ?> -<!-- Comment --> -<!--*< File comment --> +<node name="/callmanager-introspec" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> + <interface name="org.sflphone.SFLphone.CallManager"> -<node name="/org/sflphone/SFLphone" xmlns:dx="http://psiamp.org/dtd/doxygen_dbusxml.dtd"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>The CallManager interface is used to manage any call related actions.</p> + <p>Since SFLphone-daemon support multiple incoming/outgoing calls, any actions involving a specific call must address the method by the means of a unique callID. SFLphone-clients is responsible to generate the callID on outgoing call. On the other hand, SFLphone-daemon will generate a unique callID on incoming calls.</p> + </tp:docstring> + <method name="placeCall" tp:name-for-bindings="placeCall"> + <tp:docstring> + <p>This is the main method in order to place a new call. The call is registered to the daemon using this method.</p> + </tp:docstring> + <arg type="s" name="accountID" direction="in"> + <tp:docstring> + The ID of the account you want to make a call with. If the call is to be placed whithout any account by the means of a SIP URI (i.e. sip:num@server), the "IP2IP_PROFILE" is passed as the accountID. For more details about accounts see the configuration manager interface. + </tp:docstring> + </arg> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The callID is a unique identifier that must be randomly generated on the client's side. Any subsequent actions refering to this call must use this callID. + </tp:docstring> + </arg> + <arg type="s" name="to" direction="in"> + <tp:docstring> + If bound to a VoIP account, then the argument is the phone number. In case of calls involving "IP2IP_PROFILE", a complete SIP URI must be specified. + </tp:docstring> + </arg> + </method> - <!--* The CallManager interface is used to manage any call related - actions. + <method name="placeCallFirstAccount" tp:name-for-bindings="placeCallFirstAccount"> + <tp:added version="0.9.8"/> + <tp:docstring> + Place a call with the fist registered account, regarding to the account list order. + <tp:rationale> + Use this function when you don't have any information about the accounts used (Ex: Firefly mozilla extension) + </tp:rationale> + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The callID is a unique identifier that must be randomly generated on the client's side. Any subsequent actions refering to this call must use this callID. + </tp:docstring> + </arg> + <arg type="s" name="to" direction="in"> + <tp:docstring> + If bound to a VoIP account, then the argument is the phone number. In case of calls involving "IP2IP_PROFILE", a complete SIP URI must be specified. + </tp:docstring> + </arg> + </method> - Since SFLphone-daemon support multiple incoming/outgoing - calls, any actions involving a specific call must address the - method by the means of a unique callID. SFLphone-clients is - responsible to generate the callID on outgoing call. On the - otehr hand, SFLphone-daemon will generate a unique callID on - incoming calls. + <method name="refuse" tp:name-for-bindings="refuse"> + <tp:docstring> + Refuse an incoming call. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The callID. + </tp:docstring> + </arg> - Actions are performed asynchronously, SFLphone-client should - subscribe to the callStateChanged signal in order to be - notified on updates in call status. - --> - <interface name="org.sflphone.SFLphone.CallManager"> - - <!--* This is the main method in order to place a new call. The - call is registered to the daemon using this method - specified a unique identifier and VoIP Accout to be bound with. - - The account is specified by its accountID. - - If the call is to be placed whithout any account by the - means of a SIP URI (i.e. sip:num@server), the - "IP2IP_PROFILE" is passed as the accountID. For more - details about accounts see the configuration manager interface. - - The callID is a unique identifier that must be randomly - generated on sflphone-client's side. Any subsequent - actions refering to this call must use this callID. - - If bound to a VoIP account, the to argument is the phone - number. In case of calls involving "IP2IP_PROFILE", a - complete SIP URI must be specified. - - @param[in] input accountID - @param[in] input callID - @param[in] input to - --> - - <method name="placeCall"> - <arg type="s" name="accountID" direction="in"/> - <arg type="s" name="callID" direction="in" /> - <arg type="s" name="to" direction="in" /> - </method> - - <method name="placeCallFirstAccount"> - <arg type="s" name="callID" direction="in"/> - <arg type="s" name="to" direction="in"/> - </method> - - <method name="refuse"> - <!--* Method called to refuse an incoming call. - - @param[in] input callID - --> - <arg type="s" name="callID" direction="in"/> - </method> - - <method name="accept"> - <!--* Method called to answer an incoming call. Automatically put - the current call on state HOLD. - - @param[in] input callID - --> - <arg type="s" name="callID" direction="in"/> - </method> - - <method name="hangUp"> - <!--* Method called to hangup a call in state "CURRENT" or "HOLD". - - @param[in] input callID - --> - <arg type="s" name="callID" direction="in"/> - </method> - - <method name="hangUpConference"> - <!--* This method will hangup a conference in state "" - every call participating to the conference. - - @param[in] input confID - --> - <arg type="s" name="confID" direction="in"/> - </method> - - <method name="hold"> - <!--* Place this call on state HOLD. - - @param[in] input confID - --> - <arg type="s" name="callID" direction="in"/> - </method> - - <method name="unhold"> - <!--* Place this call on state CURRENT. - - @param[in] input confID - --> - <arg type="s" name="callID" direction="in"/> - </method> - - <method name="transfert"> - <!--* Transfer a call to given phone number. - - @param[in] input confID - @param[in] input to - --> - <arg type="s" name="callID" direction="in"/> - <arg type="s" name="to" direction="in"/> - </method> - - <method name="playDTMF"> - <!--* Dual-Tone multi-frequency. Tell SFLphone-daemon to play - dial tones. A SIP INFO message is sent to notify the server. - - @param[in] input Unicode charter for pressed key - --> - <arg type="s" name="key" direction="in"/> - </method> - - <method name="startTone"> - <!--* This method is used to start audio stream and play tone. - - @param[in] input confID - --> - <arg type="i" name="start" direction="in"/> - <arg type="i" name="type" direction="in"/> - </method> - - <method name="setVolume"> - <!--* This method sets the volume using a linear scale - [0,100]. Pulseaudio has its own mechanism to modify - application volume. This method is enabled only if the - ALSA API is used. - - @param[in] input device - @param[in] input value - --> - <arg type="s" name="device" direction="in"/> - <arg type="d" name="value" direction="in"/> - </method> - - <method name="getVolume"> - <!--* This method is enabled only if the ALSA API is used, Pulseaudio - has its own mechanism to modify application volume. Return - a value on a linear scale [0,100]. - - @param[in] input device - @param[out] output value - --> - <arg type="s" name="device" direction="in"/> - <arg type="d" name="value" direction="out"/> - </method> - - <method name="joinParticipant"> - <!--* Join two participants together to create a 3-way - conference including current SFLphone-client. - conferenceCreated signal is emited on success. - - @param[in] input sel_callID - @param[in] input drag_callID - --> - <arg type="s" name="sel_callID" direction="in"/> - <arg type="s" name="drag_callID" direction="in"/> - </method> - - <method name="addParticipant"> - <!--* Join a new particiant to an already created conference. - conferenceChaged signal is emited on success. - - @param[in] input callID - @param[in] input confID - --> - <arg type="s" name="callID" direction="in"/> - <arg type="s" name="confID" direction="in"/> - </method> - - <method name="addMainParticipant"> - <!--* As SFLphone-daemon can handle multiple calls and - conferences. It may happen that SFLphone-client's user - leave a conference to answer an incoming call or - send new ones. This method is used to reintroduce - SFLphone-client's user into the conference. - - It put the current call on state HOLD or detach - SFLphone-client's user from the another conference. - - @param[in] input confID - --> - <arg type="s" name="confID" direction="in"/> - </method> - - <method name="detachParticipant"> - <!--* Detach the given call from the conference. If only one - participant is left, the conference is deleted and the - "conferenceRemoved" signal is emited. - - @param[in] input callID - --> - <arg type="s" name="callID" direction="in"/> - </method> - - <method name="joinConference"> - <!--* Method used to join two conference together. - - @param[in] input sel_confID - @param[in] input drag_confID - --> - <arg type="s" name="sel_confID" direction="in"/> - <arg type="s" name="drag_confID" direction="in"/> - </method> - - <method name="getConferenceDetails"> - <!--* Returns a hashtable containing conference details. - - "CONFID" - "CONF_STATE" - - @param[in] input confID - @param[out] output a infos - --> - <arg type="s" name="callID" direction="in"/> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <arg type="a{ss}" name="infos" direction="out"/> - </method> - - <method name="getConferenceList"> - <!--* Returns a list containing all active confID in SFLphone-daemon. - - @param[out] output list - --> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="setRecording"> - <arg type="s" name="callID" direction="in"/> - </method> - - <method name="getIsRecording"> - <arg type="s" name="callID" direction="in"/> - <arg type="b" name="isRecording" direction="out"/> - </method> - - <method name="getCallDetails"> - <!--* Returns a hashtable containing call details. - - "ACCOUNTID" - "PEER_NUMBER" - "PEER_NAME" - "DISPLAY_NAME" Name to display - "CALL_STATE" The state of the call - "CALL_TYPE" SIP or IAX - - @param[in] input callID - @param[out] output a infos - --> - <arg type="s" name="callID" direction="in"/> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <arg type="a{ss}" name="infos" direction="out"/> - </method> - - <method name="getCallList"> - <!--* Returns a list containing all active callID in SFLphone-daemon. - - @param[out] output list - --> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="getCurrentCallID"> - <!--* Returns the CURRENT callID - - @param[out] output callID - --> - <arg type="s" name="callID" direction="out"/> - </method> - - <method name="getCurrentCodecName"> - <arg type="s" name="callID" direction="in"/> - <arg type="s" name="codecName" direction="out"/> - </method> - - <signal name="currentSelectedCodec"> - <arg type="s" name="callID" direction="out" /> - <arg type="s" name="codecName" direction="out"/> - </signal> - - <signal name="incomingCall"> - <!--* Signal sent to notify incoming calls. - - The callID generated by the daemon and must be stored - by SFLphone-client in order to address other action for - this call. - - @param[in] input accountID - @param[in] input callID - @param[in] input from - --> - <arg type="s" name="accountID" /> - <arg type="s" name="callID" /> - <arg type="s" name="from" /> - </signal> - - <signal name="incomingMessage"> - <arg type="s" name="accountID" direction="out" /> - <arg type="s" name="message" direction="out"/> - </signal> - - <signal name="callStateChanged"> - <!--* Signal emited by SFLphone-daemon to notify of a chage in - call state. - - The following is a liste of possible call state: - - "INCOMING" Initial state of incoming calls - "RINGING" Initial state of received outgoing call - "CURRENT" The normal active state of an answered call - "HUNGUP" Notify that the call has been hungup by peer - "BUSY" - "FAILURE" Signal emited on failure to answer the call - "HOLD" CAll state is now on hold - "UNHOLD_RECORD" CAll state is now on CURRENT (pursue recording) - "UNHOLD_CURRENT" CAll state is now on CURRENT - - @param[in] input accountID - @param[in] input state - --> - <arg type="s" name="callID" direction="out"/> - <arg type="s" name="state" direction="out"/> - </signal> - - <signal name="conferenceChanged"> - <!--* Signal emited by SFLphone-daemon to notify of a chage in - conference state. - - The following is a liste of possible conference state: - - "ACTIVE_ATACHED" Conference state is active - "ACTIVE_DETACHED" Conference state is active - "HOLD" Conference is on hold - - @param[in] input accountID - @param[in] input state - --> - <arg type="s" name="confID" direction="out"/> - <arg type="s" name="state" direction="out"/> - </signal> - - <method name="getParticipantList"> - <!--* Return a vector (or a list) containig the callIP of every - participant to a given conference. SFLphone-client should - keep and update the list of participant. - - @param[in] input accountID - @param[out] output List of callID - --> - <arg type="s" name="confID" direction="in"/> - <arg type="as" name="list" direction="out"/> - </method> - - <signal name="conferenceCreated"> - <!--* Emited when a new conference is created. SFLphone-client - is reponsible to store the confID and call - getParticipantList to update display. - - param[out] output Newly generated confID - --> - <arg type="s" name="confID" direction="out"/> - </signal> - - <signal name="conferenceRemoved"> - <!--* Emited when a new conference is removed. SFLphone-client - should have kept a list of current participant in order to - display modification. - - @param[out] output confID - --> - <arg type="s" name="confID" direction="out"/> - </signal> - - <method name="holdConference"> - <!--* Put the hole conference on hold. Every call participating - to this conference will be update to state HOLD. - - @param[in] input confID - --> - <arg type="s" name="confID" direction="in"/> - </method> - - <method name="unholdConference"> - <!--* Put the conference on state ACTIVE. Every call participating - to this conference will be updated to state UNHOLD. - - @param[in] input confID - --> - <arg type="s" name="confID" direction="in"/> - </method> - - <signal name="sipCallStateChanged"> - <arg type="s" name="callID" direction="out"/> - <arg type="s" name="state" direction="out"/> - <arg type="i" name="code" direction="out"/> - </signal> - - <signal name="registrationStateChanged"> - <arg type="s" name="accountID" direction="out"/> - <arg type="s" name="state" direction="out"/> - <arg type="i" name="code" direction="out"/> - </signal> - - <signal name="voiceMailNotify"> - <arg type="s" name="accountID" direction="out"/> - <arg type="i" name="count" direction="out"/> - </signal> - - <signal name="volumeChanged"> - <arg type="s" name="device" direction="out"/> - <arg type="d" name="value" direction="out"/> - </signal> - - <signal name="transferSucceded"> - </signal> - - <signal name="transferFailed"> - </signal> - - <signal name="secureSdesOn"> - <arg type="s" name="callID" direction="out" /> - </signal> - - <signal name="secureSdesOff"> - <arg type="s" name="callID" direction="out" /> - </signal> - - <!-- ZRTP Methods and Signals --> - <signal name="secureZrtpOn"> - <arg type="s" name="callID" direction="out" /> - <arg type="s" name="cipher" direction="out" /> - </signal> - - <signal name="secureZrtpOff"> - <arg type="s" name="callID" direction="out" /> - </signal> - - <signal name="confirmGoClear"> - <arg type="s" name="callID" direction="out" /> - </signal> - - <signal name="zrtpNegotiationFailed"> - <arg type="s" name="callID" direction="out" /> - <arg type="s" name="reason" direction="out" /> - <arg type="s" name="severity" direction="out" /> - </signal> - - <signal name="zrtpNotSuppOther"> - <arg type="s" name="callID" direction="out" /> - </signal> - - <signal name="showSAS"> - <arg type="s" name="callID" direction="out" /> - <arg type="s" name="sas" direction="out" /> - <arg type="b" name="verified" direction="out" /> - </signal> - - <method name="setSASVerified"> - <arg type="s" name="callID" direction="in"/> - </method> - - <method name="resetSASVerified"> - <arg type="s" name="callID" direction="in"/> - </method> - - <method name="setConfirmGoClear"> - <arg type="s" name="callID" direction="in"/> - </method> - - <method name="requestGoClear"> - <arg type="s" name="callID" direction="in"/> - </method> - - <method name="acceptEnrollment"> - <arg type="s" name="callID" direction="in"/> - <arg type="b" name="accepted" direction="in"/> - </method> - - <method name="setPBXEnrollment"> - <arg type="s" name="callID" direction="in"/> - <arg type="b" name="yesNo" direction="in"/> - </method> -<!-- - <signal name="error"> - <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <arg type="a{ss}" name="details" direction="out"/> - </signal> ---> - - </interface> + </method> + + <method name="accept" tp:name-for-bindings="accept"> + <tp:docstring> + Answer an incoming call. Automatically put the current call on state HOLD. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The callID. + </tp:docstring> + </arg> + </method> + + <method name="hangUp" tp:name-for-bindings="hangUp"> + <tp:docstring> + Hangup a call in state "CURRENT" or "HOLD". + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The callID. + </tp:docstring> + </arg> + </method> + + <method name="hangUpConference" tp:name-for-bindings="hangUpConference"> + <tp:added version="0.9.7"/> + <tp:docstring> + Hangup a conference, and every call participating to the conference. + </tp:docstring> + <arg type="s" name="confID" direction="in"> + <tp:docstring> + The unique conference ID. + </tp:docstring> + </arg> + </method> + + <method name="hold" tp:name-for-bindings="hold"> + <tp:docstring> + Place a call on hold. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The callID. + </tp:docstring> + </arg> + </method> + + <method name="unhold" tp:name-for-bindings="unhold"> + <tp:docstring> + Hold off a call, and place this call on state CURRENT. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The callID. + </tp:docstring> + </arg> + </method> + + <method name="transfert" tp:name-for-bindings="transfert"> + <tp:docstring> + Transfer a call to given phone number. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The callID. + </tp:docstring> + </arg> + <arg type="s" name="to" direction="in"> + <tp:docstring> + The phone number to transfer the call to. + </tp:docstring> + </arg> + </method> + + <method name="playDTMF" tp:name-for-bindings="playDTMF"> + <tp:docstring> + Dual-Tone multi-frequency. Tell the core to play dial tones. A SIP INFO message is sent to notify the server. + </tp:docstring> + <arg type="s" name="key" direction="in"> + <tp:docstring> + Unicode charter for pressed key + </tp:docstring> + </arg> + </method> + + <method name="startTone" tp:name-for-bindings="startTone"> + <tp:docstring> + Start audio stream and play tone.. + </tp:docstring> + <arg type="i" name="start" direction="in"/> + <arg type="i" name="type" direction="in"/> + </method> + + <method name="setVolume" tp:name-for-bindings="setVolume"> + <tp:docstring> + <p>Sets the volume using a linear scale [0,100].</p> + <tp:rationale>Pulseaudio has its own mechanism to modify application volume. This method is enabled only if the ALSA API is used.</tp:rationale> + </tp:docstring> + <arg type="s" name="device" direction="in"> + <tp:docstring> + The device: mic or speaker + </tp:docstring> + </arg> + <arg type="d" name="value" direction="in"> + <tp:docstring> + The volume value (between 0 and 100) + </tp:docstring> + </arg> + </method> + + <method name="getVolume" tp:name-for-bindings="getVolume"> + <tp:docstring> + <p>Return the volume value of the given device on a linear scale [0,100].</p> + <tp:rationale>Only enabled if the ALSA API is used, Pulseaudio has its own mechanism to modify application volume.</tp:rationale> + </tp:docstring> + <arg type="s" name="device" direction="in"> + <tp:docstring> + The device: mic or speaker + </tp:docstring> + </arg> + <arg type="d" name="value" direction="out"> + <tp:docstring> + The volume value (between 0 and 100) + </tp:docstring> + </arg> + </method> + + <method name="joinParticipant" tp:name-for-bindings="joinParticipant"> + <tp:added version="0.9.7"/> + <tp:docstring> + <p>Join two participants together to create a 3-way conference including the current client.</p> + <tp:rationale>The signal <tp:member-ref>conferenceCreated</tp:member-ref> is emitted on success.</tp:rationale> + </tp:docstring> + <arg type="s" name="sel_callID" direction="in"/> + <arg type="s" name="drag_callID" direction="in"/> + </method> + + <method name="addParticipant" tp:name-for-bindings="addParticipant"> + <tp:added version="0.9.7"/> + <tp:docstring> + <p>Join a new particiant to an existing conference.</p> + <tp:rationale>The signal <tp:member-ref>conferenceChanged</tp:member-ref> is emitted on success.</tp:rationale> + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The ID of the call to add to the conference + </tp:docstring> + </arg> + <arg type="s" name="confID" direction="in"> + <tp:docstring> + An existing conference ID + </tp:docstring> + </arg> + </method> + + <method name="addMainParticipant" tp:name-for-bindings="addMainParticipant"> + <tp:added version="0.9.7"/> + <tp:docstring> + <p>As the core can handle multiple calls an conferences, it may happens that the client's user leave a conference to answer an incoming call or send new ones. This method is used to reintroduce SFLphone-client's user into the conference.</p> + <p>It put the current call on state HOLD or detach SFLphone-client's user from the another conference.</p> + </tp:docstring> + <arg type="s" name="confID" direction="in"> + <tp:docstring> + An existing conference ID + </tp:docstring> + </arg> + </method> + + <method name="detachParticipant" tp:name-for-bindings="detachParticipant"> + <tp:added version="0.9.7"/> + <tp:docstring> + Detach the given call from the conference. If only one participant is left, the conference is deleted and the signal <tp:member-ref>conferenceRemoved</tp:member-ref> is emited. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The call ID + </tp:docstring> + </arg> + </method> + + <method name="joinConference" tp:name-for-bindings="joinConference"> + <tp:added version="0.9.7"/> + <tp:docstring> + Join two conferences together. + </tp:docstring> + <arg type="s" name="sel_confID" direction="in"/> + <arg type="s" name="drag_confID" direction="in"/> + </method> + + <method name="getConferenceDetails" tp:name-for-bindings="getConferenceDetails"> + <tp:added version="0.9.7"/> + <tp:docstring> + Returns a hashtable containing conference details. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The call ID + </tp:docstring> + </arg> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> + <arg type="a{ss}" name="infos" direction="out"> + <tp:docstring> + A map containing the ID of the conferences and their states. + </tp:docstring> + </arg> + </method> + + <method name="getConferenceList" tp:name-for-bindings="getConferenceList"> + <tp:added version="0.9.7"/> + <tp:docstring> + Returns a list containing all active conferences. + </tp:docstring> + <arg type="as" name="list" direction="out"> + <tp:docstring> + The list of conferences. + </tp:docstring> + </arg> + </method> + + <method name="setRecording" tp:name-for-bindings="setRecording"> + <tp:docstring> + Start recording a call. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The ID of the call to record. + </tp:docstring> + </arg> + </method> + + <method name="getIsRecording" tp:name-for-bindings="getIsRecording"> + <tp:docstring> + Tells whether or not a call is being recorded. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The call ID. + </tp:docstring> + </arg> + <arg type="b" name="isRecording" direction="out"> + <tp:docstring> + Returns true is the call is being recorded. False otherwise. + </tp:docstring> + </arg> + </method> + + <method name="getCallDetails" tp:name-for-bindings="getCallDetails"> + <tp:docstring> + Get all the details about a specific call. + </tp:docstring> + <arg type="s" name="callID" direction="in"> + <tp:docstring> + The call ID. + </tp:docstring> + </arg> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> + <arg type="a{ss}" name="infos" direction="out" tp:type="String_String_Map"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>A map containing the call details: </p> + <ul> + <li>ACCOUNTID</li> + <li>PEER_NUMBER</li> + <li>PEER_NAME</li> + <li>DISPLAY_NAME</li> + <li>CALL_STATE</li> + <li>CALL_TYPE</li> + </ul> + </tp:docstring> + </arg> + </method> + + <method name="getCallList" tp:name-for-bindings="getCallList"> + <tp:docstring> + Get the list of active calls. + <tp:rationale>To get the call details, iterate on the return value and call <tp:member-ref>getCallDetails</tp:member-ref> method.</tp:rationale> + </tp:docstring> + <arg type="as" name="list" direction="out"> + <tp:docstring> + A list of call IDs. + </tp:docstring> + </arg> + </method> + + <method name="getCurrentCallID" tp:name-for-bindings="getCurrentCallID"> + <tp:docstring> + Get the CURRENT call ID. + </tp:docstring> + @param[out] output callID + <arg type="s" name="callID" direction="out"> + <tp:docstring> + The current call ID. + </tp:docstring> + </arg> + </method> + + <method name="getCurrentCodecName" tp:name-for-bindings="getCurrentCodecName"> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID" direction="in"/> + <arg type="s" name="codecName" direction="out"/> + </method> + + <signal name="currentSelectedCodec" tp:name-for-bindings="currentSelectedCodec"> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID" /> + <arg type="s" name="codecName"/> + </signal> + + <signal name="incomingCall" tp:name-for-bindings="incomingCall"> + <tp:docstring> + <p>Notify an incoming call.</p> + <p>The callID generated by the daemon and must be stored by the clients in order to address other action for + this call.</p> + <tp:rationale>The client must subscribe to this signal to handle incoming calls.</tp:rationale> + </tp:docstring> + <arg type="s" name="accountID"> + <tp:docstring> + The account ID of the callee. Clients must notify the right account when receiving this signal. + </tp:docstring> + </arg> + <arg type="s" name="callID"> + <tp:docstring> + A new call ID. + </tp:docstring> + </arg> + <arg type="s" name="from"> + <tp:docstring> + The caller phone number. + </tp:docstring> + </arg> + </signal> + + <signal name="incomingMessage" tp:name-for-bindings="incomingMessage"> + <tp:docstring> + Unused + </tp:docstring> + <arg type="s" name="accountID" /> + <arg type="s" name="message" /> + </signal> + + <signal name="callStateChanged" tp:name-for-bindings="callStateChanged"> + <tp:docstring> + <p>Notify of a change in a call state.</p> + <p>The client must subscribe to this signal.</p> + </tp:docstring> + <arg type="s" name="callID"> + <tp:docstring> + The call ID. + </tp:docstring> + </arg> + <arg type="s" name="state" > + <tp:docstring> + The acceptable states are: + <ul> + <li>INCOMING: Initial state of incoming calls</li> + <li>RINGING: Initial state of received outgoing call</li> + <li>CURRENT: The normal active state of an answered call</li> + <li>HUNGUP: Notify that the call has been hungup by peer</li> + <li>BUSY</li> + <li>FAILURE: Error when processing a call</li> + <li>HOLD</li> + <li>UNHOLD_CURRENT</li> + <li>UNHOLD_RECORD</li> + </ul> + </tp:docstring> + </arg> + </signal> + + <signal name="conferenceChanged" tp:name-for-bindings="conferenceChanged"> + <tp:added version="0.9.7"/> + <tp:docstring> + Notify of a change in the conferences state + </tp:docstring> + <arg type="s" name="confID"> + <tp:docstring> + The conference ID. + </tp:docstring> + </arg> + <arg type="s" name="state"> + <tp:docstring> + The acceptable states are: + <ul> + <li>ACTIVE_ATTACHED</li> + <li>ACTIVE_DETACHED</li> + <li>HOLD</li> + </ul> + </tp:docstring> + </arg> + </signal> + + <method name="getParticipantList" tp:name-for-bindings="getParticipantList"> + <tp:added version="0.9.7"/> + <tp:docstring> + Get the call IDs of every participant to a given conference. The client should keep and update the list of participant. + </tp:docstring> + <arg type="s" name="confID" direction="in"> + <tp:docstring> + The conference ID. + </tp:docstring> + </arg> + <arg type="as" name="list" direction="out"> + <tp:docstring> + The list of the call IDs. + </tp:docstring> + </arg> + </method> + + <signal name="conferenceCreated" tp:name-for-bindings="conferenceCreated"> + <tp:added version="0.9.7"/> + <tp:docstring> + Emited when a new conference is created. SFLphone-client is reponsible to store the confID and call <tp:member-ref>getParticipantList</tp:member-ref> to update the display. + </tp:docstring> + <arg type="s" name="confID"> + <tp:docstring> + A new conference ID. + </tp:docstring> + </arg> + </signal> + + <signal name="conferenceRemoved" tp:name-for-bindings="conferenceRemoved"> + <tp:added version="0.9.7"/> + <tp:docstring> + Emited when a new conference is remove. SFLphone-client should have kept a list of current participant in order to display modification. + </tp:docstring> + <arg type="s" name="confID"> + <tp:docstring> + The conference ID. + </tp:docstring> + </arg> + </signal> + + <method name="holdConference" tp:name-for-bindings="holdConference"> + <tp:added version="0.9.7"/> + <tp:docstring> + Hold on every calls participating to this conference. + </tp:docstring> + <arg type="s" name="confID" direction="in"> + <tp:docstring> + The conference ID. + </tp:docstring> + </arg> + </method> + + <method name="unholdConference" tp:name-for-bindings="unholdConference"> + <tp:added version="0.9.7"/> + <tp:docstring> + Hold off every calls participating to this conference. + </tp:docstring> + <arg type="s" name="confID" direction="in"> + <tp:docstring> + The conference ID. + </tp:docstring> + </arg> + </method> + + <signal name="sipCallStateChanged" tp:name-for-bindings="sipCallStateChanged"> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID" /> + <arg type="s" name="state" /> + <arg type="i" name="code" /> + </signal> + + <signal name="registrationStateChanged" tp:name-for-bindings="registrationStateChanged"> + <tp:docstring> + <p>The state of an account has changed.</p> + <p>The clients have to subscribe to this signal to use accounts.</p> + </tp:docstring> + <arg type="s" name="accountID" > + <tp:docstring> + The account ID + </tp:docstring> + </arg> + <arg type="s" name="state"> + <tp:docstring> + The new registration state + </tp:docstring> + </arg> + <arg type="i" name="code"> + <tp:docstring> + The SIP or IAX2 code + </tp:docstring> + </arg> + </signal> + + <signal name="voiceMailNotify" tp:name-for-bindings="voiceMailNotify"> + <tp:docstring> + Notify the clients of the voicemail number for a specific account, if applicable. + </tp:docstring> + <arg type="s" name="accountID"> + <tp:docstring> + The account ID. + </tp:docstring> + </arg> + <arg type="i" name="count"> + <tp:docstring> + The number of waiting messages. + </tp:docstring> + </arg> + </signal> + + <signal name="volumeChanged" tp:name-for-bindings="volumeChanged"> + <tp:docstring> + Notify the clients of a volume level change. + </tp:docstring> + <arg type="s" name="device"> + <tp:docstring> + The device: mic or speaker + </tp:docstring> + </arg> + <arg type="d" name="value"> + <tp:docstring> + The new volume value + </tp:docstring> + </arg> + </signal> + + <signal name="transferSucceded" tp:name-for-bindings="transferSucceded"> + <tp:docstring> + The transfer has been successfully processed. + </tp:docstring> + </signal> + + <signal name="transferFailed" tp:name-for-bindings="transferFailed"> + <tp:docstring> + The transfer operation has failed. + </tp:docstring> + </signal> + + <signal name="secureSdesOn" tp:name-for-bindings="secureSdesOn"> + <tp:added version="0.9.7"/> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID"/> + </signal> + + <signal name="secureSdesOff" tp:name-for-bindings="secureSdesOff"> + <tp:added version="0.9.7"/> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID" /> + </signal> + + <!-- ZRTP Methods and Signals --> + <signal name="secureZrtpOn" tp:name-for-bindings="secureZrtpOn"> + <tp:added version="0.9.7"/> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID" /> + <arg type="s" name="cipher" /> + </signal> + + <signal name="secureZrtpOff" tp:name-for-bindings="secureZrtpOff"> + <tp:added version="0.9.7"/> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID" /> + </signal> + + <signal name="confirmGoClear" tp:name-for-bindings="confirmGoClear"> + <tp:added version="0.9.7"/> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID" /> + </signal> + + <signal name="zrtpNegotiationFailed" tp:name-for-bindings="zrtpNegotiationFailed"> + <tp:added version="0.9.7"/> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID" /> + <arg type="s" name="reason" /> + <arg type="s" name="severity" /> + </signal> + + <signal name="zrtpNotSuppOther" tp:name-for-bindings="zrtpNotSuppOther"> + <tp:added version="0.9.7"/> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID" /> + </signal> + + <signal name="showSAS" tp:name-for-bindings="showSAS"> + <tp:added version="0.9.7"/> + <tp:added version="0.9.7"/> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID" /> + <arg type="s" name="sas" /> + <arg type="b" name="verified"/> + </signal> + + <method name="setSASVerified" tp:name-for-bindings="setSASVerified"> + <tp:added version="0.9.7"/> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID" direction="in"/> + </method> + + <method name="resetSASVerified" tp:name-for-bindings="resetSASVerified"> + <tp:added version="0.9.7"/> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID" direction="in"/> + </method> + + <method name="setConfirmGoClear" tp:name-for-bindings="setConfirmGoClear"> + <tp:added version="0.9.7"/> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID" direction="in"/> + </method> + + <method name="requestGoClear" tp:name-for-bindings="requestGoClear"> + <tp:added version="0.9.7"/> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID" direction="in"/> + </method> + + <method name="acceptEnrollment" tp:name-for-bindings="acceptEnrollment"> + <tp:added version="0.9.7"/> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID" direction="in"/> + <arg type="b" name="accepted" direction="in"/> + </method> + + <method name="setPBXEnrollment" tp:name-for-bindings="setPBXEnrollment"> + <tp:added version="0.9.7"/> + <tp:docstring> + </tp:docstring> + <arg type="s" name="callID" direction="in"/> + <arg type="b" name="yesNo" direction="in"/> + </method> + + </interface> </node> diff --git a/sflphone-common/src/dbus/callmanager.cpp b/sflphone-common/src/dbus/callmanager.cpp index 1c30ef975528dab36b6ed6840dd2bbac18cd7af5..36b5aa87a958aacb1c29046f11dfb860fe278f6e 100644 --- a/sflphone-common/src/dbus/callmanager.cpp +++ b/sflphone-common/src/dbus/callmanager.cpp @@ -77,14 +77,14 @@ CallManager::placeCallFirstAccount (const std::string& callID, void CallManager::refuse (const std::string& callID) { - _debug ("CallManager::refuse received"); + _debug ("CallManager: refuse received"); Manager::instance().refuseCall (callID); } void CallManager::accept (const std::string& callID) { - _debug ("CallManager::accept received"); + _debug ("CallManager: accept received"); Manager::instance().answerCall (callID); } diff --git a/sflphone-common/src/dbus/configurationmanager-introspec.xml b/sflphone-common/src/dbus/configurationmanager-introspec.xml index 0b66386689b19c9612c175bb562cce576fad7319..a34111d91751fddcb7dbe6e40c2843c989ba1415 100644 --- a/sflphone-common/src/dbus/configurationmanager-introspec.xml +++ b/sflphone-common/src/dbus/configurationmanager-introspec.xml @@ -1,568 +1,571 @@ <?xml version="1.0" ?> -<node name="/org/sflphone/SFLphone"> - <interface name="org.sflphone.SFLphone.ConfigurationManager"> - - <!-- Accounts-related methods --> - <method name="getAccountDetails"> - <!--* Method that returns a hashtable containing the current - account configuration setting. - - CONFIG_ACCOUNT_ENABLE - CONFIG_ACCOUNT_RESOLVE_ONCE - CONFIG_ACCOUNT_TYPE - HOSTNAME - USERNAME - PASSWORD - REALM - AUTHENTICATION_USERNAME - CONFIG_ACCOUNT_MAILBOX - CONFIG_ACCOUNT_REGISTRATION_EXPIRE - LOCAL_INTERFACE - PUBLISHED_SAMEAS_LOCAL - PUBLISHED_ADDRESS - LOCAL_PORT - PUBLISHED_PORT - DISPLAY_NAME - STUN_ENABLE - STUN_SERVER - - REGISTRATION_STATUS - REGISTRATION_STATE_CODE - REGISTRATION_STATE_DESCRIPTION - SRTP_KEY_EXCHANGE - SRTP_ENABLE - - SRTP_RTP_FALLBACK - ZRTP_DISPLAY_SAS - ZRTP_DISPLAY_SAS_ONCE - ZRTP_HELLO_HASH - ZRTP_NOT_SUPP_WARNING - - TLS_LISTENER_PORT - TLS_ENABLE - TLS_CA_LIST_FILE - TLS_CERTIFICATE_FILE - TLS_PRIVATE_KEY_FILE - - TLS_METHOD - TLS_CIPHERS - TLS_SERVER_NAME - TLS_VERIFY_SERVER - TLS_VERIFY_CLIENT - TLS_REQUIRE_CLIENT_CERTIFICATE - TLS_NEGOTIATION_TIMEOUT_SEC - TLS_NEGOTIATION_TIMEOUT_MSEC - - - @param[in] input accountID - @param[out] output details - --> - <arg type="s" name="accountID" direction="in"/> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <arg type="a{ss}" name="details" direction="out"/> - </method> - - <method name="setAccountDetails"> - <!--* Modify the current accout parameter settings given an - accountID and a hash table containing the parameters to - update. The hash table is not required to be complete, - only the parameter to change may be specified. Only the - running parameters are updated dynamically, configuration - settings are stored in the configuration file when - SFLphone-daemon quit. - - For a complete list of account settings refer to getAccountDetails - - @param[in] input accountID - @param[in] input details - --> - <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="MapStringString"/> - <arg type="s" name="accountID" direction="in"/> - <arg type="a{ss}" name="details" direction="in"/> - </method> - - <method name="setCredential"> - <arg type="s" name="accountID" direction="in"/> - <arg type="i" name="index" direction="in"/> - <arg type="a{ss}" name="credentialInformation" direction="in"/> - </method> - - <method name="setNumberOfCredential"> - <arg type="s" name="accountID" direction="in"/> - <arg type="i" name="number" direction="in"/> - </method> - - <method name="deleteAllCredential"> - <arg type="s" name="accountID" direction="in"/> - </method> - - <method name="getIp2IpDetails"> - <!--* Specific call to get configuration settings of the - IP2IP_PROFILE. Which are sligthly different since no VoIP - Account parameters are envolved. - - ACCOUNT_ID - SRTP_KEY_EXCHANGE - SRTP_ENABLE - SRTP_RTP_FALLBACK - ZRTP_DISPLAY_SAS - ZRTP_HELLO_HASH - ZRTP_NOT_SUPP_WARNING - ZRTP_DISPLAY_SAS_ONCE - LOCAL_INTERFACE - LOCAL_PORT - - TLS_LISTENER_PORT - TLS_CA_LIST_FILE - TLS_CERTIFICATE_FILE - TLS_PRIVATE_KEY_FILE - TLS_PASSWORD - TLS_METHOD - TLS_CIPHERS - TLS_SERVER_NAME - TLS_VERIFY_SERVER - TLS_VERIFY_CLIENT - TLS_REQUIRE_CLIENT_CERTIFICATE - TLS_NEGOTIATION_TIMEOUT_SEC - TLS_NEGOTIATION_TIMEOUT_MSEC - - @param[in] input accountID - @param[out] output details - --> - <arg type="a{ss}" name="details" direction="out"/> - </method> - - <method name="setIp2IpDetails"> - <!--* Modify the IP2IP_PROFILE parameter settings a hash table - containing the parameters to update. The hash table is not required to be complete, - only the parameters to be modified may be specified. Also, - only the running configuration is updated dynamically, - settings are stored in the configuration file when - SFLphone-daemon quit. - - For a complete list of account settings refer to getAccountDetails - - @param[in] input accountID - @param[in] input details - --> - <arg type="a{ss}" name="details" direction="in"/> - </method> - - <method name="getCredential"> - <arg type="s" name="accountID" direction="in"/> - <arg type="i" name="index" direction="in"/> - <arg type="a{ss}" name="credentialInformation" direction="out"/> - </method> - - <method name="getNumberOfCredential"> - <arg type="s" name="accountID" direction="in"/> - <arg type="i" name="numberOfCredential" direction="out"/> - </method> - - <method name="addAccount"> - <!--* Add a new account to the SFLphone-daemon list. If no - details are specified, default parameters are used. - A REGISTER is automatically sent and configuration is - saved if account created successfully. - - @param[in] input details - @param[out] output accountID - --> - <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/> - <arg type="a{ss}" name="details" direction="in"/> - <arg type="s" name="createdAccountId" direction="out"/> - </method> - - <method name="setAccountsOrder"> - <!--* Update the account list given a new list of accountID. If no account is specified - for a call, the first one in the list will be used. - - @param[in] input order - --> - <arg type="s" name="order" direction="in"/> - </method> - - <method name="removeAccount"> - <!--* Delete an account from SFLphone-daemon list and erase - account parameters from configuration file. - - @param[in] input accountID - --> - <arg type="s" name="accoundID" direction="in"/> - </method> - - <method name="getAccountList"> - <!--* Get teh accountlist as stored in SFLphone-daemon. - - @param[in] input accountID - --> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="sendRegister"> - <!--* Send accout registration request to PBX server. Register - the account if expire=1, unregister if expire=0. - - @param[in] input accountID - --> - <arg type="s" name="accountID" direction="in"/> - <arg type="i" name="expire" direction="in"/> - </method> - - <!-- /////////////////////// --> + +<node name="/configurationmanager-introspec" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> + <interface name="org.sflphone.SFLphone.ConfigurationManager"> + + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + </tp:docstring> + + <method name="getAccountDetails" tp:name-for-bindings="getAccountDetails"> + <!--* Method that returns a hashtable containing the current + account configuration setting. + + CONFIG_ACCOUNT_ENABLE + CONFIG_ACCOUNT_RESOLVE_ONCE + CONFIG_ACCOUNT_TYPE + HOSTNAME + USERNAME + PASSWORD + REALM + AUTHENTICATION_USERNAME + CONFIG_ACCOUNT_MAILBOX + CONFIG_ACCOUNT_REGISTRATION_EXPIRE + LOCAL_INTERFACE + PUBLISHED_SAMEAS_LOCAL + PUBLISHED_ADDRESS + LOCAL_PORT + PUBLISHED_PORT + DISPLAY_NAME + STUN_ENABLE + STUN_SERVER + + REGISTRATION_STATUS + REGISTRATION_STATE_CODE + REGISTRATION_STATE_DESCRIPTION + SRTP_KEY_EXCHANGE + SRTP_ENABLE + + SRTP_RTP_FALLBACK + ZRTP_DISPLAY_SAS + ZRTP_DISPLAY_SAS_ONCE + ZRTP_HELLO_HASH + ZRTP_NOT_SUPP_WARNING + + TLS_LISTENER_PORT + TLS_ENABLE + TLS_CA_LIST_FILE + TLS_CERTIFICATE_FILE + TLS_PRIVATE_KEY_FILE + + TLS_METHOD + TLS_CIPHERS + TLS_SERVER_NAME + TLS_VERIFY_SERVER + TLS_VERIFY_CLIENT + TLS_REQUIRE_CLIENT_CERTIFICATE + TLS_NEGOTIATION_TIMEOUT_SEC + TLS_NEGOTIATION_TIMEOUT_MSEC + + + @param[in] input accountID + @param[out] output details + --> + <arg type="s" name="accountID" direction="in"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> + <arg type="a{ss}" name="details" direction="out"/> + </method> + + <method name="setAccountDetails" tp:name-for-bindings="setAccountDetails"> + <!--* Modify the current accout parameter settings given an + accountID and a hash table containing the parameters to + update. The hash table is not required to be complete, + only the parameter to change may be specified. Only the + running parameters are updated dynamically, configuration + settings are stored in the configuration file when + SFLphone-daemon quit. + + For a complete list of account settings refer to getAccountDetails + + @param[in] input accountID + @param[in] input details + --> + <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="MapStringString"/> + <arg type="s" name="accountID" direction="in"/> + <arg type="a{ss}" name="details" direction="in"/> + </method> + + <method name="setCredential" tp:name-for-bindings="setCredential"> + <arg type="s" name="accountID" direction="in"/> + <arg type="i" name="index" direction="in"/> + <arg type="a{ss}" name="credentialInformation" direction="in"/> + </method> + + <method name="setNumberOfCredential" tp:name-for-bindings="setNumberOfCredential"> + <arg type="s" name="accountID" direction="in"/> + <arg type="i" name="number" direction="in"/> + </method> + + <method name="deleteAllCredential" tp:name-for-bindings="deleteAllCredential"> + <arg type="s" name="accountID" direction="in"/> + </method> + + <method name="getIp2IpDetails" tp:name-for-bindings="getIp2IpDetails"> + <!--* Specific call to get configuration settings of the + IP2IP_PROFILE. Which are sligthly different since no VoIP + Account parameters are envolved. + + ACCOUNT_ID + SRTP_KEY_EXCHANGE + SRTP_ENABLE + SRTP_RTP_FALLBACK + ZRTP_DISPLAY_SAS + ZRTP_HELLO_HASH + ZRTP_NOT_SUPP_WARNING + ZRTP_DISPLAY_SAS_ONCE + LOCAL_INTERFACE + LOCAL_PORT + + TLS_LISTENER_PORT + TLS_CA_LIST_FILE + TLS_CERTIFICATE_FILE + TLS_PRIVATE_KEY_FILE + TLS_PASSWORD + TLS_METHOD + TLS_CIPHERS + TLS_SERVER_NAME + TLS_VERIFY_SERVER + TLS_VERIFY_CLIENT + TLS_REQUIRE_CLIENT_CERTIFICATE + TLS_NEGOTIATION_TIMEOUT_SEC + TLS_NEGOTIATION_TIMEOUT_MSEC + + @param[in] input accountID + @param[out] output details + --> + <arg type="a{ss}" name="details" direction="out"/> + </method> + + <method name="setIp2IpDetails" tp:name-for-bindings="setIp2IpDetails"> + <!--* Modify the IP2IP_PROFILE parameter settings a hash table + containing the parameters to update. The hash table is not required to be complete, + only the parameters to be modified may be specified. Also, + only the running configuration is updated dynamically, + settings are stored in the configuration file when + SFLphone-daemon quit. + + For a complete list of account settings refer to getAccountDetails + + @param[in] input accountID + @param[in] input details + --> + <arg type="a{ss}" name="details" direction="in"/> + </method> + + <method name="getCredential" tp:name-for-bindings="getCredential"> + <arg type="s" name="accountID" direction="in"/> + <arg type="i" name="index" direction="in"/> + <arg type="a{ss}" name="credentialInformation" direction="out"/> + </method> + + <method name="getNumberOfCredential" tp:name-for-bindings="getNumberOfCredential"> + <arg type="s" name="accountID" direction="in"/> + <arg type="i" name="numberOfCredential" direction="out"/> + </method> + + <method name="addAccount" tp:name-for-bindings="addAccount"> + <!--* Add a new account to the SFLphone-daemon list. If no + details are specified, default parameters are used. + A REGISTER is automatically sent and configuration is + saved if account created successfully. + + @param[in] input details + @param[out] output accountID + --> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/> + <arg type="a{ss}" name="details" direction="in"/> + <arg type="s" name="createdAccountId" direction="out"/> + </method> + + <method name="setAccountsOrder" tp:name-for-bindings="setAccountsOrder"> + <!--* Update the account list given a new list of accountID. If no account is specified + for a call, the first one in the list will be used. + + @param[in] input order + --> + <arg type="s" name="order" direction="in"/> + </method> + + <method name="removeAccount" tp:name-for-bindings="removeAccount"> + <!--* Delete an account from SFLphone-daemon list and erase + account parameters from configuration file. + + @param[in] input accountID + --> + <arg type="s" name="accoundID" direction="in"/> + </method> + + <method name="getAccountList" tp:name-for-bindings="getAccountList"> + <!--* Get teh accountlist as stored in SFLphone-daemon. + + @param[in] input accountID + --> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"/> + </method> + + <method name="sendRegister" tp:name-for-bindings="sendRegister"> + <!--* Send accout registration request to PBX server. Register + the account if expire=1, unregister if expire=0. + + @param[in] input accountID + --> + <arg type="s" name="accountID" direction="in"/> + <arg type="i" name="expire" direction="in"/> + </method> + + <!-- /////////////////////// --> <!-- Various audio-related methods --> - - <method name="getToneLocaleList"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="getVersion"> - <arg type="s" name="version" direction="out"/> - </method> - - <method name="getRingtoneList"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="getPlaybackDeviceList"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="getRecordDeviceList"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="isRingtoneEnabled"> - <arg type="i" name="bool" direction="out"/> - </method> - - <method name="ringtoneEnabled"> - </method> - - <method name="getRingtoneChoice"> - <arg type="s" name="tone" direction="out"/> - </method> - - <method name="setRingtoneChoice"> - <arg type="s" name="tone" direction="in"/> - </method> - - <method name="getAudioManager"> - <arg type="i" name="api" direction="out"/> - </method> - - <method name="setAudioManager"> - <arg type="i" name="api" direction="in"/> - </method> - - <method name="getRecordPath"> - <arg type="s" name="rec" direction="out"/> - </method> - - <method name="setRecordPath"> - <arg type="s" name="rec" direction="in"/> - </method> - - <!-- /////////////////////// --> - - <!-- Codecs-related methods --> - - <method name="getCodecList"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="getCodecDetails"> - <arg type="i" name="payload" direction="in"/> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="details" direction="out"/> - </method> - - <method name="getActiveCodecList"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + + <method name="getToneLocaleList" tp:name-for-bindings="getToneLocaleList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"/> + </method> + + <method name="getVersion" tp:name-for-bindings="getVersion"> + <arg type="s" name="version" direction="out"/> + </method> + + <method name="getRingtoneList" tp:name-for-bindings="getRingtoneList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"/> + </method> + + <method name="getPlaybackDeviceList" tp:name-for-bindings="getPlaybackDeviceList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"/> + </method> + + <method name="getRecordDeviceList" tp:name-for-bindings="getRecordDeviceList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"/> + </method> + + <method name="isRingtoneEnabled" tp:name-for-bindings="isRingtoneEnabled"> + <arg type="i" name="bool" direction="out"/> + </method> + + <method name="ringtoneEnabled" tp:name-for-bindings="ringtoneEnabled"> + </method> + + <method name="getRingtoneChoice" tp:name-for-bindings="getRingtoneChoice"> + <arg type="s" name="tone" direction="out"/> + </method> + + <method name="setRingtoneChoice" tp:name-for-bindings="setRingtoneChoice"> + <arg type="s" name="tone" direction="in"/> + </method> + + <method name="getAudioManager" tp:name-for-bindings="getAudioManager"> + <arg type="i" name="api" direction="out"/> + </method> + + <method name="setAudioManager" tp:name-for-bindings="setAudioManager"> + <arg type="i" name="api" direction="in"/> + </method> + + <method name="getRecordPath" tp:name-for-bindings="getRecordPath"> + <arg type="s" name="rec" direction="out"/> + </method> + + <method name="setRecordPath" tp:name-for-bindings="setRecordPath"> + <arg type="s" name="rec" direction="in"/> + </method> + + <!-- /////////////////////// --> + + <!-- Codecs-related methods --> + + <method name="getCodecList" tp:name-for-bindings="getCodecList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"/> + </method> + + <method name="getCodecDetails" tp:name-for-bindings="getCodecDetails"> + <arg type="i" name="payload" direction="in"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="details" direction="out"/> + </method> + + <method name="getActiveCodecList" tp:name-for-bindings="getActiveCodecList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> <arg type="s" name="accountID" direction="in"/> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="setActiveCodecList"> - <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="VectorString"/> - <arg type="as" name="list" direction="in"/> - <arg type="s" name="accountID" direction="in"/> - </method> - - - <!-- Audio devices methods --> - - <method name="getInputAudioPluginList"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="getOutputAudioPluginList"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="setInputAudioPlugin"> - <arg type="s" name="audioPlugin" direction="in"/> - </method> - - <method name="setOutputAudioPlugin"> - <arg type="s" name="audioPlugin" direction="in"/> - </method> - - <method name="getAudioOutputDeviceList"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="setAudioOutputDevice"> - <arg type="i" name="index" direction="in"/> - </method> - - <method name="getAudioInputDeviceList"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="setAudioInputDevice"> - <arg type="i" name="index" direction="in"/> - </method> - - <method name="getCurrentAudioDevicesIndex"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="getAudioDeviceIndex"> - <arg type="s" name="name" direction="in"/> - <arg type="i" name="index" direction="out"/> - </method> - - <method name="getCurrentAudioOutputPlugin"> - <arg type="s" name="plugin" direction="out"/> - </method> + <arg type="as" name="list" direction="out"/> + </method> + + <method name="setActiveCodecList" tp:name-for-bindings="setActiveCodecList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="VectorString"/> + <arg type="as" name="list" direction="in"/> + <arg type="s" name="accountID" direction="in"/> + </method> + + + <!-- Audio devices methods --> + + <method name="getInputAudioPluginList" tp:name-for-bindings="getInputAudioPluginList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"/> + </method> + + <method name="getOutputAudioPluginList" tp:name-for-bindings="getOutputAudioPluginList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"/> + </method> + + <method name="setInputAudioPlugin" tp:name-for-bindings="setInputAudioPlugin"> + <arg type="s" name="audioPlugin" direction="in"/> + </method> + + <method name="setOutputAudioPlugin" tp:name-for-bindings="setOutputAudioPlugin"> + <arg type="s" name="audioPlugin" direction="in"/> + </method> + + <method name="getAudioOutputDeviceList" tp:name-for-bindings="getAudioOutputDeviceList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"/> + </method> + + <method name="setAudioOutputDevice" tp:name-for-bindings="setAudioOutputDevice"> + <arg type="i" name="index" direction="in"/> + </method> + + <method name="getAudioInputDeviceList" tp:name-for-bindings="getAudioInputDeviceList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"/> + </method> + + <method name="setAudioInputDevice" tp:name-for-bindings="setAudioInputDevice"> + <arg type="i" name="index" direction="in"/> + </method> + + <method name="getCurrentAudioDevicesIndex" tp:name-for-bindings="getCurrentAudioDevicesIndex"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"/> + </method> + + <method name="getAudioDeviceIndex" tp:name-for-bindings="getAudioDeviceIndex"> + <arg type="s" name="name" direction="in"/> + <arg type="i" name="index" direction="out"/> + </method> + + <method name="getCurrentAudioOutputPlugin" tp:name-for-bindings="getCurrentAudioOutputPlugin"> + <arg type="s" name="plugin" direction="out"/> + </method> <!-- General Settings Panel --> - <method name="isMd5CredentialHashing"> - <arg type="b" name="res" direction="out"/> - </method> - - <method name="setMd5CredentialHashing"> - <arg type="b" name="enabled" direction="in"/> - </method> - - <method name="isIax2Enabled"> - <arg type="i" name="res" direction="out"/> - </method> - - <method name="setNotify"> - </method> - - <method name="getNotify"> - <arg type="i" name="level" direction="out"/> - </method> - - <method name="setMailNotify"> - </method> - - <method name="getMailNotify"> - <arg type="i" name="level" direction="out"/> - </method> - - <method name="getDialpad"> - <arg type="i" name="state" direction="out"/> - </method> - - <method name="setDialpad"> - <arg type="b" name="display" direction="in"/> - </method> - - <method name="getSearchbar"> - <arg type="i" name="state" direction="out"/> - </method> - - <method name="setSearchbar"> - </method> - - <method name="setHistoryEnabled"> - </method> - - <method name="getHistoryEnabled"> - <arg type="s" name="state" direction="out"/> - </method> - - <method name="getVolumeControls"> - <arg type="i" name="state" direction="out"/> - </method> - - <method name="setVolumeControls"> - <arg type="b" name="display" direction="in"/> - </method> - - <method name="getHistoryLimit"> - <arg type="i" name="days" direction="out"/> - </method> - - <method name="setHistoryLimit"> - <arg type="i" name="days" direction="in"/> - </method> - - <method name="startHidden"> - </method> - - <method name="isStartHidden"> - <arg type="i" name="state" direction="out"/> - </method> - - <method name="popupMode"> - <arg type="i" name="state" direction="out"/> - </method> - - <method name="switchPopupMode"> - </method> - - <method name="getWindowWidth"> - <arg type="i" name="width" direction="out"/> - </method> - - <method name="getWindowHeight"> - <arg type="i" name="height" direction="out"/> - </method> - - <method name="setWindowWidth"> - <arg type="i" name="width" direction="in"/> - </method> - - <method name="setWindowHeight"> - <arg type="i" name="height" direction="in"/> - </method> - - <method name="getWindowPositionX"> - <arg type="i" name="posX" direction="out"/> - </method> - - <method name="setWindowPositionX"> - <arg type="i" name="posX" direction="in"/> - </method> - - <method name="getWindowPositionY"> - <arg type="i" name="posY" direction="out"/> - </method> - - <method name="setWindowPositionY"> - <arg type="i" name="posY" direction="in"/> - </method> - - <method name="enableStatusIcon"> - <arg type="s" name="value" direction="in"/> - </method> - - <method name="isStatusIconEnabled"> - <arg type="s" name="value" direction="out"/> - </method> - - - <!-- Addressbook configuration --> - <method name="getAddressbookSettings"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringInt"/> - <arg type="a{si}" name="settings" direction="out"/> - </method> - - <method name="setAddressbookSettings"> - <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringInt"/> - <arg type="a{si}" name="settings" direction="in"/> - </method> - - <!-- Addressbook list --> - <method name="getAddressbookList"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="settings" direction="out"/> - </method> - - <method name="setAddressbookList"> - <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="VectorString"/> - <arg type="as" name="settings" direction="in"/> - </method> - - <!-- Hook configuration --> - <method name="getHookSettings"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <arg type="a{ss}" name="settings" direction="out"/> - </method> - - <method name="setHookSettings"> - <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/> - <arg type="a{ss}" name="settings" direction="in"/> - </method> - - <method name="getHistory"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <arg type="a{ss}" name="entries" direction="out"/> - </method> - - <method name="setHistory"> - <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/> - <arg type="a{ss}" name="entries" direction="in"/> - </method> - - <signal name="accountsChanged"> - </signal> - - <signal name="errorAlert"> - <arg type="i" name="code" direction="out"/> - </signal> - - <!-- TLS Methods --> - <method name="getSupportedTlsMethod"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="getTlsSettingsDefault"> - <arg type="a{ss}" name="details" direction="out"/> - </method> - - <method name="getTlsSettings"> - <arg type="s" name="accountID" direction="in"/> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <arg type="a{ss}" name="details" direction="out"/> - </method> - - <method name="setTlsSettings"> - <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="MapStringString"/> - <arg type="s" name="accountID" direction="in"/> - <arg type="a{ss}" name="details" direction="in"/> - </method> - - <method name="getAddrFromInterfaceName"> - <arg type="s" name="interface" direction="in"/> - <arg type="s" name="address" direction="out"/> - </method> - - <method name="getAllIpInterface"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="getAllIpInterfaceByName"> - <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> - <arg type="as" name="list" direction="out"/> - </method> - - <method name="getShortcuts"> - <arg type="a{si}" name="shortcutsMap" direction="out"/> - </method> - - <method name="setShortcuts"> - <arg type="a{si}" name="shortcutsMap" direction="in"/> - </method> + <method name="isMd5CredentialHashing" tp:name-for-bindings="isMd5CredentialHashing"> + <arg type="b" name="res" direction="out"/> + </method> + + <method name="setMd5CredentialHashing" tp:name-for-bindings="setMd5CredentialHashing"> + <arg type="b" name="enabled" direction="in"/> + </method> + + <method name="isIax2Enabled" tp:name-for-bindings="isIax2Enabled"> + <arg type="i" name="res" direction="out"/> + </method> + + <method name="setNotify" tp:name-for-bindings="setNotify"> + </method> + + <method name="getNotify" tp:name-for-bindings="getNotify"> + <arg type="i" name="level" direction="out"/> + </method> + + <method name="setMailNotify" tp:name-for-bindings="setMailNotify"> + </method> + + <method name="getMailNotify" tp:name-for-bindings="getMailNotify"> + <arg type="i" name="level" direction="out"/> + </method> + + <method name="getDialpad" tp:name-for-bindings="getDialpad"> + <arg type="i" name="state" direction="out"/> + </method> + + <method name="setDialpad" tp:name-for-bindings="setDialpad"> + <arg type="b" name="display" direction="in"/> + </method> + + <method name="getSearchbar" tp:name-for-bindings="getSearchbar"> + <arg type="i" name="state" direction="out"/> + </method> + + <method name="setSearchbar" tp:name-for-bindings="setSearchbar"> + </method> + + <method name="setHistoryEnabled" tp:name-for-bindings="setHistoryEnabled"> + </method> + + <method name="getHistoryEnabled" tp:name-for-bindings="getHistoryEnabled"> + <arg type="s" name="state" direction="out"/> + </method> + + <method name="getVolumeControls" tp:name-for-bindings="getVolumeControls"> + <arg type="i" name="state" direction="out"/> + </method> + + <method name="setVolumeControls" tp:name-for-bindings="setVolumeControls"> + <arg type="b" name="display" direction="in"/> + </method> + + <method name="getHistoryLimit" tp:name-for-bindings="getHistoryLimit"> + <arg type="i" name="days" direction="out"/> + </method> + + <method name="setHistoryLimit" tp:name-for-bindings="setHistoryLimit"> + <arg type="i" name="days" direction="in"/> + </method> + + <method name="startHidden" tp:name-for-bindings="startHidden"> + </method> + + <method name="isStartHidden" tp:name-for-bindings="isStartHidden"> + <arg type="i" name="state" direction="out"/> + </method> + + <method name="popupMode" tp:name-for-bindings="popupMode"> + <arg type="i" name="state" direction="out"/> + </method> + + <method name="switchPopupMode" tp:name-for-bindings="switchPopupMode"> + </method> + + <method name="getWindowWidth" tp:name-for-bindings="getWindowWidth"> + <arg type="i" name="width" direction="out"/> + </method> + + <method name="getWindowHeight" tp:name-for-bindings="getWindowHeight"> + <arg type="i" name="height" direction="out"/> + </method> + + <method name="setWindowWidth" tp:name-for-bindings="setWindowWidth"> + <arg type="i" name="width" direction="in"/> + </method> + + <method name="setWindowHeight" tp:name-for-bindings="setWindowHeight"> + <arg type="i" name="height" direction="in"/> + </method> + + <method name="getWindowPositionX" tp:name-for-bindings="getWindowPositionX"> + <arg type="i" name="posX" direction="out"/> + </method> + + <method name="setWindowPositionX" tp:name-for-bindings="setWindowPositionX"> + <arg type="i" name="posX" direction="in"/> + </method> + + <method name="getWindowPositionY" tp:name-for-bindings="getWindowPositionY"> + <arg type="i" name="posY" direction="out"/> + </method> + + <method name="setWindowPositionY" tp:name-for-bindings="setWindowPositionY"> + <arg type="i" name="posY" direction="in"/> + </method> + + <method name="enableStatusIcon" tp:name-for-bindings="enableStatusIcon"> + <arg type="s" name="value" direction="in"/> + </method> + + <method name="isStatusIconEnabled" tp:name-for-bindings="isStatusIconEnabled"> + <arg type="s" name="value" direction="out"/> + </method> + + + <!-- Addressbook configuration --> + <method name="getAddressbookSettings" tp:name-for-bindings="getAddressbookSettings"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringInt"/> + <arg type="a{si}" name="settings" direction="out"/> + </method> + + <method name="setAddressbookSettings" tp:name-for-bindings="setAddressbookSettings"> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringInt"/> + <arg type="a{si}" name="settings" direction="in"/> + </method> + + <!-- Addressbook list --> + <method name="getAddressbookList" tp:name-for-bindings="getAddressbookList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="settings" direction="out"/> + </method> + + <method name="setAddressbookList" tp:name-for-bindings="setAddressbookList"> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="VectorString"/> + <arg type="as" name="settings" direction="in"/> + </method> + + <!-- Hook configuration --> + <method name="getHookSettings" tp:name-for-bindings="getHookSettings"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> + <arg type="a{ss}" name="settings" direction="out"/> + </method> + + <method name="setHookSettings" tp:name-for-bindings="setHookSettings"> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/> + <arg type="a{ss}" name="settings" direction="in"/> + </method> + + <method name="getHistory" tp:name-for-bindings="getHistory"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> + <arg type="a{ss}" name="entries" direction="out"/> + </method> + + <method name="setHistory" tp:name-for-bindings="setHistory"> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/> + <arg type="a{ss}" name="entries" direction="in"/> + </method> + + <signal name="accountsChanged" tp:name-for-bindings="accountsChanged"> + </signal> + + <signal name="errorAlert" tp:name-for-bindings="errorAlert"> + <arg type="i" name="code"/> + </signal> + + <!-- TLS Methods --> + <method name="getSupportedTlsMethod" tp:name-for-bindings="getSupportedTlsMethod"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"/> + </method> + + <method name="getTlsSettingsDefault" tp:name-for-bindings="getTlsSettingsDefault"> + <arg type="a{ss}" name="details" direction="out"/> + </method> + + <method name="getTlsSettings" tp:name-for-bindings="getTlsSettings"> + <arg type="s" name="accountID" direction="in"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/> + <arg type="a{ss}" name="details" direction="out"/> + </method> + + <method name="setTlsSettings" tp:name-for-bindings="setTlsSettings"> + <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="MapStringString"/> + <arg type="s" name="accountID" direction="in"/> + <arg type="a{ss}" name="details" direction="in"/> + </method> + + <method name="getAddrFromInterfaceName" tp:name-for-bindings="getAddrFromInterfaceName"> + <arg type="s" name="interface" direction="in"/> + <arg type="s" name="address" direction="out"/> + </method> + + <method name="getAllIpInterface" tp:name-for-bindings="getAllIpInterface"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"/> + </method> + + <method name="getAllIpInterfaceByName" tp:name-for-bindings="getAllIpInterfaceByName"> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"/> + </method> + + <method name="getShortcuts" tp:name-for-bindings="getShortcuts"> + <arg type="a{si}" name="shortcutsMap" direction="out"/> + </method> + + <method name="setShortcuts" tp:name-for-bindings="setShortcuts"> + <arg type="a{si}" name="shortcutsMap" direction="in"/> + </method> </interface> </node> diff --git a/sflphone-common/src/dbus/instance-introspec.xml b/sflphone-common/src/dbus/instance-introspec.xml index 90a60d632d04ca83039efcadcfa2f4981bfda39e..4b7d075cd87112df83744e3740f892d4f1cb26e5 100644 --- a/sflphone-common/src/dbus/instance-introspec.xml +++ b/sflphone-common/src/dbus/instance-introspec.xml @@ -1,18 +1,46 @@ <?xml version="1.0" ?> -<node name="/org/sflphone/SFLphone"> - <interface name="org.sflphone.SFLphone.Instance"> - - <method name="Register"> - <arg type="i" name="pid" direction="in"/> - <arg type="s" name="name" direction="in"/> - </method> - - <method name="Unregister"> - <arg type="i" name="pid" direction="in"/> - </method> - - <method name="getRegistrationCount"> - <arg type="i" name="count" direction="out"/> - </method> - </interface> +<node name="/instance-introspec" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> + <interface name="org.sflphone.SFLphone.Instance"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>Count the number of clients actually registered to the core. When initializing your client, you need to register it against the core by using this interface.</p> + </tp:docstring> + <method name="Register" tp:name-for-bindings="Register"> + <tp:docstring> + Register a new client to the core. Increments the registration count. + </tp:docstring> + <arg type="i" name="pid" direction="in"> + <tp:docstring> + The pid of the client process + </tp:docstring> + </arg> + <arg type="s" name="name" direction="in"> + <tp:docstring> + The name of the client + </tp:docstring> + </arg> + </method> + <method name="Unregister" tp:name-for-bindings="Unregister"> + <tp:docstring> + Unregister a connected client from the core. Decrements the registration count. If no more clients are connected, ie the registration count equals 0, the core properly quits. + </tp:docstring> + <arg type="i" name="pid" direction="in"> + <tp:docstring> + The pid of the client process + </tp:docstring> + </arg> + </method> + + <method name="getRegistrationCount" tp:name-for-bindings="getRegistrationCount"> + <tp:docstring> + Get the number of connected clients. + </tp:docstring> + <arg type="i" name="count" direction="out"> + <tp:docstring> + The number of client currently connected to the core + </tp:docstring> + </arg> + </method> + + + </interface> </node> diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp index e5efbdee68a68363aa189af4f60728f26f3448b4..c6eee7e01a886dc597681e44a0c065f07913ced7 100644 --- a/sflphone-common/src/managerimpl.cpp +++ b/sflphone-common/src/managerimpl.cpp @@ -376,7 +376,9 @@ bool ManagerImpl::answerCall (const CallID& call_id) { //THREAD=Main bool ManagerImpl::hangupCall (const CallID& call_id) { - _debug ("ManagerImpl::hangupCall(%s)", call_id.c_str()); + + _info("Manager: Hangup call %s", call_id.c_str()); + PulseLayer *pulselayer; AccountID account_id; bool returnValue = true; @@ -387,7 +389,7 @@ bool ManagerImpl::hangupCall (const CallID& call_id) { stopTone(); /* Broadcast a signal over DBus */ - _debug (" hangupCall: Send DBUS call state change (HUNGUP) for id %s", call_id.c_str()); + _debug ("Manager: Send DBUS call state change (HUNGUP) for id %s", call_id.c_str()); if (_dbus) _dbus->getCallManager()->callStateChanged(call_id, "HUNGUP"); @@ -419,7 +421,7 @@ bool ManagerImpl::hangupCall (const CallID& call_id) { if (account_id == AccountNULL) { - _debug ("! Manager Hangup Call: Call doesn't exists"); + _error ("Manager: Error: account id is NULL in hangup"); returnValue = false; } else { @@ -434,7 +436,7 @@ bool ManagerImpl::hangupCall (const CallID& call_id) { // stop streams if (audiolayer && (nbCalls <= 0)) { - _debug (" hangupCall: stop audio stream, ther is only %i call(s) remaining", nbCalls); + _debug ("Manager: stop audio stream, ther is only %i call(s) remaining", nbCalls); audiolayer->stopStream(); } @@ -446,7 +448,8 @@ bool ManagerImpl::hangupCall (const CallID& call_id) { } bool ManagerImpl::hangupConference (const ConfID& id) { - _debug ("ManagerImpl::hangupConference()"); + + _debug ("Manager: Hangup conference %s", id.c_str()); Conference *conf; ConferenceMap::iterator iter_conf = _conferencemap.find(id); @@ -463,7 +466,7 @@ bool ManagerImpl::hangupConference (const ConfID& id) { ParticipantSet::iterator iter_participant = participants.begin(); while (iter_participant != participants.end()) { - _debug ("ManagerImpl::hangupConference participant %s", (*iter_participant).c_str()); + _debug ("Manager: Hangup onference participant %s", (*iter_participant).c_str()); hangupCall(*iter_participant); @@ -483,6 +486,8 @@ bool ManagerImpl::cancelCall (const CallID& id) { AccountID accountid; bool returnValue; + _debug("Manager: Cancel call"); + stopTone(); /* Direct IP to IP call */ @@ -518,13 +523,12 @@ bool ManagerImpl::onHoldCall (const CallID& call_id) { AccountID account_id; bool returnValue; - _debug ("ManagerImpl::onHoldCall(%s)", call_id.c_str()); + _debug ("Manager: Put call %s on hold", call_id.c_str()); stopTone(); CallID current_call_id = getCurrentCallId(); - _debug (" onHoldCall: try to put call %s on hold", call_id.c_str()); /* Direct IP to IP call */ @@ -537,7 +541,7 @@ bool ManagerImpl::onHoldCall (const CallID& call_id) { account_id = getAccountFromCall(call_id); if (account_id == AccountNULL) { - _debug (" onHoldCall: Account ID %s or callid %s doesn't exists", account_id.c_str(), call_id.c_str()); + _debug ("Manager: Account ID %s or callid %s doesn't exists in call onHold", account_id.c_str(), call_id.c_str()); return false; } @@ -568,7 +572,7 @@ bool ManagerImpl::offHoldCall (const CallID& call_id) { is_rec = false; - _debug ("ManagerImpl::offHoldCall(%s)", call_id.c_str()); + _debug ("Manager: Put call %s off hold", call_id.c_str()); stopTone(); @@ -580,11 +584,9 @@ bool ManagerImpl::offHoldCall (const CallID& call_id) { // if this is not a conferenceand this and is not a conference participant if (!isConference(current_call_id) && !participToConference( current_call_id)) { - _debug (" offHoldCall: put current call (%s) on hold", current_call_id.c_str()); onHoldCall(current_call_id); } else if (isConference(current_call_id) && !participToConference( call_id)) { - _debug (" offHoldCall Put current conference (%s) on hold", current_call_id.c_str()); detachParticipant(default_id, current_call_id); } } @@ -603,11 +605,11 @@ bool ManagerImpl::offHoldCall (const CallID& call_id) { account_id = getAccountFromCall(call_id); if (account_id == AccountNULL) { - _debug ("Manager OffHold Call: Call doesn't exists"); + _warn ("Manager: Error: Call doesn't exists in off hold"); return false; } - _debug ("Setting OFFHOLD, Account %s, callid %s", account_id.c_str(), call_id.c_str()); + _debug ("Manager: Setting offhold, Account %s, callid %s", account_id.c_str(), call_id.c_str()); is_rec = getAccountLink(account_id)->getCall(call_id)->isRecording(); returnValue = getAccountLink(account_id)->offhold(call_id); @@ -636,12 +638,6 @@ bool ManagerImpl::offHoldCall (const CallID& call_id) { _audiodriver->flushMain(); } - // codecName = getCurrentCodecName (call_id); - // _debug("ManagerImpl::hangupCall(): broadcast codec name %s ",codecName.c_str()); - - // if (_dbus) _dbus->getCallManager()->currentSelectedCodec (call_id,codecName.c_str()); - - return returnValue; } @@ -650,64 +646,46 @@ bool ManagerImpl::transferCall (const CallID& call_id, const std::string& to) { AccountID accountid; bool returnValue; - stopTone(); + _info("Manager: Transfer call %s\n", call_id.c_str()); CallID current_call_id = getCurrentCallId(); - if (participToConference(call_id)) { - - _debug("Particip to a conference\n"); - - Conference *conf = getConferenceFromCallID(call_id); - - if (conf != NULL) { - // remove this participant - removeParticipant(call_id); - - processRemainingParticipant(current_call_id, conf); - } - } else { - - _debug("Do not Particip to a conference\n"); - - // we are not participating to a conference, current call switched to "" - if (!isConference(current_call_id)) - switchCall(""); - } - - /* Direct IP to IP call */ + // Direct IP to IP call if (getConfigFromCall(call_id) == Call::IPtoIP) { - returnValue - = SIPVoIPLink::instance(AccountNULL)-> transfer(call_id, to); + returnValue = SIPVoIPLink::instance(AccountNULL)-> transfer(call_id, to); } - /* Classic call, attached to an account */ + // Classic call, attached to an account else { - accountid = getAccountFromCall(call_id); + + accountid = getAccountFromCall(call_id); if (accountid == AccountNULL) { - _debug ("! Manager Transfer Call: Call doesn't exists"); + _warn ("Manager: Call doesn't exists"); return false; } returnValue = getAccountLink(accountid)->transfer(call_id, to); - removeCallAccount(call_id); } + // remove waiting call in case we make transfer without even answer removeWaitingCall(call_id); - if (_dbus) - _dbus->getCallManager()->callStateChanged(call_id, "HUNGUP"); - return returnValue; } void ManagerImpl::transferFailed () { + + _debug("UserAgent: Transfer failed"); + if (_dbus) _dbus->getCallManager()->transferFailed(); } void ManagerImpl::transferSucceded () { + + _debug("UserAgent: Transfer succeded"); + if (_dbus) _dbus->getCallManager()->transferSucceded(); @@ -718,6 +696,8 @@ bool ManagerImpl::refuseCall (const CallID& id) { AccountID accountid; bool returnValue; + _debug("Manager: Refuse call %s", id.c_str()); + CallID current_call_id = getCurrentCallId(); stopTone(); @@ -727,12 +707,14 @@ bool ManagerImpl::refuseCall (const CallID& id) { // AudioLayer* audiolayer = getAudioDriver(); if (nbCalls <= 1) { - _debug (" refuseCall: stop audio stream, ther is only %i call(s) remaining", nbCalls); + _debug (" refuseCall: stop audio stream, there is only %i call(s) remaining", nbCalls); AudioLayer* audiolayer = getAudioDriver(); audiolayer->stopStream(); } + _debug("OK"); + /* Direct IP to IP call */ if (getConfigFromCall(id) == Call::IPtoIP) { @@ -744,7 +726,7 @@ bool ManagerImpl::refuseCall (const CallID& id) { accountid = getAccountFromCall(id); if (accountid == AccountNULL) { - _debug ("! Manager refuseCall: Call doesn't exists"); + _warn ("Manager: Call doesn't exists"); return false; } @@ -752,6 +734,7 @@ bool ManagerImpl::refuseCall (const CallID& id) { removeCallAccount(id); } + _debug("OK"); // if the call was outgoing or established, we didn't refuse it // so the method did nothing @@ -760,9 +743,6 @@ bool ManagerImpl::refuseCall (const CallID& id) { if (_dbus) _dbus->getCallManager()->callStateChanged(id, "HUNGUP"); - - // if(current_call_id.compare("") != 0) - // switchCall (""); } return returnValue; @@ -1542,18 +1522,24 @@ bool ManagerImpl::incomingCallWaiting () { } void ManagerImpl::addWaitingCall (const CallID& id) { + ost::MutexLock m(_waitingCallMutex); _waitingCall.insert(id); _nbIncomingWaitingCall++; + + _info("Manager: Add waiting call %s (%d calls)", id.c_str(), _nbIncomingWaitingCall); } void ManagerImpl::removeWaitingCall (const CallID& id) { + ost::MutexLock m(_waitingCallMutex); // should return more than 1 if it erase a call if (_waitingCall.erase(id)) { _nbIncomingWaitingCall--; } + + _info("Manager: Remove waiting call %s (%d calls)", id.c_str(), _nbIncomingWaitingCall); } bool ManagerImpl::isWaitingCall (const CallID& id) { @@ -1571,29 +1557,29 @@ bool ManagerImpl::isWaitingCall (const CallID& id) { //////////////////////////////////////////////////////////////////////////////// // SipEvent Thread bool ManagerImpl::incomingCall (Call* call, const AccountID& accountId) { - PulseLayer *pulselayer; + std::string from, number, display_name, display; + if(!call) + _error("Manager: Error: no call at this point"); + stopTone(); - _debug ("Incoming call %s for account %s", call->getCallId().data(), accountId.c_str()); + _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 == AccountNULL) { - associateConfigToCall(call->getCallId(), Call::IPtoIP); - } else { + } + else { // strip sip: which is not required and bring confusion with ip to ip calls // when placing new call from history (if call is IAX, do nothing) std::string peerNumber = call->getPeerNumber(); int startIndex = peerNumber.find("sip:"); - // if "sip:" is found => it is not an IAX call - if (startIndex != (int) string::npos) { std::string strippedPeerNumber = peerNumber.substr(startIndex + 4); call->setPeerNumber(strippedPeerNumber); @@ -1601,32 +1587,23 @@ bool ManagerImpl::incomingCall (Call* call, const AccountID& accountId) { } - _debug ("ManagerImpl::incomingCall :: hasCurrentCall() %i ", hasCurrentCall()); - if (!hasCurrentCall()) { + _debug ("Manager: Has no current call"); call->setConnectionState(Call::Ringing); ringtone(); - // switchCall (call->getCallId()); } - - /* - else { - addWaitingCall(call->getCallId()); - } - */ + else { + _debug ("Manager: has current call"); + } addWaitingCall(call->getCallId()); from = call->getPeerName(); - number = call->getPeerNumber(); - display_name = call->getDisplayName(); - // _debug( "incomingCall from: %s, number: %s, display_name: %s", from.c_str(), number.c_str(), display_name.c_str()); - if (from != "" && number != "") { from.append(" <"); from.append(number); @@ -1637,33 +1614,15 @@ bool ManagerImpl::incomingCall (Call* call, const AccountID& accountId) { from.append(">"); } - /* - CallIDSet::iterator iter = _waitingCall.begin(); - while (iter != _waitingCall.end()) { - CallID ident = *iter; - _debug("ManagerImpl::incomingCall :: CALL iteration: %s ",ident.c_str()); - ++iter; - } - */ - /* Broadcast a signal over DBus */ - _debug ("From: %s, Number: %s, DisplayName: %s", from.c_str(), number.c_str(), display_name.c_str()); + _debug ("Manager: From: %s, Number: %s, Display Name: %s", from.c_str(), number.c_str(), display_name.c_str()); display = display_name; - display.append(" "); - display.append(from); if (_dbus) - _dbus->getCallManager()->incomingCall(accountId, call->getCallId(), - display.c_str()); - - //if (_dbus) _dbus->getCallManager()->callStateChanged(call->getCallId(), "INCOMING"); - - if (_audiodriver->getLayerType() == PULSEAUDIO) { - pulselayer = dynamic_cast<PulseLayer *> (getAudioDriver()); - } + _dbus->getCallManager()->incomingCall(accountId, call->getCallId(), display.c_str()); return true; } @@ -1713,7 +1672,7 @@ void ManagerImpl::peerHungupCall (const CallID& call_id) { AccountID account_id; bool returnValue; - _debug ("ManagerImpl::peerHungupCall(%s)", call_id.c_str()); + _debug ("Manager: Peer hungup call %s", call_id.c_str()); // store the current call id CallID current_call_id = getCurrentCallId(); @@ -1745,11 +1704,6 @@ void ManagerImpl::peerHungupCall (const CallID& call_id) { account_id = getAccountFromCall(call_id); - if (account_id == AccountNULL) { - _debug ("peerHungupCall: Call doesn't exists"); - return; - } - returnValue = getAccountLink(account_id)->peerHungup(call_id); } @@ -1945,7 +1899,8 @@ void ManagerImpl::ringback () { * Multi Thread */ void ManagerImpl::ringtone () { - _debug ("ManagerImpl::ringtone"); + + _debug ("Manager: Start ringtone"); std::string ringchoice; AudioLayer *audiolayer; AudioCodec *codecForTone; @@ -1954,7 +1909,7 @@ void ManagerImpl::ringtone () { if (isRingtoneEnabled()) { - _debug (" Tone is enabled"); + _debug ("Manager: Tone is enabled"); //TODO Comment this because it makes the daemon crashes since the main thread //synchronizes the ringtone thread. @@ -1969,10 +1924,12 @@ void ManagerImpl::ringtone () { audiolayer = getAudioDriver(); - layer = audiolayer->getLayerType(); - - if (audiolayer == 0) + if (!audiolayer) { + _error("Manager: Error: no audio layer in ringtone"); return; + } + + layer = audiolayer->getLayerType(); samplerate = audiolayer->getSampleRate(); @@ -3939,7 +3896,6 @@ bool ManagerImpl::removeCallAccount (const CallID& callID) { if (_callAccountMap.erase(callID)) { return true; } - return false; } @@ -4098,18 +4054,19 @@ ManagerImpl::getAccount (const AccountID& accountID) { AccountID ManagerImpl::getAccountIdFromNameAndServer ( const std::string& userName, const std::string& server) { + AccountMap::iterator iter; SIPAccount *account; - _debug ("getAccountIdFromNameAndServer : username = %s , server = %s", userName.c_str(), server.c_str()); + + _info ("Manager : username = %s , server = %s", userName.c_str(), server.c_str()); // Try to find the account id from username and server name by full match for (iter = _accountMap.begin(); iter != _accountMap.end(); ++iter) { - _debug ("for : account = %s", iter->first.c_str()); account = dynamic_cast<SIPAccount *> (iter->second); if (account != NULL) { if (account->fullMatch(userName, server)) { - _debug ("Matching accountId in request is a fullmatch"); + _debug ("Manager: Matching account id in request is a fullmatch %s@%s", userName.c_str(), server.c_str()); return iter->first; } } @@ -4121,7 +4078,7 @@ AccountID ManagerImpl::getAccountIdFromNameAndServer ( if (account != NULL) { if (account->hostnameMatch(server)) { - _debug ("Matching accountId in request with hostname"); + _debug ("Manager: Matching account id in request with hostname %s", server.c_str()); return iter->first; } } @@ -4133,12 +4090,14 @@ AccountID ManagerImpl::getAccountIdFromNameAndServer ( if (account != NULL) { if (account->userMatch(userName)) { - _debug ("Matching accountId in request with username"); + _debug ("Manager: Matching account id in request with username %s", userName.c_str()); return iter->first; } } } + _debug ("Manager: Username %s or server %s doesn't match any account, using IP2IP", userName.c_str(), server.c_str()); + // Failed again! return AccountNULL return AccountNULL; } @@ -4262,7 +4221,7 @@ bool ManagerImpl::associateConfigToCall (const CallID& callID, if (getConfigFromCall(callID) == CallConfigNULL) { // nothing with the same ID _callConfigMap[callID] = config; - _debug ("Associate Call %s with config %i", callID.data(), config); + _debug ("Manager: Associate call %s with config %i", callID.c_str(), config); return true; } else { return false; diff --git a/sflphone-common/src/sip/sipcall.cpp b/sflphone-common/src/sip/sipcall.cpp index d1e22660c64e97650684a27048114b875de382e2..9ed7f7a90e42b3651fdd67fddde9972fbd9a7565 100644 --- a/sflphone-common/src/sip/sipcall.cpp +++ b/sflphone-common/src/sip/sipcall.cpp @@ -33,17 +33,19 @@ SIPCall::SIPCall (const CallID& id, Call::CallType type, pj_pool_t *pool) : Call , _invSession (NULL) , _local_sdp (0) { + _debug ("SIPCall: Create new call %s", id.c_str()); + _local_sdp = new Sdp (pool); - _debug ("SIPCALL::Constructor for this class is called "); } SIPCall::~SIPCall() { + _debug ("SIPCall: Delete call"); + delete _audiortp; _audiortp = 0; delete _local_sdp; _local_sdp = 0; - _debug ("SIPCALL::Destructor for this class is called "); } diff --git a/sflphone-common/src/sip/sipcall.h b/sflphone-common/src/sip/sipcall.h index f2d93259da6872000a51a3491da79e2d37eef3b4..7d14936729055c65cbd348263fcac35b6fe620f9 100644 --- a/sflphone-common/src/sip/sipcall.h +++ b/sflphone-common/src/sip/sipcall.h @@ -97,9 +97,11 @@ class SIPCall : public Call void setTid(int tid) { _tid = tid; } void setXferSub(pjsip_evsub* sub) {_xferSub = sub;} + pjsip_evsub *getXferSub() {return _xferSub;} void setInvSession(pjsip_inv_session* inv) {_invSession = inv;} + pjsip_inv_session *getInvSession() {return _invSession;} Sdp* getLocalSDP (void) { return _local_sdp; } diff --git a/sflphone-common/src/sip/sipvoiplink.cpp b/sflphone-common/src/sip/sipvoiplink.cpp index 4d1e25a850a9f7fef5de7f0bf1aaed5395927bd3..112788ad61490c5a2e2593ec4e4b8c834e489b2b 100644 --- a/sflphone-common/src/sip/sipvoiplink.cpp +++ b/sflphone-common/src/sip/sipvoiplink.cpp @@ -50,6 +50,8 @@ #include <sys/ioctl.h> #include <linux/if.h> +#include <map> + #define CAN_REINVITE 1 static char * invitationStateMap[] = { @@ -79,9 +81,17 @@ struct result { pjsip_server_addresses servers; }; +/** The default transport (5060) */ pjsip_transport *_localUDPTransport = NULL; + +/** The local tls listener */ pjsip_tpfactory *_localTlsListener = NULL; +/** A map to retreive SFLphone internal call id + * Given a SIP call ID (usefull for transaction sucha as transfer)*/ +std::map<std::string, CallID> transferCallID; + + const pj_str_t STR_USER_AGENT = { (char*) "User-Agent", 10 }; /**************** EXTERN VARIABLES AND FUNCTIONS (callbacks) **************************/ @@ -342,6 +352,7 @@ SIPVoIPLink::terminateSIPCall() void SIPVoIPLink::terminateOneCall (const CallID& id) { + _debug("UserAgent: Terminate call %s", id.c_str()); SIPCall *call = getSIPCall (id); @@ -386,7 +397,7 @@ std::string SIPVoIPLink::getInterfaceAddrFromName(std::string ifaceName) { struct in_addr *addr_in; if((fd = socket (AF_INET, SOCK_DGRAM,0)) < 0) - _debug("UserAgent: getInterfaceAddrFromName error could not open socket\n"); + _error("UserAgent: Error: could not open socket"); memset (&ifr, 0, sizeof (struct ifreq)); @@ -394,7 +405,7 @@ std::string SIPVoIPLink::getInterfaceAddrFromName(std::string ifaceName) { ifr.ifr_addr.sa_family = AF_INET; if((err = ioctl(fd, SIOCGIFADDR, &ifr)) < 0) - _debug("UserAgent: getInterfaceAddrFromName use default interface (0.0.0.0)\n"); + _debug("UserAgent: Use default interface (0.0.0.0)"); saddr_in = (struct sockaddr_in *)&ifr.ifr_addr; addr_in = &(saddr_in->sin_addr); @@ -921,12 +932,12 @@ SIPVoIPLink::peerHungup (const CallID& id) pjsip_tx_data *tdata = NULL; SIPCall* call; - _info("SIP: Peer hungup"); + _info("UserAgent: Peer hungup"); call = getSIPCall (id); if (call==0) { - _debug ("! SIP Error: Call doesn't exist"); + _warn ("UserAgent: Call doesn't exist"); return false; } @@ -949,7 +960,7 @@ SIPVoIPLink::peerHungup (const CallID& id) // Release RTP thread if (Manager::instance().isCurrentCall (id)) { - _debug ("* SIP Info: Stopping AudioRTP for hangup"); + _debug ("UserAgent: Stopping AudioRTP for hangup"); call->getAudioRtp()->stop(); } @@ -964,15 +975,15 @@ SIPVoIPLink::peerHungup (const CallID& id) bool SIPVoIPLink::cancel (const CallID& id) { + _info ("UserAgent: Cancel call %s", id.c_str()); + SIPCall* call = getSIPCall (id); - if (call==0) { - _debug ("! SIP Error: Call doesn't exist"); + if (!call) { + _warn("UserAgent: Error: Call doesn't exist"); return false; } - _debug ("- SIP Action: Cancel call %s [cid: %3d]", id.data(), call->getCid()); - terminateOneCall (id); removeCall (id); @@ -1109,13 +1120,13 @@ SIPVoIPLink::transfer (const CallID& id, const std::string& to) account_id = Manager::instance().getAccountFromCall (id); account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (account_id)); - if (account == NULL) { - _debug ("SIPVoIPLink::transfer account is null. Returning."); + if (!account) { + _error("UserAgent: Error: Transfer account is null. Returning."); return false; } - if (call==0) { - _debug ("! SIP Failure: Call doesn't exist"); + if (!call) { + _error ("UserAgent: Error: Call doesn't exist"); return false; } @@ -1128,7 +1139,7 @@ SIPVoIPLink::transfer (const CallID& id, const std::string& to) pj_cstr (&pjDest, dest.c_str()); } - _debug ("Transfering to %s", dest.c_str()); + _info ("UserAgent: Transfering to %s", dest.c_str()); /* Create xfer client subscription. */ pj_bzero (&xfer_cb, sizeof (xfer_cb)); @@ -1137,13 +1148,13 @@ SIPVoIPLink::transfer (const CallID& id, const std::string& to) status = pjsip_xfer_create_uac (call->getInvSession()->dlg, &xfer_cb, &sub); if (status != PJ_SUCCESS) { - _debug ("UserAgent: Unable to create xfer -- %d", status); + _warn ("UserAgent: Unable to create xfer -- %d", status); return false; } /* Associate this voiplink of call with the client subscription * We can not just associate call with the client subscription - * because after this function, we can not find the cooresponding + * because after this function, we can no find the cooresponding * voiplink from the call any more. But the voiplink is useful! */ pjsip_evsub_set_mod_data (sub, getModId(), this); @@ -1154,15 +1165,21 @@ SIPVoIPLink::transfer (const CallID& id, const std::string& to) status = pjsip_xfer_initiate (sub, &pjDest, &tdata); if (status != PJ_SUCCESS) { - _debug ("UserAgent: Unable to create REFER request -- %d", status); + _error ("UserAgent: Unable to create REFER request -- %d", status); return false; } + // Put SIP call id in map in order to retrieve call during transfer callback + std::string callidtransfer(call->getInvSession()->dlg->call_id->id.ptr, call->getInvSession()->dlg->call_id->id.slen); + _debug("%s", callidtransfer.c_str()); + transferCallID.insert(std::pair<std::string, CallID>(callidtransfer, call->getCallId())); + + /* Send. */ status = pjsip_xfer_send_request (sub, tdata); if (status != PJ_SUCCESS) { - _debug ("UserAgent: Unable to send REFER request -- %d", status); + _error ("UserAgent: Unable to send REFER request -- %d", status); return false; } @@ -1171,7 +1188,12 @@ SIPVoIPLink::transfer (const CallID& id, const std::string& to) bool SIPVoIPLink::transferStep2 (SIPCall* call) { - call->getAudioRtp()->stop(); + + // TODO is this the best way to proceed? + Manager::instance().peerHungupCall(call->getCallId()); + + + return true; } @@ -1182,17 +1204,18 @@ SIPVoIPLink::refuse (const CallID& id) pj_status_t status; pjsip_tx_data *tdata; + _debug("UserAgent: Refuse call %s", id.c_str()); call = getSIPCall (id); if (call==0) { - _debug ("Call doesn't exist"); + _error ("UserAgent: Error: Call doesn't exist"); return false; } // can't refuse outgoing call or connected if (!call->isIncoming() || call->getConnectionState() == Call::Connected) { - _debug ("It's not an incoming call, or it's already answered"); + _debug ("UserAgent: Call %s is not in state incoming, or is already answered"); return false; } @@ -1211,6 +1234,8 @@ SIPVoIPLink::refuse (const CallID& id) terminateOneCall (id); + _debug("UserAgent: Refuse call completed"); + return true; } @@ -1374,25 +1399,18 @@ SIPVoIPLink::SIPStartCall (SIPCall* call, const std::string& subject UNUSED) // Creates URI std::string fromUri; - std::string toUri; - std::string contactUri; fromUri = account->getFromUri(); - toUri = call->getPeerNumber(); // expecting a fully well formed sip uri std::string address = findLocalAddressFromUri (toUri, account->getAccountTransport ()); - int port = findLocalPortFromUri (toUri, account->getAccountTransport ()); std::stringstream ss; - std::string portStr; - ss << port; - ss >> portStr; contactUri = account->getContactHeader (address, portStr); @@ -1403,15 +1421,12 @@ SIPVoIPLink::SIPStartCall (SIPCall* call, const std::string& subject UNUSED) contactUri.c_str()); pj_str_t pjFrom; - pj_cstr (&pjFrom, fromUri.c_str()); pj_str_t pjContact; - pj_cstr (&pjContact, contactUri.c_str()); pj_str_t pjTo; - pj_cstr (&pjTo, toUri.c_str()); // Create the dialog (UAC) @@ -1455,7 +1470,6 @@ SIPVoIPLink::SIPStartCall (SIPCall* call, const std::string& subject UNUSED) // decrement transport's ref count // pjsip_transport_dec_ref(account->getAccountTransport()); - status = pjsip_inv_send_msg (inv, tdata); if (status != PJ_SUCCESS) { @@ -1478,7 +1492,7 @@ void SIPVoIPLink::SIPCallServerFailure (SIPCall *call) { if (call != 0) { - _debug ("Server error!"); + _error ("UserAgent: Error: Server error!"); CallID id = call->getCallId(); Manager::instance().callFailure (id); terminateOneCall (id); @@ -1492,7 +1506,10 @@ SIPVoIPLink::SIPCallServerFailure (SIPCall *call) void SIPVoIPLink::SIPCallClosed (SIPCall *call) { + _info("UserAgent: Closing call"); + if (!call) { + _warn("UserAgent: Error: CAll pointer is NULL\n"); return; } @@ -1500,16 +1517,14 @@ SIPVoIPLink::SIPCallClosed (SIPCall *call) if (Manager::instance().isCurrentCall (id)) { call->setAudioStart (false); - _debug ("* SIP Info: Stopping AudioRTP when closing"); + _debug ("UserAgent: Stopping AudioRTP when closing"); call->getAudioRtp()->stop(); } - _debug ("After close RTP"); - Manager::instance().peerHungupCall (id); terminateOneCall (id); removeCall (id); - _debug ("After remove call ID"); + } void @@ -1520,7 +1535,7 @@ SIPVoIPLink::SIPCallReleased (SIPCall *call) } // if we are here.. something when wrong before... - _debug ("SIP call release"); + _debug ("UserAgent: SIP call release"); CallID id = call->getCallId(); @@ -2965,7 +2980,7 @@ void set_voicemail_info (AccountID account, pjsip_msg_body *body) void SIPVoIPLink::handle_reinvite (SIPCall *call) { - _debug ("UserAgent: handle_reinvite"); + _debug ("UserAgent: Handle reinvite"); /* // Close the previous RTP session call->getAudioRtp()->stop (); @@ -2988,7 +3003,7 @@ void SIPVoIPLink::handle_reinvite (SIPCall *call) // This callback is called when the invite session state has changed void call_on_state_changed (pjsip_inv_session *inv, pjsip_event *e) { - _debug ("call_on_state_changed to state %s", invitationStateMap[inv->state]); + _debug ("UserAgent: Call state changed to %s", invitationStateMap[inv->state]); pjsip_rx_data *rdata; pj_status_t status; @@ -3033,7 +3048,6 @@ void call_on_state_changed (pjsip_inv_session *inv, pjsip_event *e) pjsip_evsub_state ev_state = PJSIP_EVSUB_STATE_ACTIVE; switch (call->getInvSession()->state) { - // switch (inv->state) { case PJSIP_INV_STATE_NULL: @@ -3072,9 +3086,7 @@ void call_on_state_changed (pjsip_inv_session *inv, pjsip_event *e) pjsip_tx_data *tdata; pj_status_t status; - status = pjsip_xfer_notify (call->getXferSub(), - ev_state, st_code, - NULL, &tdata); + status = pjsip_xfer_notify (call->getXferSub(), ev_state, st_code, NULL, &tdata); if (status != PJ_SUCCESS) { _debug ("UserAgent: Unable to create NOTIFY -- %d", status); @@ -3133,45 +3145,35 @@ void call_on_state_changed (pjsip_inv_session *inv, pjsip_event *e) _debug ("State: %s. Cause: %.*s", invitationStateMap[inv->state], (int) inv->cause_text.slen, inv->cause_text.ptr); + accId = Manager::instance().getAccountFromCall (call->getCallId()); + link = dynamic_cast<SIPVoIPLink *> (Manager::instance().getAccountLink (accId)); + + // Make sure link is valid + assert(link); + switch (inv->cause) { - /* The call terminates normally - BYE / CANCEL */ + // The call terminates normally - BYE / CANCEL case PJSIP_SC_OK: - case PJSIP_SC_REQUEST_TERMINATED: - accId = Manager::instance().getAccountFromCall (call->getCallId()); - link = dynamic_cast<SIPVoIPLink *> (Manager::instance().getAccountLink (accId)); - - if (link) { - link->SIPCallClosed (call); - } - + link->SIPCallClosed (call); break; - case PJSIP_SC_NOT_FOUND: /* peer not found */ - - case PJSIP_SC_DECLINE: /* We have been ignored */ + case PJSIP_SC_DECLINE: + _debug("UserAgent: Call %s is declined", call->getCallId().c_str()); + if (inv->role == PJSIP_ROLE_UAC) + link->SIPCallServerFailure (call); + break; + case PJSIP_SC_NOT_FOUND: /* peer not found */ case PJSIP_SC_REQUEST_TIMEOUT: /* request timeout */ - case PJSIP_SC_NOT_ACCEPTABLE_HERE: /* no compatible codecs */ - case PJSIP_SC_NOT_ACCEPTABLE_ANYWHERE: - case PJSIP_SC_UNSUPPORTED_MEDIA_TYPE: - case PJSIP_SC_UNAUTHORIZED: - case PJSIP_SC_FORBIDDEN: - case PJSIP_SC_REQUEST_PENDING: - accId = Manager::instance().getAccountFromCall (call->getCallId()); - link = dynamic_cast<SIPVoIPLink *> (Manager::instance().getAccountLink (accId)); - - if (link) { - link->SIPCallServerFailure (call); - } - + link->SIPCallServerFailure (call); break; default: @@ -3185,7 +3187,7 @@ void call_on_state_changed (pjsip_inv_session *inv, pjsip_event *e) // This callback is called after SDP offer/answer session has completed. void call_on_media_update (pjsip_inv_session *inv, pj_status_t status) { - _debug ("UserAgent: Call on media update"); + _debug ("UserAgent: Call media update"); const pjmedia_sdp_session *local_sdp; const pjmedia_sdp_session *remote_sdp; @@ -3324,9 +3326,9 @@ void call_on_forked (pjsip_inv_session *inv, pjsip_event *e) void call_on_tsx_changed (pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e) { - _debug("call_on_tsx_changed to state %s", transactionStateMap[tsx->state]); + assert(tsx); - + _debug("UserAgent: Transaction changed to state %s", transactionStateMap[tsx->state]); if (tsx->role==PJSIP_ROLE_UAS && tsx->state==PJSIP_TSX_STATE_TRYING && pjsip_method_cmp (&tsx->method, &pjsip_refer_method) ==0) { @@ -3336,17 +3338,27 @@ void call_on_tsx_changed (pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_ if (e && e->body.rx_msg.rdata) { + + _debug("Event"); pjsip_tx_data* t_data; pjsip_rx_data* r_data = e->body.rx_msg.rdata; - if (r_data->msg_info.msg->line.req.method.id == PJSIP_OTHER_METHOD) { + if (r_data && r_data->msg_info.msg->line.req.method.id == PJSIP_OTHER_METHOD) { + + _debug("R_data"); + + std::string method_info = "INFO"; + std::string method_notify = "NOTIFY"; + + std::string request = pjsip_rx_data_get_info (r_data); - std::string method_name = "INFO"; - std::string request = r_data->msg_info.msg->line.req.method.name.ptr; + _debug("UserAgent: %s", request.c_str()); - if (request.find (method_name) != (size_t)-1) { + if(request.find (method_notify) != (size_t)-1) { - _debug ("%s", pjsip_rx_data_get_info (r_data)); + } + // Must reply 200 OK on SIP INFO request + else if (request.find (method_info) != (size_t)-1) { pjsip_dlg_create_response (inv->dlg, r_data, PJSIP_SC_OK, NULL, &t_data); @@ -3355,6 +3367,8 @@ void call_on_tsx_changed (pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_ } } } + + _debug("OK: ransaction changed to state"); } void regc_cb (struct pjsip_regc_cbparam *param) @@ -3484,18 +3498,18 @@ mod_on_rx_request (pjsip_rx_data *rdata) std::string method_name; std::string request; + + _info("UserAgent: Receiving REQUEST using transport: %s %s (refcnt=%d)", + rdata->tp_info.transport->obj_name, + rdata->tp_info.transport->info, + (int)pj_atomic_get(rdata->tp_info.transport->ref_cnt)); + // No need to go any further on incoming ACK if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD) { _info("UserAgent: received an ACK"); return true; } - // Handle the incoming call invite in this function - _info("UserAgent: Receiving REQUEST using transport: %s %s (refcnt=%d)", - rdata->tp_info.transport->obj_name, - rdata->tp_info.transport->info, - (int)pj_atomic_get(rdata->tp_info.transport->ref_cnt)); - /* First, let's got the username and server name from the invite. * We will use them to detect which account is the callee. */ @@ -3505,13 +3519,10 @@ mod_on_rx_request (pjsip_rx_data *rdata) userName = std::string (sip_uri->user.ptr, sip_uri->user.slen); server = std::string (sip_uri->host.ptr, sip_uri->host.slen); - _debug ("UserAgent: mod_on_rx_request: %s@%s", userName.c_str(), server.c_str()); - // Get the account id of callee from username and server account_id = Manager::instance().getAccountIdFromNameAndServer (userName, server); /* If we don't find any account to receive the call */ - if (account_id == AccountNULL) { _debug ("UserAgent: Username %s doesn't match any account, using IP2IP!",userName.c_str()); } @@ -3544,7 +3555,7 @@ mod_on_rx_request (pjsip_rx_data *rdata) displayName = std::string (""); } - _debug ("UserAgent: The receiver is : %s@%s", userName.data(), server.data()); + _debug ("UserAgent: The receiver is: %s@%s", userName.data(), server.data()); _debug ("UserAgent: The callee account id is %s", account_id.c_str()); /* Now, it is the time to find the information of the caller */ @@ -3562,6 +3573,7 @@ mod_on_rx_request (pjsip_rx_data *rdata) // Get the server voicemail notification // Catch the NOTIFY message if (rdata->msg_info.msg->line.req.method.id == PJSIP_OTHER_METHOD) { + method_name = "NOTIFY"; // Retrieve all the message. Should contains only the method name but ... request = rdata->msg_info.msg->line.req.method.name.ptr; @@ -3598,10 +3610,10 @@ mod_on_rx_request (pjsip_rx_data *rdata) get_remote_sdp_from_offer (rdata, &r_sdp); if(account->getActiveCodecs().empty()) { - _warn ("UserAgent: Error: No active codec"); - pj_strdup2 (_pool, &reason, "no active codec"); + _warn ("UserAgent: Error: No active codec"); + pj_strdup2 (_pool, &reason, "no active codec"); pjsip_endpt_respond_stateless (_endpt, rdata, PJSIP_SC_NOT_ACCEPTABLE_HERE , - &reason, NULL, NULL); + &reason, NULL, NULL); return true; } @@ -3640,13 +3652,14 @@ mod_on_rx_request (pjsip_rx_data *rdata) id = Manager::instance().getNewCallID(); call = new SIPCall (id, Call::Incoming, _pool); - /* If an error occured at the call creation */ + + // If an error occured at the call creation if (!call) { _warn("UserAgent: Error: Unable to create an incoming call"); - pj_strdup2 (_pool, &reason, "unable to create an incoming call"); + pj_strdup2 (_pool, &reason, "unable to create an incoming call"); pjsip_endpt_respond_stateless (_endpt, rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, &reason, NULL, NULL); - return false; + return false; } std::string addrToUse, addrSdp ="0.0.0.0"; @@ -3658,17 +3671,17 @@ mod_on_rx_request (pjsip_rx_data *rdata) // May use the published address as well addrToUse = SIPVoIPLink::instance("")->getInterfaceAddrFromName(account->getLocalInterface ()); - account->isStunEnabled () ? addrSdp = account->getPublishedAddress () : addrSdp = addrToUse; - // Set the appropriate transport to have the right VIA header - link->init_transport_selector (account->getAccountTransport (), &tp); + account->isStunEnabled () ? addrSdp = account->getPublishedAddress () : addrSdp = addrToUse; + // Set the appropriate transport to have the right VIA header + link->init_transport_selector (account->getAccountTransport (), &tp); - if(account->getAccountTransport()) { + if(account->getAccountTransport()) { - _debug("UserAgent: Process INVITE request using transport: %s %s (refcnt=%i)", - account->getAccountTransport()->obj_name, - account->getAccountTransport()->info, - (int)pj_atomic_get(account->getAccountTransport()->ref_cnt)); - } + _debug("UserAgent: SIP transport for this account: %s %s (refcnt=%i)", + account->getAccountTransport()->obj_name, + account->getAccountTransport()->info, + (int)pj_atomic_get(account->getAccountTransport()->ref_cnt)); + } } @@ -3689,22 +3702,6 @@ mod_on_rx_request (pjsip_rx_data *rdata) call->initRecFileName(); - // Notify UI there is an incoming call - - _debug ("UserAgent: Add call to account link"); - - if (Manager::instance().incomingCall (call, account_id)) { - // Add this call to the callAccountMap in ManagerImpl - Manager::instance().getAccountLink (account_id)->addCall (call); - } else { - // Fail to notify UI - delete call; call = NULL; - _warn ("UserAgent: Fail to notify UI!"); - pj_strdup2 (_pool, &reason, "fail to notify ui"); - pjsip_endpt_respond_stateless (_endpt, rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, - &reason, NULL, NULL); - return false; - } // Have to do some stuff with the SDP // Set the codec map, IP, peer number and so on... for the SIPCall object @@ -3740,7 +3737,7 @@ mod_on_rx_request (pjsip_rx_data *rdata) pj_strdup2 (_pool, &reason, "fail to create uas dialog"); pjsip_endpt_respond_stateless (_endpt, rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, &reason, NULL, NULL); - return true; + return false; } // Specify media capability during invite session creation @@ -3754,7 +3751,8 @@ mod_on_rx_request (pjsip_rx_data *rdata) // Associate the call in the invite session inv->mod_data[_mod_ua.id] = call; - // Send a 180/Ringing response + // Send a 180 Ringing response + _info ("UserAgent: Send a 180 Ringing response"); status = pjsip_inv_initial_answer (inv, rdata, PJSIP_SC_RINGING, NULL, NULL, &tdata); PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1); @@ -3769,6 +3767,20 @@ mod_on_rx_request (pjsip_rx_data *rdata) // Update the connection state call->setConnectionState (Call::Ringing); + _debug ("UserAgent: Add call to account link"); + if (Manager::instance().incomingCall (call, account_id)) { + // Add this call to the callAccountMap in ManagerImpl + Manager::instance().getAccountLink (account_id)->addCall (call); + } else { + // Fail to notify UI + delete call; call = NULL; + _warn ("UserAgent: Fail to notify UI!"); + pj_strdup2 (_pool, &reason, "fail to notify ui"); + pjsip_endpt_respond_stateless (_endpt, rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, + &reason, NULL, NULL); + return false; + } + /* Done */ return true; @@ -3826,8 +3838,7 @@ void onCallTransfered (pjsip_inv_session *inv, pjsip_rx_data *rdata) * request. */ ref_by_hdr = (pjsip_hdr*) - pjsip_msg_find_hdr_by_name (rdata->msg_info.msg, &str_ref_by, - NULL); + pjsip_msg_find_hdr_by_name (rdata->msg_info.msg, &str_ref_by, NULL); /* Notify callback */ code = PJSIP_SC_ACCEPTED; @@ -4013,10 +4024,9 @@ void xfer_func_cb (pjsip_evsub *sub, pjsip_event *event) * When subscription is accepted (got 200/OK to REFER), check if * subscription suppressed. */ - if (pjsip_evsub_get_state (sub) == PJSIP_EVSUB_STATE_ACCEPTED) { - _debug ("Transfer accepted! Waiting for notifications. "); + _debug ("UserAgent: Transfer received, waiting for notifications. "); } @@ -4025,6 +4035,7 @@ void xfer_func_cb (pjsip_evsub *sub, pjsip_event *event) */ else if (pjsip_evsub_get_state (sub) == PJSIP_EVSUB_STATE_ACTIVE || pjsip_evsub_get_state (sub) == PJSIP_EVSUB_STATE_TERMINATED) { + pjsip_msg *msg; pjsip_msg_body *body; pjsip_status_line status_line; @@ -4032,13 +4043,6 @@ void xfer_func_cb (pjsip_evsub *sub, pjsip_event *event) pj_bool_t cont; pj_status_t status; - std::string noresource; - std::string ringing; - std::string request; - - noresource = "noresource"; - ringing = "Ringing"; - SIPVoIPLink *link = reinterpret_cast<SIPVoIPLink *> (pjsip_evsub_get_mod_data (sub, _mod_ua.id)); @@ -4052,101 +4056,73 @@ void xfer_func_cb (pjsip_evsub *sub, pjsip_event *event) } + /* Application is not interested with call progress status */ if (!link || !event) { - /* Application is not interested with call progress status */ - _debug ("UserAgent: Either link or event is empty!"); + _warn ("UserAgent: Either link or event is empty in transfer callback"); return; } + pjsip_rx_data* r_data = event->body.rx_msg.rdata; - /* This better be a NOTIFY request */ - if (event->type == PJSIP_EVENT_TSX_STATE && - event->body.tsx_state.type == PJSIP_EVENT_RX_MSG) { - - pjsip_rx_data *rdata; - - rdata = event->body.tsx_state.src.rdata; + std::string method_notify = "NOTIFY"; + std::string request = pjsip_rx_data_get_info (r_data); + /* This better be a NOTIFY request */ + if (r_data->msg_info.msg->line.req.method.id == PJSIP_OTHER_METHOD && + request.find(method_notify) != (size_t)-1) { /* Check if there's body */ - msg = rdata->msg_info.msg; + msg = r_data->msg_info.msg; body = msg->body; if (!body) { - // if (call->getCallConfiguration () == Call::IPtoIP) { - // _debug("UserAgent: IptoIp NOTIFY without message body"); - // } - // else{ - _debug ("UserAgent: Warning! Received NOTIFY without message body"); + _warn ("UserAgent: Warning! Received NOTIFY without message body"); return; - // } } - - /* Check for appropriate content */ if (pj_stricmp2 (&body->content_type.type, "message") != 0 || pj_stricmp2 (&body->content_type.subtype, "sipfrag") != 0) { - _debug ("UserAgent: Warning! Received NOTIFY with non message/sipfrag content"); + _warn ("UserAgent: Warning! Received NOTIFY without message/sipfrag content"); return; } /* Try to parse the content */ - status = pjsip_parse_status_line ( (char*) body->data, body->len, - &status_line); + status = pjsip_parse_status_line ( (char*) body->data, body->len, &status_line); if (status != PJ_SUCCESS) { - _debug ("UserAgent: Warning! Received NOTIFY with invalid message/sipfrag content"); + _warn ("UserAgent: Warning! Received NOTIFY with invalid message/sipfrag content"); return; } } else { - _debug ("UserAgent: Set code to 500!"); + _error ("UserAgent: Error: Set code to 500 during transfer"); status_line.code = 500; status_line.reason = *pjsip_get_status_text (500); } - // Get current call - SIPCall *call = dynamic_cast<SIPCall *> (link->getCall (Manager::instance().getCurrentCallId())); + // Get call coresponding to this transaction + std::string transferID(r_data->msg_info.cid->id.ptr, r_data->msg_info.cid->id.slen); + std::map<std::string, CallID>::iterator it = transferCallID.find(transferID); + CallID cid = it->second; + SIPCall *call = dynamic_cast<SIPCall *> (link->getCall (cid)); if (!call) { - _debug ("UserAgent: Call doesn't exit!"); + _warn ("UserAgent: Call with id %s doesn't exit!", cid.c_str()); return; } - if (event->body.rx_msg.rdata->msg_info.msg_buf != NULL) { - request = event->body.rx_msg.rdata->msg_info.msg_buf; - - if ( (int) request.find (noresource) != -1) { - _debug ("UserAgent: NORESOURCE for transfer!"); - link->transferStep2 (call); - pjsip_evsub_terminate (sub, PJ_TRUE); - - Manager::instance().transferFailed(); - return; - } - - if ( (int) request.find (ringing) != -1) { - _debug ("UserAgent: transfered call RINGING!"); - link->transferStep2 (call); - pjsip_evsub_terminate (sub, PJ_TRUE); - - Manager::instance().transferSucceded(); - return; - } - } - - /* Notify application */ is_last = (pjsip_evsub_get_state (sub) ==PJSIP_EVSUB_STATE_TERMINATED); cont = !is_last; + _debug("UserAgent: Notification status line: %d", status_line.code); if (status_line.code/100 == 2) { - _debug ("UserAgent: Try to stop rtp!"); + _debug ("UserAgent: Received 200 OK on call transfered, stop call!"); pjsip_tx_data *tdata; status = pjsip_inv_end_session (call->getInvSession(), PJSIP_SC_GONE, NULL, &tdata); diff --git a/sippxml/account_uas_recv_hangup.xml b/sippxml/account_uas_recv_hangup.xml index 101e6f4c97442b091dc86fedc913078353126c63..94bea4704232386a5518de7995c3138bc3007850 100644 --- a/sippxml/account_uas_recv_hangup.xml +++ b/sippxml/account_uas_recv_hangup.xml @@ -96,8 +96,6 @@ <recv request="ACK"> </recv> - <pause milliseconds="500"/> - <send retrans="500"> <![CDATA[ diff --git a/sippxml/ip2ip_uac_send_hangup.xml b/sippxml/ip2ip_uac_send_hangup.xml index 49cc63fca06e2cd1f2a40f1f65929de436da7d6b..8b801eb49438bb553a448f28e2c410f86c34a234 100644 --- a/sippxml/ip2ip_uac_send_hangup.xml +++ b/sippxml/ip2ip_uac_send_hangup.xml @@ -95,6 +95,4 @@ <recv response="200"> </recv> - <pause milliseconds="1000"/> - </scenario> diff --git a/sippxml/ip2ip_uac_send_peer_hungup.xml b/sippxml/ip2ip_uac_send_peer_hungup.xml index 4e811e38262f10680417f9415e960e33585b26ee..048b0d8a062521288ed6afc5c21934a2232dd30a 100644 --- a/sippxml/ip2ip_uac_send_peer_hungup.xml +++ b/sippxml/ip2ip_uac_send_peer_hungup.xml @@ -89,6 +89,4 @@ ]]> </send> - <pause milliseconds="1000"/> - </scenario> diff --git a/sippxml/testsuiteuac.sh b/sippxml/testsuiteuac.sh index be9455244341e1074b25b4fbee1f8cbbf9c28391..9e993dfeb80926a0b7131add92bc4d657ab89726 100644 --- a/sippxml/testsuiteuac.sh +++ b/sippxml/testsuiteuac.sh @@ -1,17 +1,22 @@ #!/bin/bash -# sleep 5; -SERVERPORT=5062 + +LOCALPORT=5062 +LOCALIP_lo=127.0.0.1 +LOCALIP_eth0=192.168.50.182 + +REMOTEADDR_lo=127.0.0.1:5060 +REMOTEADDR_ast=192.168.50.79 # SCENARIO 1 Test 1 function test_ip2ip_send_hangup { - # start sipp server to receive calls from sflphone - sipp -sf ip2ip_uas_recv_peer_hungup.xml 127.0.0.1:5060 -i 127.0.0.1 -p ${SERVERPORT} - # start sflphoned # /usr/lib/sflphone/sflphoned& + # start sipp server to receive calls from sflphone + sipp -sf ip2ip_uas_recv_peer_hungup.xml ${REMOTEADDR_lo} -i ${LOCALIP_lo} -p ${LOCALPORT} + # wait some time to make sure sflphoned is started # sleep 1; @@ -25,12 +30,12 @@ function test_ip2ip_send_hangup { # SCENARIO 1 Test 2 function test_ip2ip_send_peer_hungup { - # start sipp server to receive calls from sflphone and then hangup - sipp -sf ip2ip_uas_recv_hangup.xml 127.0.0.1:5060 -s 127.0.0.1:5060 -i 127.0.0.1 -p ${SERVERPORT} - # start sflphoned # /usr/lib/sflphone/sflphoned& + # start sipp server to receive calls from sflphone and then hangup + sipp -sf ip2ip_uas_recv_hangup.xml ${REMOTEADDR_lo} -s ${REMOTEADDR_lo} -i ${LOCALIP_lo} -p ${LOCALPORT} + # wait some time to make sure sflphoned is started # sleep 1; @@ -57,29 +62,7 @@ function test_ip2ip_recv_hangup { # sleep 1; # start sipp client and send calls - sipp -sf ip2ip_uac_send_peer_hungup.xml 127.0.0.1:5060 -i 127.0.0.1 -p ${SERVERPORT} -l 1 - - # kill every one - # bashtrap -} - - -# SCENARIO 1 Test 4 -function test_ip2ip_recv_peer_hungup { - - # start sflphoned - # /usr/lib/sflphone/sflphoned& - - # wait some time to make sure sflphoned is started - # sleep 1; - - # python ../tools/pysflphone/pysflphone_testdbus.py & - - # wait some time to make sure client is bound - # sleep 1; - - # start sipp client and send calls - sipp -sf ip2ip_uac_send_hangup.xml 127.0.0.1:5060 -i 127.0.0.1 -p ${SERVERPORT} -l 1 + sipp -sf ip2ip_uac_send_peer_hungup.xmlip2ip_uac_send_hangup.xml ${REMOTEADDR_lo} -i ${LOCALIP_lo} -p ${LOCALPORT} -l 1 -m 10 # kill every one # bashtrap @@ -100,10 +83,10 @@ function test_account_send_hangup { # sleep 1; # process only one registration - sipp -sf account_uas_register.xml 192.168.50.79 -i 192.168.50.182 -p ${SERVERPORT} -l 1 -m 1 + sipp -sf account_uas_register.xml ${REMOTEADDR_ast} -i ${LOCALIP_eth0} -p ${LOCALPORT} -l 1 -m 1 # start sipp client and send calls - sipp -sf account_uas_recv_peer_hungup.xml 192.168.50.79 -i 192.168.50.182 -p ${SERVERPORT} -l 1 + sipp -sf account_uas_recv_peer_hungup.xml ${REMOTEADDR_ast} -i ${LOCALIP_eth0} -p ${LOCALPORT} -l 1 # kill every one # bashtrap @@ -124,10 +107,10 @@ function test_account_send_peer_hungup { # sleep 1; # process only one registration - sipp -sf account_uas_register.xml 192.168.50.79 -i 192.168.50.182 -p ${SERVERPORT} -l 1 -m 1 + sipp -sf account_uas_register.xml ${REMOTEADDR_ast} -i ${LOCALIP_eth0} -p ${LOCALPORT} -l 1 -m 1 # start sipp client and send calls - sipp -sf account_uas_recv_hangup.xml 192.168.50.79 -i 192.168.50.182 -p ${SERVERPORT} -l 1 + sipp -sf account_uas_recv_hangup.xml ${REMOTEADDR_ast} -i ${LOCALIP_eth0} -p ${LOCALPORT} -l 1 # kill every one # bashtrap @@ -148,11 +131,10 @@ function test_account_recv_hangup { # sleep 1; # process only one registration - sipp -sf account_uas_register.xml 192.168.50.79 -i 192.168.50.182 -p ${SERVERPORT} -l 1 -m 1 + sipp -sf account_uas_register.xml ${REMOTEADDR_ast} -i ${LOCALIP_eth0} -p ${LOCALPORT} -l 1 -m 1 # start sipp client and send calls - sipp -sf account_uac_send_peer_hungup.xml 192.168.50.79 -i 192.168.50.182 -p ${SERVERPORT} -l 1 - + sipp -sf account_uac_send_peer_hungup.xml ${REMOTEADDR_ast} -i ${LOCALIP_eth0} -p ${LOCALPORT} -l 1 -m 10 # kill every one # bashtrap } @@ -172,10 +154,10 @@ function test_account_recv_peer_hungup { # sleep 1; # process only one registration - sipp -sf account_uas_register.xml 192.168.50.79 -i 192.168.50.182 -p ${SERVERPORT} -l 1 -m 1 + sipp -sf account_uas_register.xml ${REMOTEADDR_ast} -i ${LOCALIP_eth0} -p ${LOCALPORT} -l 1 -m 1 # start sipp client and send calls - sipp -sf account_uac_send_hangup.xml 192.168.50.79 -i 192.168.50.182 -p ${SERVERPORT} -l 1 + sipp -sf account_uac_send_hangup.xml ${REMOTEADDR_ast} -i ${LOCALIP_eth0} -p ${LOCALPORT} -l 1 -m 10 # kill every one # bashtrap @@ -196,7 +178,7 @@ function test_ip2ip_send_hold_offhold { # sleep 1; # start sipp client and send calls - sipp -sf ip2ip_uas_recv_hold_offhold.xml 127.0.0.1:5060 -i 127.0.0.1 -p ${SERVERPORT} + sipp -sf ip2ip_uas_recv_hold_offhold.xml ${REMOTEADDR_lo} -i ${LOCALIP_lo} -p ${LOCALPORT} # kill every one # bashtrap } @@ -216,16 +198,36 @@ function test_account_send_transfer { # sleep 1; # process only one registration - sipp -sf account_uas_register.xml 192.168.50.79 -i 192.168.50.182 -p ${SERVERPORT} -l 1 -m 1 + sipp -sf account_uas_register.xml ${REMOTEADDR_ast} -i ${LOCALIP_eth0} -p ${LOCALPORT} -l 1 -m 1 # start sipp client and send calls - sipp -sf account_uas_recv_transfered.xml 192.168.50.79 -i 192.168.50.182 -p ${SERVERPORT} -l 1 + sipp -sf account_uas_recv_transfered.xml ${REMOTEADDR_ast} -i ${LOCALIP_eth0} -p ${LOCALPORT} -l 1 # kill every one # bashtrap } +# SCENARIO 5 Test 1 +function test_ip2ip_send_refused { + + # start sflphoned + # /usr/lib/sflphone/sflphoned& + + # start sipp server to receive calls from sflphone and then hangup + sipp -sf ip2ip_uac_send_refused.xml ${REMOTEADDR_lo} -s ${REMOTEADDR_lo} -i ${LOCALIP_lo} -p ${LOCALPORT} -l 1 + + # wait some time to make sure sflphoned is started + # sleep 1; + + # run python client and script to make calls + # python ../tools/pysflphone/pysflphone_testdbus.py & + + # kill every one + bashtrap +} + + # function called if CTRL-C detected bashtrap() { @@ -236,20 +238,68 @@ bashtrap() # ============================ Test Suite ============================ -# SCENARIO 1: Normal flow calls (IP2IP) + + +# SCENARIO 1: (IP2IP) Normal flow calls + +# Test 1: - Send an IP2IP call +# - Hangup # test_ip2ip_send_hangup + +# Test 2: - Send an IP2IP call +# - Peer Hangup # test_ip2ip_send_peer_hungup + +# Test 3: - Receive an IP2IP call +# - Hangup # test_ip2ip_recv_hangup + +# Test 4: - Receive an IP2IP call +# - Peer Hangup # test_ip2ip_recv_peer_hungup -# SCENARIO 2: Normal flow calls (Account) + + +# SCENARIO 2: (ACCOUNT) Normal flow calls + +# Test 1: - Send an ACCOUNT call +# - Hangup # test_account_send_hangup + +# Test 2: - Send an ACCOUNT call +# - Peer Hangup # test_account_send_peer_hungup + +# Test 3: - Receive an ACCOUNT call +# - Hangup # test_account_recv_hangup + +# Test 4: - Receive an ACCOUNT call +# - Peer Hangup # test_account_recv_peer_hungup + + # SCENARIO 3: Hold/offHold calls (Account) + +# Test 1: - Send an IP2IP call +# - Put this call on HOLD +# - Off HOLD this call +# - Hangup # test_ip2ip_send_hold_offhold + + # SCENARIO 4: Transfer calls (Account) -test_account_send_transfer \ No newline at end of file + +# Test 1: - Send an IP2IP call +# - Transfer this call to another sipp instance +# - Hangup +# test_account_send_transfer + + +#SCENARIO 5: Refuse call (IP2IP) + +# Test 1: - Receive a call +# - Refuse (hangup without answer) +test_ip2ip_send_refused \ No newline at end of file diff --git a/tools/pysflphone/pysflphone_testdbus.py b/tools/pysflphone/pysflphone_testdbus.py index 3e7c97f0b03dc2df97dc4f643275e11224d75ce2..933f8736c9ab8e57183006a92069910119ff66d2 100644 --- a/tools/pysflphone/pysflphone_testdbus.py +++ b/tools/pysflphone/pysflphone_testdbus.py @@ -13,21 +13,37 @@ from threading import Event print "Import SFLphone" from sflphonectrlsimple import SflPhoneCtrlSimple -# def killhandler(signum, frame): -# raise IOError("Couldn't open device!") +# Define remote IP address constant +REMOTEADDR_lo="127.0.0.1:5062" -# signal.signal(signal.SIGKILL, killhandler) +# Defines phone numbers +PHONE1="27182" +PHONE2="31416" +PHONE3="14142" + +# Define function callback to emulate UA behavior on +# recieving a call (peer hangup)) def acceptOnIncomingCall(sflphone): - time.sleep(0.2) + sflphone.Accept(sflphone.currentCallId) + +# Define function callback to emulate UA behavior on +# receiving a call and hanging up def acceptOnIncomingCallHangup(sflphone): - time.sleep(0.2) - sflphone.Accept(sflphone.currentCallId) - time.sleep(0.5) + + sflphone.Accept(sflphone.currentCallId) sflphone.HangUp(sflphone.currentCallId) + +# Define function callback to emulate UA behavior on +# refusing a call +def refuseOnIncomingCall(sflphone): + # time.sleep(0.5) + sflphone.Refuse(sflphone.currentCallId) + + class SflPhoneTests(): def __init__(self, sfl): @@ -75,12 +91,13 @@ class SflPhoneTests(): print "Account with ID " + accountID + " removed" + # SCENARIO 1 Test 1 def test_ip2ip_send_hangup(self): """Make a call to a server (sipp) on port 5062""" i = 0 while(i < 10): - callid = self.sflphone.Call("sip:test@127.0.0.1:5062") + callid = self.sflphone.Call("sip:test@" + REMOTEADDR_lo) time.sleep(0.5) self.sflphone.HangUp(callid) @@ -91,19 +108,21 @@ class SflPhoneTests(): del self.sflphone + # SCENARIO 1 Test 2 def test_ip2ip_send_peer_hungup(self): """Make a call to a server (sipp) on port 5062""" i = 0 - while(i < 1): + while(i < 10): - callid = self.sflphone.Call("sip:test@127.0.0.1:5062") + callid = self.sflphone.Call("sip:test@" + REMOTEADDR_lo) time.sleep(1.0) i = i+1 del self.sflphone - + + # SCENARIO 1 Test 3 def test_ip2ip_recv_hangup(self): """Wait for calls, answer then hangup""" @@ -114,6 +133,7 @@ class SflPhoneTests(): self.sflphone.start() + # SCENARIO 1 Test 4 def test_ip2ip_recv_peer_hungup(self): """Wait for calls, answer, peer hangup""" # Add callback for this test @@ -123,30 +143,32 @@ class SflPhoneTests(): self.sflphone.start() + # SCENARIO 2 Test 1 def test_account_send_hangup(self): """Send new account call, hangup once peer answered""" i = 0 - while(i < 1): + while(i < 10): - callid = self.sflphone.Call("27182") - time.sleep(1.0) + callid = self.sflphone.Call(PHONE1) + time.sleep(0.2) self.sflphone.HangUp(callid) - time.sleep(1.0) + time.sleep(0.2) i = i+1 # del self.sflphone + # SCENARIO 2 Test 2 def test_account_send_peer_hungup(self): """Send new account call, hangup once peer answered""" i = 0 while(i < 10): - callid = self.sflphone.Call("27182") + callid = self.sflphone.Call(PHONE1) time.sleep(1.0) i = i+1 @@ -154,6 +176,7 @@ class SflPhoneTests(): del self.sflphone + # SCENARIO 2 Test 3 def test_account_recv_hangup(self): """Register an account and wait for incoming calls""" @@ -164,6 +187,7 @@ class SflPhoneTests(): self.sflphone.start() + # SCENARIO 2 Test 4 def test_account_recv_peer_hungup(self): """Register an account and wait for incoming calls""" @@ -174,12 +198,13 @@ class SflPhoneTests(): self.sflphone.start() + # SCENARIO 3 Test 1 def test_ip2ip_send_hold_offhold(self): """Send new call, hold this call, offhold, hangup""" i = 0 while(i < 10): - callid = self.sflphone.Call("sip:test@127.0.0.1:5062") + callid = self.sflphone.Call("sip:test@" + REMOTEADDR_lo) time.sleep(0.5) self.sflphone.Hold(callid) @@ -196,22 +221,34 @@ class SflPhoneTests(): del self.sflphone + # SCENARIO 4 Test 1 def test_account_send_transfer(self): """Send new calls, transfer it to a new instance""" i = 0 while(i < 1): - callid = self.sflphone.Call("27182") + callid = self.sflphone.Call(PHONE1) time.sleep(1.0) - self.sflphone.Transfer(callid,"14142") + self.sflphone.Transfer(callid,PHONE3) # self.sflphone.HangUp(callid) # time.sleep(1.0) i = i+1 + # SCENARIO 5 Test 1 + def test_ip2ip_recv_refuse(self): + """Receive an incoming IP2IP call, refuse it""" + + # Add callback for this test + self.sflphone.onIncomingCall_cb = refuseOnIncomingCall + + # Start Glib mainloop + self.sflphone.start() + + # Open sflphone and connect to sflphoned through dbus sflphone = SflPhoneCtrlSimple(True) @@ -223,6 +260,10 @@ testsuite = SflPhoneTests(sflphone) sflphone.setFirstRegisteredAccount(); +# ============================ Test Suite ============================ + + + # SCENARIO 1: IP2IP Normal flow calls # Test 1: - Send an IP2IP call @@ -262,6 +303,7 @@ sflphone.setFirstRegisteredAccount(); # testsuite.test_account_recv_peer_hungup() + # SCENARIO 3: IP2IP Call, HOLD/OFFHOLD # Test 1: - Send an IP2IP call @@ -271,9 +313,18 @@ sflphone.setFirstRegisteredAccount(); # testsuite.test_ip2ip_send_hold_offhold() + # SCENARIO 4: IP2IP Call, HOLD/OFFHOLD # Test 1: - Send an IP2IP call # - Transfer this call to another sipp instance # - Hangup -testsuite.test_account_send_transfer() +# testsuite.test_account_send_transfer() + + + +# SCENARIO 5: IP2IP Call, Refuse + +# Test 1: - Receive an incoming call +# - Hangup without answer +testsuite.test_ip2ip_recv_refuse() diff --git a/tools/pysflphone/sflphonectrlsimple.py b/tools/pysflphone/sflphonectrlsimple.py index a19d4ab0901f4b28fb2081d3f68fc58a5419b2e1..491e105e8256fb6314c80b95b081fb0d5c7f75fc 100755 --- a/tools/pysflphone/sflphonectrlsimple.py +++ b/tools/pysflphone/sflphonectrlsimple.py @@ -66,6 +66,7 @@ class SflPhoneCtrlSimple(Thread): self.registered = False self.register() self.currentCallId = "" + self.loop = MainLoop() self.test = test @@ -534,11 +535,12 @@ class SflPhoneCtrlSimple(Thread): def Refuse(self, callid): """Refuse an incoming call identified by a CallID""" - if not self.account: - self.setFirstRegisteredAccount() + print "Refuse call " + callid + # if not self.account: + # self.setFirstRegisteredAccount() - if not self.isAccountRegistered(): - raise SflPhoneError("Can't refuse a call without a registered account") + # if not self.isAccountRegistered(): + # raise SflPhoneError("Can't refuse a call without a registered account") if callid is None or callid == "": raise SflPhoneError("Invalid callID") @@ -548,6 +550,7 @@ class SflPhoneCtrlSimple(Thread): def Accept(self, callid): """Accept an incoming call identified by a CallID""" + print "Accept call " + callid if not self.account: self.setFirstRegisteredAccount() @@ -603,4 +606,9 @@ class SflPhoneCtrlSimple(Thread): return callid def run(self): - self.loop.run() + gobject.threads_init() + # self.loop.run() + context = self.loop.get_context() + + while 1: + context.iteration(True)