first pass at connecting audio config dialog to rest of system. Can configure single...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sun, 11 Nov 2012 01:22:01 +0000 (01:22 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sun, 11 Nov 2012 01:22:01 +0000 (01:22 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@956 01035d8c-6547-0410-b346-abe4f91aad63

fdmdv2/src/dlg_audiooptions.cpp
fdmdv2/src/dlg_audiooptions.h
fdmdv2/src/fdmdv2_main.cpp
fdmdv2/src/fdmdv2_main.h

index c120249d8737df3e7f9ffa9d3d21e0eedc96c34d..c5d65b49aa1658cda7b089eae201035320aa9c79 100644 (file)
-//=========================================================================\r
-// Name:          AudioOptsDialog.cpp\r
-// Purpose:       Implements simple wxWidgets application with GUI\r
-//                created using wxFormBuilder.\r
-// Author:\r
-// Created:\r
-// Copyright:\r
-// License:       wxWidgets license (www.wxwidgets.org)\r
-//\r
-// Notes:         Note that all GUI creation code is implemented in\r
-//                gui.cpp source file which is generated by wxFormBuilder.\r
-//=========================================================================\r
-#include "fdmdv2_main.h"\r
-#include "dlg_audiooptions.h"\r
-\r
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=\r
-// AudioOptsDialog()\r
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=\r
-AudioOptsDialog::AudioOptsDialog(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxDialog(parent, id, title, pos, size, style)\r
-{\r
-    this->SetSizeHints(wxSize(650, 400), wxDefaultSize);\r
-\r
-    m_isPaInitialized = false;\r
-\r
-    if(!m_isPaInitialized)\r
-    {\r
-        if((pa_err = Pa_Initialize()) == paNoError)\r
-        {\r
-            m_isPaInitialized = true;\r
-        }\r
-        else\r
-        {\r
-            wxMessageBox(wxT("Port Audio failed to initialize"), wxT("Pa_Initialize"), wxOK);\r
-            return;\r
-        }\r
-    }\r
-\r
-    wxBoxSizer* mainSizer;\r
-    mainSizer = new wxBoxSizer(wxVERTICAL);\r
-    m_panel1 = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);\r
-    wxBoxSizer* bSizer4;\r
-    bSizer4 = new wxBoxSizer(wxVERTICAL);\r
-    m_notebook1 = new wxNotebook(m_panel1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_BOTTOM);\r
-    m_panelRx = new wxPanel(m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);\r
-    wxBoxSizer* bSizer20;\r
-    bSizer20 = new wxBoxSizer(wxVERTICAL);\r
-    wxGridSizer* gSizer4;\r
-    gSizer4 = new wxGridSizer(2, 1, 0, 0);\r
-    wxStaticBoxSizer* sbSizer2;\r
-    sbSizer2 = new wxStaticBoxSizer(new wxStaticBox(m_panelRx, wxID_ANY, _("Rx Radio Device")), wxVERTICAL);\r
-    m_listCtrlRxInDevices = new wxListCtrl(m_panelRx, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_HRULES|wxLC_REPORT|wxLC_VRULES);\r
-    sbSizer2->Add(m_listCtrlRxInDevices, 1, wxALL|wxEXPAND, 1);\r
-    wxBoxSizer* bSizer811;\r
-    bSizer811 = new wxBoxSizer(wxHORIZONTAL);\r
-    m_staticText51 = new wxStaticText(m_panelRx, wxID_ANY, _("Device:"), wxDefaultPosition, wxDefaultSize, 0);\r
-    m_staticText51->Wrap(-1);\r
-    bSizer811->Add(m_staticText51, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5);\r
-    m_textCtrlRxIn = new wxTextCtrl(m_panelRx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);\r
-    bSizer811->Add(m_textCtrlRxIn, 1, wxALIGN_CENTER_VERTICAL|wxALL, 1);\r
-    m_staticText6 = new wxStaticText(m_panelRx, wxID_ANY, _("Sample Rate:"), wxDefaultPosition, wxDefaultSize, 0);\r
-    m_staticText6->Wrap(-1);\r
-    bSizer811->Add(m_staticText6, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5);\r
-    m_cbSampleRateRxIn = new wxComboBox(m_panelRx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN);\r
-    bSizer811->Add(m_cbSampleRateRxIn, 0, wxALL, 1);\r
-    sbSizer2->Add(bSizer811, 0, wxEXPAND, 5);\r
-    gSizer4->Add(sbSizer2, 1, wxEXPAND, 5);\r
-    wxStaticBoxSizer* sbSizer3;\r
-    sbSizer3 = new wxStaticBoxSizer(new wxStaticBox(m_panelRx, wxID_ANY, _("Rx Speaker Stream")), wxVERTICAL);\r
-    m_listCtrlRxOutDevices = new wxListCtrl(m_panelRx, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_HRULES|wxLC_REPORT|wxLC_VRULES);\r
-    sbSizer3->Add(m_listCtrlRxOutDevices, 1, wxALL|wxEXPAND, 1);\r
-    wxBoxSizer* bSizer81;\r
-    bSizer81 = new wxBoxSizer(wxHORIZONTAL);\r
-    m_staticText9 = new wxStaticText(m_panelRx, wxID_ANY, _("Device:"), wxDefaultPosition, wxDefaultSize, 0);\r
-    m_staticText9->Wrap(-1);\r
-    bSizer81->Add(m_staticText9, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);\r
-    m_textCtrlRxOut = new wxTextCtrl(m_panelRx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);\r
-    bSizer81->Add(m_textCtrlRxOut, 1, wxALIGN_CENTER_VERTICAL|wxALL, 1);\r
-    m_staticText10 = new wxStaticText(m_panelRx, wxID_ANY, _("Sample Rate:"), wxDefaultPosition, wxDefaultSize, 0);\r
-    m_staticText10->Wrap(-1);\r
-    bSizer81->Add(m_staticText10, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5);\r
-    m_cbSampleRateRxOut = new wxComboBox(m_panelRx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN);\r
-    bSizer81->Add(m_cbSampleRateRxOut, 0, wxALIGN_CENTER_VERTICAL|wxALL, 1);\r
-    sbSizer3->Add(bSizer81, 0, wxEXPAND, 2);\r
-    gSizer4->Add(sbSizer3, 1, wxEXPAND, 2);\r
-    bSizer20->Add(gSizer4, 1, wxEXPAND, 1);\r
-    m_panelRx->SetSizer(bSizer20);\r
-    m_panelRx->Layout();\r
-    bSizer20->Fit(m_panelRx);\r
-    m_notebook1->AddPage(m_panelRx, _("Receive"), true);\r
-    m_panelTx = new wxPanel(m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);\r
-    wxBoxSizer* bSizer18;\r
-    bSizer18 = new wxBoxSizer(wxVERTICAL);\r
-    wxGridSizer* gSizer2;\r
-    gSizer2 = new wxGridSizer(2, 1, 0, 0);\r
-    wxStaticBoxSizer* sbSizer22;\r
-    sbSizer22 = new wxStaticBoxSizer(new wxStaticBox(m_panelTx, wxID_ANY, _("Tx Microphone Stream")), wxVERTICAL);\r
-    m_listCtrlTxInDevices = new wxListCtrl(m_panelTx, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_HRULES|wxLC_REPORT|wxLC_VRULES);\r
-    sbSizer22->Add(m_listCtrlTxInDevices, 1, wxALL|wxEXPAND, 1);\r
-    wxBoxSizer* bSizer83;\r
-    bSizer83 = new wxBoxSizer(wxHORIZONTAL);\r
-    m_staticText12 = new wxStaticText(m_panelTx, wxID_ANY, _("Device:"), wxDefaultPosition, wxDefaultSize, 0);\r
-    m_staticText12->Wrap(-1);\r
-    bSizer83->Add(m_staticText12, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5);\r
-    m_textCtrlTxIn = new wxTextCtrl(m_panelTx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);\r
-    bSizer83->Add(m_textCtrlTxIn, 1, wxALIGN_CENTER_VERTICAL|wxALL, 1);\r
-    m_staticText11 = new wxStaticText(m_panelTx, wxID_ANY, _("Sample Rate:"), wxDefaultPosition, wxDefaultSize, 0);\r
-    m_staticText11->Wrap(-1);\r
-    bSizer83->Add(m_staticText11, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5);\r
-    m_cbSampleRateTxIn = new wxComboBox(m_panelTx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN);\r
-    bSizer83->Add(m_cbSampleRateTxIn, 0, wxALL, 1);\r
-    sbSizer22->Add(bSizer83, 0, wxEXPAND, 2);\r
-    gSizer2->Add(sbSizer22, 1, wxEXPAND, 5);\r
-    wxStaticBoxSizer* sbSizer21;\r
-    sbSizer21 = new wxStaticBoxSizer(new wxStaticBox(m_panelTx, wxID_ANY, _("Tx Radio Stream")), wxVERTICAL);\r
-    m_listCtrlTxOutDevices = new wxListCtrl(m_panelTx, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_HRULES|wxLC_REPORT|wxLC_VRULES);\r
-    sbSizer21->Add(m_listCtrlTxOutDevices, 1, wxALL|wxEXPAND, 2);\r
-    wxBoxSizer* bSizer82;\r
-    bSizer82 = new wxBoxSizer(wxHORIZONTAL);\r
-    m_staticText81 = new wxStaticText(m_panelTx, wxID_ANY, _("Device:"), wxDefaultPosition, wxDefaultSize, 0);\r
-    m_staticText81->Wrap(-1);\r
-    bSizer82->Add(m_staticText81, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);\r
-    m_textCtrlTxOut = new wxTextCtrl(m_panelTx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);\r
-    bSizer82->Add(m_textCtrlTxOut, 1, wxALIGN_CENTER_VERTICAL|wxALL, 1);\r
-    m_staticText71 = new wxStaticText(m_panelTx, wxID_ANY, _("Sample Rate:"), wxDefaultPosition, wxDefaultSize, 0);\r
-    m_staticText71->Wrap(-1);\r
-    bSizer82->Add(m_staticText71, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5);\r
-    m_cbSampleRateTxOut = new wxComboBox(m_panelTx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN);\r
-    bSizer82->Add(m_cbSampleRateTxOut, 0, wxALL, 1);\r
-    sbSizer21->Add(bSizer82, 0, wxEXPAND, 2);\r
-    gSizer2->Add(sbSizer21, 1, wxEXPAND, 5);\r
-    bSizer18->Add(gSizer2, 1, wxEXPAND, 1);\r
-    m_panelTx->SetSizer(bSizer18);\r
-    m_panelTx->Layout();\r
-    bSizer18->Fit(m_panelTx);\r
-    m_notebook1->AddPage(m_panelTx, _("Transmit"), false);\r
-    m_panelAPI = new wxPanel(m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);\r
-    wxBoxSizer* bSizer12;\r
-    bSizer12 = new wxBoxSizer(wxHORIZONTAL);\r
-    wxGridSizer* gSizer31;\r
-    gSizer31 = new wxGridSizer(2, 1, 0, 0);\r
-    wxStaticBoxSizer* sbSizer1;\r
-    sbSizer1 = new wxStaticBoxSizer(new wxStaticBox(m_panelAPI, wxID_ANY, _("PortAudio")), wxVERTICAL);\r
-    wxGridSizer* gSizer3;\r
-    gSizer3 = new wxGridSizer(4, 2, 0, 0);\r
-    m_staticText7 = new wxStaticText(m_panelAPI, wxID_ANY, _("PortAudio Version String:"), wxDefaultPosition, wxDefaultSize, 0);\r
-    m_staticText7->Wrap(-1);\r
-    gSizer3->Add(m_staticText7, 0, wxALIGN_RIGHT|wxALL|wxALIGN_CENTER_VERTICAL, 1);\r
-    wxBoxSizer* bSizer151;\r
-    bSizer151 = new wxBoxSizer(wxVERTICAL);\r
-    m_textStringVer = new wxTextCtrl(m_panelAPI, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY);\r
-    bSizer151->Add(m_textStringVer, 0, wxALL|wxEXPAND, 1);\r
-    gSizer3->Add(bSizer151, 1, wxEXPAND, 2);\r
-    m_staticText8 = new wxStaticText(m_panelAPI, wxID_ANY, _("PortAudio Int Version:"), wxDefaultPosition, wxDefaultSize, 0);\r
-    m_staticText8->Wrap(-1);\r
-    gSizer3->Add(m_staticText8, 0, wxALIGN_RIGHT|wxALL|wxALIGN_CENTER_VERTICAL, 1);\r
-    wxBoxSizer* bSizer13;\r
-    bSizer13 = new wxBoxSizer(wxVERTICAL);\r
-    m_textIntVer = new wxTextCtrl(m_panelAPI, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY);\r
-    bSizer13->Add(m_textIntVer, 0, wxALL|wxALIGN_CENTER_VERTICAL, 1);\r
-    gSizer3->Add(bSizer13, 1, wxEXPAND, 5);\r
-    m_staticText5 = new wxStaticText(m_panelAPI, wxID_ANY, _("Device Count:"), wxDefaultPosition, wxDefaultSize, 0);\r
-    m_staticText5->Wrap(-1);\r
-    gSizer3->Add(m_staticText5, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 1);\r
-    wxBoxSizer* bSizer14;\r
-    bSizer14 = new wxBoxSizer(wxVERTICAL);\r
-    m_textCDevCount = new wxTextCtrl(m_panelAPI, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(45,-1), wxTE_READONLY);\r
-    m_textCDevCount->SetMaxSize(wxSize(45,-1));\r
-    bSizer14->Add(m_textCDevCount, 0, wxALIGN_CENTER_VERTICAL|wxALL, 1);\r
-    gSizer3->Add(bSizer14, 1, wxEXPAND, 5);\r
-    m_staticText4 = new wxStaticText(m_panelAPI, wxID_ANY, _("API Count:"), wxDefaultPosition, wxDefaultSize, 0);\r
-    m_staticText4->Wrap(-1);\r
-    gSizer3->Add(m_staticText4, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 1);\r
-    wxBoxSizer* bSizer15;\r
-    bSizer15 = new wxBoxSizer(wxVERTICAL);\r
-    m_textAPICount = new wxTextCtrl(m_panelAPI, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(45,-1), wxTE_READONLY);\r
-    m_textAPICount->SetMaxSize(wxSize(45,-1));\r
-    bSizer15->Add(m_textAPICount, 0, wxALIGN_CENTER_VERTICAL|wxALL, 1);\r
-    gSizer3->Add(bSizer15, 1, wxEXPAND, 5);\r
-    sbSizer1->Add(gSizer3, 1, wxEXPAND, 2);\r
-    gSizer31->Add(sbSizer1, 1, wxEXPAND, 2);\r
-    wxStaticBoxSizer* sbSizer6;\r
-    sbSizer6 = new wxStaticBoxSizer(new wxStaticBox(m_panelAPI, wxID_ANY, _("Other")), wxVERTICAL);\r
-    gSizer31->Add(sbSizer6, 1, wxEXPAND, 5);\r
-    bSizer12->Add(gSizer31, 1, wxEXPAND, 5);\r
-    m_panelAPI->SetSizer(bSizer12);\r
-    m_panelAPI->Layout();\r
-    bSizer12->Fit(m_panelAPI);\r
-    m_notebook1->AddPage(m_panelAPI, _("API Info"), false);\r
-    bSizer4->Add(m_notebook1, 1, wxEXPAND | wxALL, 0);\r
-    m_panel1->SetSizer(bSizer4);\r
-    m_panel1->Layout();\r
-    bSizer4->Fit(m_panel1);\r
-    mainSizer->Add(m_panel1, 1, wxEXPAND | wxALL, 1);\r
-    wxBoxSizer* bSizer6;\r
-    bSizer6 = new wxBoxSizer(wxHORIZONTAL);\r
-    m_btnRefresh = new wxButton(this, wxID_ANY, _("Refresh"), wxDefaultPosition, wxDefaultSize, 0);\r
-    bSizer6->Add(m_btnRefresh, 0, wxALIGN_CENTER|wxALL, 2);\r
-    m_sdbSizer1 = new wxStdDialogButtonSizer();\r
-    m_sdbSizer1OK = new wxButton(this, wxID_OK);\r
-    m_sdbSizer1->AddButton(m_sdbSizer1OK);\r
-    m_sdbSizer1Apply = new wxButton(this, wxID_APPLY);\r
-    m_sdbSizer1->AddButton(m_sdbSizer1Apply);\r
-    m_sdbSizer1Cancel = new wxButton(this, wxID_CANCEL);\r
-    m_sdbSizer1->AddButton(m_sdbSizer1Cancel);\r
-    m_sdbSizer1->Realize();\r
-    bSizer6->Add(m_sdbSizer1, 1, wxALIGN_CENTER_VERTICAL, 2);\r
-    mainSizer->Add(bSizer6, 0, wxEXPAND, 2);\r
-    this->SetSizer(mainSizer);\r
-    this->Layout();\r
-    this->Centre(wxBOTH);\r
-//    this->Centre(wxBOTH);\r
-\r
-    m_notebook1->SetSelection(0);\r
-\r
-    showAPIInfo();\r
-    m_RxInDevices.m_listDevices   = m_listCtrlRxInDevices;\r
-    m_RxInDevices.direction       = AUDIO_IN;\r
-    m_RxInDevices.m_textDevice    = m_textCtrlRxIn;\r
-    m_RxInDevices.m_cbSampleRate  = m_cbSampleRateRxIn;\r
-\r
-    m_RxOutDevices.m_listDevices  = m_listCtrlRxOutDevices;\r
-    m_RxOutDevices.direction      = AUDIO_OUT;\r
-    m_RxOutDevices.m_textDevice   = m_textCtrlRxOut;\r
-    m_RxOutDevices.m_cbSampleRate = m_cbSampleRateRxOut;\r
-\r
-    m_TxInDevices.m_listDevices   = m_listCtrlTxInDevices;\r
-    m_TxInDevices.direction       = AUDIO_IN;\r
-    m_TxInDevices.m_textDevice    = m_textCtrlTxIn;\r
-    m_TxInDevices.m_cbSampleRate  = m_cbSampleRateTxIn;\r
-\r
-    m_TxOutDevices.m_listDevices  = m_listCtrlTxOutDevices;\r
-    m_TxOutDevices.direction      = AUDIO_OUT;\r
-    m_TxOutDevices.m_textDevice   = m_textCtrlTxOut;\r
-    m_TxOutDevices.m_cbSampleRate = m_cbSampleRateTxOut;\r
-\r
-    populateParams(m_RxInDevices);\r
-    populateParams(m_RxOutDevices);\r
-    populateParams(m_TxInDevices);\r
-    populateParams(m_TxOutDevices);\r
-\r
-    m_listCtrlRxInDevices->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( AudioOptsDialog::OnRxInDeviceSelect ), NULL, this );\r
-    m_listCtrlRxOutDevices->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( AudioOptsDialog::OnRxOutDeviceSelect ), NULL, this );\r
-    m_listCtrlTxInDevices->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( AudioOptsDialog::OnTxInDeviceSelect ), NULL, this );\r
-    m_listCtrlTxOutDevices->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( AudioOptsDialog::OnTxOutDeviceSelect ), NULL, this );\r
-    m_btnRefresh->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AudioOptsDialog::OnRefreshClick ), NULL, this );\r
-    m_sdbSizer1Apply->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AudioOptsDialog::OnApplyAudioParameters ), NULL, this );\r
-    m_sdbSizer1Cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AudioOptsDialog::OnCancelAudioParameters ), NULL, this );\r
-    m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AudioOptsDialog::OnOkAudioParameters ), NULL, this );\r
-/*\r
-        void OnClose( wxCloseEvent& event ) { event.Skip(); }\r
-        void OnHibernate( wxActivateEvent& event ) { event.Skip(); }\r
-        void OnIconize( wxIconizeEvent& event ) { event.Skip(); }\r
-        void OnInitDialog( wxInitDialogEvent& event ) { event.Skip(); }\r
-*/\r
-//    this->Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(AudioOptsDialog::OnClose));\r
-    this->Connect(wxEVT_HIBERNATE, wxActivateEventHandler(AudioOptsDialog::OnHibernate));\r
-    this->Connect(wxEVT_ICONIZE, wxIconizeEventHandler(AudioOptsDialog::OnIconize));\r
-    this->Connect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(AudioOptsDialog::OnInitDialog));\r
-}\r
-\r
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=\r
-// ~AudioOptsDialog()\r
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=\r
-AudioOptsDialog::~AudioOptsDialog()\r
-{\r
-    // Disconnect Events\r
-    this->Disconnect(wxEVT_HIBERNATE, wxActivateEventHandler(AudioOptsDialog::OnHibernate));\r
-    this->Disconnect(wxEVT_ICONIZE, wxIconizeEventHandler(AudioOptsDialog::OnIconize));\r
-    this->Disconnect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(AudioOptsDialog::OnInitDialog));\r
-\r
-    m_listCtrlRxInDevices->Disconnect(wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(AudioOptsDialog::OnRxInDeviceSelect), NULL, this);\r
-    m_listCtrlRxOutDevices->Disconnect(wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(AudioOptsDialog::OnRxOutDeviceSelect), NULL, this);\r
-    m_listCtrlTxInDevices->Disconnect(wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(AudioOptsDialog::OnTxInDeviceSelect), NULL, this);\r
-    m_listCtrlTxOutDevices->Disconnect(wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(AudioOptsDialog::OnTxOutDeviceSelect), NULL, this);\r
-    m_btnRefresh->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(AudioOptsDialog::OnRefreshClick), NULL, this);\r
-    m_sdbSizer1Apply->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(AudioOptsDialog::OnApplyAudioParameters), NULL, this);\r
-    m_sdbSizer1Cancel->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(AudioOptsDialog::OnCancelAudioParameters), NULL, this);\r
-    m_sdbSizer1OK->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(AudioOptsDialog::OnOkAudioParameters), NULL, this);\r
-}\r
-\r
+//=========================================================================
+// Name:          AudioOptsDialog.cpp
+// Purpose:       Implements simple wxWidgets application with GUI
+//                created using wxFormBuilder.
+// Author:
+// Created:
+// Copyright:
+// License:       wxWidgets license (www.wxwidgets.org)
+//
+// Notes:         Note that all GUI creation code is implemented in
+//                gui.cpp source file which is generated by wxFormBuilder.
+//=========================================================================
+#include "fdmdv2_main.h"
+#include "dlg_audiooptions.h"
+
+void AudioOptsDialog::Pa_Init(void)
+{
+    m_isPaInitialized = false;
+
+    if((pa_err = Pa_Initialize()) == paNoError)
+    {
+        m_isPaInitialized = true;
+    }
+    else
+    {
+        wxMessageBox(wxT("Port Audio failed to initialize"), wxT("Pa_Initialize"), wxOK);
+        return;
+    }
+}
+
+
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
+// AudioOptsDialog()
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
+AudioOptsDialog::AudioOptsDialog(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxDialog(parent, id, title, pos, size, style)
+{
+    this->SetSizeHints(wxSize(800, 400), wxDefaultSize);
+
+    Pa_Init();
+
+    wxBoxSizer* mainSizer;
+    mainSizer = new wxBoxSizer(wxVERTICAL);
+    m_panel1 = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
+    wxBoxSizer* bSizer4;
+    bSizer4 = new wxBoxSizer(wxVERTICAL);
+    m_notebook1 = new wxNotebook(m_panel1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_BOTTOM);
+    m_panelRx = new wxPanel(m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
+    wxBoxSizer* bSizer20;
+    bSizer20 = new wxBoxSizer(wxVERTICAL);
+    wxGridSizer* gSizer4;
+    gSizer4 = new wxGridSizer(2, 1, 0, 0);
+    wxStaticBoxSizer* sbSizer2;
+    sbSizer2 = new wxStaticBoxSizer(new wxStaticBox(m_panelRx, wxID_ANY, _("From Radio")), wxVERTICAL);
+    m_listCtrlRxInDevices = new wxListCtrl(m_panelRx, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_HRULES|wxLC_REPORT|wxLC_VRULES);
+    sbSizer2->Add(m_listCtrlRxInDevices, 1, wxALL|wxEXPAND, 1);
+    wxBoxSizer* bSizer811;
+    bSizer811 = new wxBoxSizer(wxHORIZONTAL);
+    m_staticText51 = new wxStaticText(m_panelRx, wxID_ANY, _("Device:"), wxDefaultPosition, wxDefaultSize, 0);
+    m_staticText51->Wrap(-1);
+    bSizer811->Add(m_staticText51, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5);
+    m_textCtrlRxIn = new wxTextCtrl(m_panelRx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
+    bSizer811->Add(m_textCtrlRxIn, 1, wxALIGN_CENTER_VERTICAL|wxALL, 1);
+    m_staticText6 = new wxStaticText(m_panelRx, wxID_ANY, _("Sample Rate:"), wxDefaultPosition, wxDefaultSize, 0);
+    m_staticText6->Wrap(-1);
+    bSizer811->Add(m_staticText6, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5);
+    m_cbSampleRateRxIn = new wxComboBox(m_panelRx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN);
+    bSizer811->Add(m_cbSampleRateRxIn, 0, wxALL, 1);
+    sbSizer2->Add(bSizer811, 0, wxEXPAND, 5);
+    gSizer4->Add(sbSizer2, 1, wxEXPAND, 5);
+    wxStaticBoxSizer* sbSizer3;
+    sbSizer3 = new wxStaticBoxSizer(new wxStaticBox(m_panelRx, wxID_ANY, _("To Speaker/Headphones")), wxVERTICAL);
+    m_listCtrlRxOutDevices = new wxListCtrl(m_panelRx, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_HRULES|wxLC_REPORT|wxLC_VRULES);
+    sbSizer3->Add(m_listCtrlRxOutDevices, 1, wxALL|wxEXPAND, 1);
+    wxBoxSizer* bSizer81;
+    bSizer81 = new wxBoxSizer(wxHORIZONTAL);
+    m_staticText9 = new wxStaticText(m_panelRx, wxID_ANY, _("Device:"), wxDefaultPosition, wxDefaultSize, 0);
+    m_staticText9->Wrap(-1);
+    bSizer81->Add(m_staticText9, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+    m_textCtrlRxOut = new wxTextCtrl(m_panelRx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
+    bSizer81->Add(m_textCtrlRxOut, 1, wxALIGN_CENTER_VERTICAL|wxALL, 1);
+    m_staticText10 = new wxStaticText(m_panelRx, wxID_ANY, _("Sample Rate:"), wxDefaultPosition, wxDefaultSize, 0);
+    m_staticText10->Wrap(-1);
+    bSizer81->Add(m_staticText10, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5);
+    m_cbSampleRateRxOut = new wxComboBox(m_panelRx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN);
+    bSizer81->Add(m_cbSampleRateRxOut, 0, wxALIGN_CENTER_VERTICAL|wxALL, 1);
+    sbSizer3->Add(bSizer81, 0, wxEXPAND, 2);
+    gSizer4->Add(sbSizer3, 1, wxEXPAND, 2);
+    bSizer20->Add(gSizer4, 1, wxEXPAND, 1);
+    m_panelRx->SetSizer(bSizer20);
+    m_panelRx->Layout();
+    bSizer20->Fit(m_panelRx);
+    m_notebook1->AddPage(m_panelRx, _("Receive"), true);
+    m_panelTx = new wxPanel(m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
+    wxBoxSizer* bSizer18;
+    bSizer18 = new wxBoxSizer(wxVERTICAL);
+    wxGridSizer* gSizer2;
+    gSizer2 = new wxGridSizer(2, 1, 0, 0);
+    wxStaticBoxSizer* sbSizer22;
+    sbSizer22 = new wxStaticBoxSizer(new wxStaticBox(m_panelTx, wxID_ANY, _("From Microphone")), wxVERTICAL);
+    m_listCtrlTxInDevices = new wxListCtrl(m_panelTx, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_HRULES|wxLC_REPORT|wxLC_VRULES);
+    sbSizer22->Add(m_listCtrlTxInDevices, 1, wxALL|wxEXPAND, 1);
+    wxBoxSizer* bSizer83;
+    bSizer83 = new wxBoxSizer(wxHORIZONTAL);
+    m_staticText12 = new wxStaticText(m_panelTx, wxID_ANY, _("Device:"), wxDefaultPosition, wxDefaultSize, 0);
+    m_staticText12->Wrap(-1);
+    bSizer83->Add(m_staticText12, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5);
+    m_textCtrlTxIn = new wxTextCtrl(m_panelTx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
+    bSizer83->Add(m_textCtrlTxIn, 1, wxALIGN_CENTER_VERTICAL|wxALL, 1);
+    m_staticText11 = new wxStaticText(m_panelTx, wxID_ANY, _("Sample Rate:"), wxDefaultPosition, wxDefaultSize, 0);
+    m_staticText11->Wrap(-1);
+    bSizer83->Add(m_staticText11, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5);
+    m_cbSampleRateTxIn = new wxComboBox(m_panelTx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN);
+    bSizer83->Add(m_cbSampleRateTxIn, 0, wxALL, 1);
+    sbSizer22->Add(bSizer83, 0, wxEXPAND, 2);
+    gSizer2->Add(sbSizer22, 1, wxEXPAND, 5);
+    wxStaticBoxSizer* sbSizer21;
+    sbSizer21 = new wxStaticBoxSizer(new wxStaticBox(m_panelTx, wxID_ANY, _("To Radio")), wxVERTICAL);
+    m_listCtrlTxOutDevices = new wxListCtrl(m_panelTx, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_HRULES|wxLC_REPORT|wxLC_VRULES);
+    sbSizer21->Add(m_listCtrlTxOutDevices, 1, wxALL|wxEXPAND, 2);
+    wxBoxSizer* bSizer82;
+    bSizer82 = new wxBoxSizer(wxHORIZONTAL);
+    m_staticText81 = new wxStaticText(m_panelTx, wxID_ANY, _("Device:"), wxDefaultPosition, wxDefaultSize, 0);
+    m_staticText81->Wrap(-1);
+    bSizer82->Add(m_staticText81, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+    m_textCtrlTxOut = new wxTextCtrl(m_panelTx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
+    bSizer82->Add(m_textCtrlTxOut, 1, wxALIGN_CENTER_VERTICAL|wxALL, 1);
+    m_staticText71 = new wxStaticText(m_panelTx, wxID_ANY, _("Sample Rate:"), wxDefaultPosition, wxDefaultSize, 0);
+    m_staticText71->Wrap(-1);
+    bSizer82->Add(m_staticText71, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5);
+    m_cbSampleRateTxOut = new wxComboBox(m_panelTx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN);
+    bSizer82->Add(m_cbSampleRateTxOut, 0, wxALL, 1);
+    sbSizer21->Add(bSizer82, 0, wxEXPAND, 2);
+    gSizer2->Add(sbSizer21, 1, wxEXPAND, 5);
+    bSizer18->Add(gSizer2, 1, wxEXPAND, 1);
+    m_panelTx->SetSizer(bSizer18);
+    m_panelTx->Layout();
+    bSizer18->Fit(m_panelTx);
+    m_notebook1->AddPage(m_panelTx, _("Transmit"), false);
+    m_panelAPI = new wxPanel(m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
+    wxBoxSizer* bSizer12;
+    bSizer12 = new wxBoxSizer(wxHORIZONTAL);
+    wxGridSizer* gSizer31;
+    gSizer31 = new wxGridSizer(2, 1, 0, 0);
+    wxStaticBoxSizer* sbSizer1;
+    sbSizer1 = new wxStaticBoxSizer(new wxStaticBox(m_panelAPI, wxID_ANY, _("PortAudio")), wxVERTICAL);
+    wxGridSizer* gSizer3;
+    gSizer3 = new wxGridSizer(4, 2, 0, 0);
+    m_staticText7 = new wxStaticText(m_panelAPI, wxID_ANY, _("PortAudio Version String:"), wxDefaultPosition, wxDefaultSize, 0);
+    m_staticText7->Wrap(-1);
+    gSizer3->Add(m_staticText7, 0, wxALIGN_RIGHT|wxALL|wxALIGN_CENTER_VERTICAL, 1);
+    wxBoxSizer* bSizer151;
+    bSizer151 = new wxBoxSizer(wxVERTICAL);
+    m_textStringVer = new wxTextCtrl(m_panelAPI, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY);
+    bSizer151->Add(m_textStringVer, 0, wxALL|wxEXPAND, 1);
+    gSizer3->Add(bSizer151, 1, wxEXPAND, 2);
+    m_staticText8 = new wxStaticText(m_panelAPI, wxID_ANY, _("PortAudio Int Version:"), wxDefaultPosition, wxDefaultSize, 0);
+    m_staticText8->Wrap(-1);
+    gSizer3->Add(m_staticText8, 0, wxALIGN_RIGHT|wxALL|wxALIGN_CENTER_VERTICAL, 1);
+    wxBoxSizer* bSizer13;
+    bSizer13 = new wxBoxSizer(wxVERTICAL);
+    m_textIntVer = new wxTextCtrl(m_panelAPI, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY);
+    bSizer13->Add(m_textIntVer, 0, wxALL|wxALIGN_CENTER_VERTICAL, 1);
+    gSizer3->Add(bSizer13, 1, wxEXPAND, 5);
+    m_staticText5 = new wxStaticText(m_panelAPI, wxID_ANY, _("Device Count:"), wxDefaultPosition, wxDefaultSize, 0);
+    m_staticText5->Wrap(-1);
+    gSizer3->Add(m_staticText5, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 1);
+    wxBoxSizer* bSizer14;
+    bSizer14 = new wxBoxSizer(wxVERTICAL);
+    m_textCDevCount = new wxTextCtrl(m_panelAPI, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(45,-1), wxTE_READONLY);
+    m_textCDevCount->SetMaxSize(wxSize(45,-1));
+    bSizer14->Add(m_textCDevCount, 0, wxALIGN_CENTER_VERTICAL|wxALL, 1);
+    gSizer3->Add(bSizer14, 1, wxEXPAND, 5);
+    m_staticText4 = new wxStaticText(m_panelAPI, wxID_ANY, _("API Count:"), wxDefaultPosition, wxDefaultSize, 0);
+    m_staticText4->Wrap(-1);
+    gSizer3->Add(m_staticText4, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 1);
+    wxBoxSizer* bSizer15;
+    bSizer15 = new wxBoxSizer(wxVERTICAL);
+    m_textAPICount = new wxTextCtrl(m_panelAPI, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(45,-1), wxTE_READONLY);
+    m_textAPICount->SetMaxSize(wxSize(45,-1));
+    bSizer15->Add(m_textAPICount, 0, wxALIGN_CENTER_VERTICAL|wxALL, 1);
+    gSizer3->Add(bSizer15, 1, wxEXPAND, 5);
+    sbSizer1->Add(gSizer3, 1, wxEXPAND, 2);
+    gSizer31->Add(sbSizer1, 1, wxEXPAND, 2);
+    wxStaticBoxSizer* sbSizer6;
+    sbSizer6 = new wxStaticBoxSizer(new wxStaticBox(m_panelAPI, wxID_ANY, _("Other")), wxVERTICAL);
+    gSizer31->Add(sbSizer6, 1, wxEXPAND, 5);
+    bSizer12->Add(gSizer31, 1, wxEXPAND, 5);
+    m_panelAPI->SetSizer(bSizer12);
+    m_panelAPI->Layout();
+    bSizer12->Fit(m_panelAPI);
+    m_notebook1->AddPage(m_panelAPI, _("API Info"), false);
+    bSizer4->Add(m_notebook1, 1, wxEXPAND | wxALL, 0);
+    m_panel1->SetSizer(bSizer4);
+    m_panel1->Layout();
+    bSizer4->Fit(m_panel1);
+    mainSizer->Add(m_panel1, 1, wxEXPAND | wxALL, 1);
+    wxBoxSizer* bSizer6;
+    bSizer6 = new wxBoxSizer(wxHORIZONTAL);
+    m_btnRefresh = new wxButton(this, wxID_ANY, _("Refresh"), wxDefaultPosition, wxDefaultSize, 0);
+    bSizer6->Add(m_btnRefresh, 0, wxALIGN_CENTER|wxALL, 2);
+    m_sdbSizer1 = new wxStdDialogButtonSizer();
+    m_sdbSizer1OK = new wxButton(this, wxID_OK);
+    m_sdbSizer1->AddButton(m_sdbSizer1OK);
+    m_sdbSizer1Apply = new wxButton(this, wxID_APPLY);
+    m_sdbSizer1->AddButton(m_sdbSizer1Apply);
+    m_sdbSizer1Cancel = new wxButton(this, wxID_CANCEL);
+    m_sdbSizer1->AddButton(m_sdbSizer1Cancel);
+    m_sdbSizer1->Realize();
+    bSizer6->Add(m_sdbSizer1, 1, wxALIGN_CENTER_VERTICAL, 2);
+    mainSizer->Add(bSizer6, 0, wxEXPAND, 2);
+    this->SetSizer(mainSizer);
+    this->Layout();
+    this->Centre(wxBOTH);
+//    this->Centre(wxBOTH);
+
+    m_notebook1->SetSelection(0);
+
+    showAPIInfo();
+    m_RxInDevices.m_listDevices   = m_listCtrlRxInDevices;
+    m_RxInDevices.direction       = AUDIO_IN;
+    m_RxInDevices.m_textDevice    = m_textCtrlRxIn;
+    m_RxInDevices.m_cbSampleRate  = m_cbSampleRateRxIn;
+
+    m_RxOutDevices.m_listDevices  = m_listCtrlRxOutDevices;
+    m_RxOutDevices.direction      = AUDIO_OUT;
+    m_RxOutDevices.m_textDevice   = m_textCtrlRxOut;
+    m_RxOutDevices.m_cbSampleRate = m_cbSampleRateRxOut;
+
+    m_TxInDevices.m_listDevices   = m_listCtrlTxInDevices;
+    m_TxInDevices.direction       = AUDIO_IN;
+    m_TxInDevices.m_textDevice    = m_textCtrlTxIn;
+    m_TxInDevices.m_cbSampleRate  = m_cbSampleRateTxIn;
+
+    m_TxOutDevices.m_listDevices  = m_listCtrlTxOutDevices;
+    m_TxOutDevices.direction      = AUDIO_OUT;
+    m_TxOutDevices.m_textDevice   = m_textCtrlTxOut;
+    m_TxOutDevices.m_cbSampleRate = m_cbSampleRateTxOut;
+
+    populateParams(m_RxInDevices);
+    populateParams(m_RxOutDevices);
+    populateParams(m_TxInDevices);
+    populateParams(m_TxOutDevices);
+
+    m_listCtrlRxInDevices->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( AudioOptsDialog::OnRxInDeviceSelect ), NULL, this );
+    m_listCtrlRxOutDevices->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( AudioOptsDialog::OnRxOutDeviceSelect ), NULL, this );
+    m_listCtrlTxInDevices->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( AudioOptsDialog::OnTxInDeviceSelect ), NULL, this );
+    m_listCtrlTxOutDevices->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( AudioOptsDialog::OnTxOutDeviceSelect ), NULL, this );
+    m_btnRefresh->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AudioOptsDialog::OnRefreshClick ), NULL, this );
+    m_sdbSizer1Apply->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AudioOptsDialog::OnApplyAudioParameters ), NULL, this );
+    m_sdbSizer1Cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AudioOptsDialog::OnCancelAudioParameters ), NULL, this );
+    m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AudioOptsDialog::OnOkAudioParameters ), NULL, this );
+/*
+        void OnClose( wxCloseEvent& event ) { event.Skip(); }
+        void OnHibernate( wxActivateEvent& event ) { event.Skip(); }
+        void OnIconize( wxIconizeEvent& event ) { event.Skip(); }
+        void OnInitDialog( wxInitDialogEvent& event ) { event.Skip(); }
+*/
+//    this->Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(AudioOptsDialog::OnClose));
+    this->Connect(wxEVT_HIBERNATE, wxActivateEventHandler(AudioOptsDialog::OnHibernate));
+    this->Connect(wxEVT_ICONIZE, wxIconizeEventHandler(AudioOptsDialog::OnIconize));
+    this->Connect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(AudioOptsDialog::OnInitDialog));
+}
+
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
+// ~AudioOptsDialog()
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
+AudioOptsDialog::~AudioOptsDialog()
+{
+    Pa_Terminate();
+
+    // Disconnect Events
+    this->Disconnect(wxEVT_HIBERNATE, wxActivateEventHandler(AudioOptsDialog::OnHibernate));
+    this->Disconnect(wxEVT_ICONIZE, wxIconizeEventHandler(AudioOptsDialog::OnIconize));
+    this->Disconnect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(AudioOptsDialog::OnInitDialog));
+
+    m_listCtrlRxInDevices->Disconnect(wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(AudioOptsDialog::OnRxInDeviceSelect), NULL, this);
+    m_listCtrlRxOutDevices->Disconnect(wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(AudioOptsDialog::OnRxOutDeviceSelect), NULL, this);
+    m_listCtrlTxInDevices->Disconnect(wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(AudioOptsDialog::OnTxInDeviceSelect), NULL, this);
+    m_listCtrlTxOutDevices->Disconnect(wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(AudioOptsDialog::OnTxOutDeviceSelect), NULL, this);
+    m_btnRefresh->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(AudioOptsDialog::OnRefreshClick), NULL, this);
+    m_sdbSizer1Apply->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(AudioOptsDialog::OnApplyAudioParameters), NULL, this);
+    m_sdbSizer1Cancel->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(AudioOptsDialog::OnCancelAudioParameters), NULL, this);
+    m_sdbSizer1OK->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(AudioOptsDialog::OnOkAudioParameters), NULL, this);
+
+}
+
 //-------------------------------------------------------------------------
 // OnInitDialog()
 //-------------------------------------------------------------------------
 void AudioOptsDialog::OnInitDialog( wxInitDialogEvent& event )
 {
     ExchangeData(EXCHANGE_DATA_IN);
-    //populateAudioInfo();
 }
 
+// helper function to look up name of devNum, and if it exists write
+// name to textCtrl.  Used to trap dissapearing devices.
+
+int AudioOptsDialog::setTextCtrlIfDevNumValid(wxTextCtrl *textCtrl, wxListCtrl *listCtrl, int devNum)
+{
+    if (devNum > listCtrl->GetItemCount()) {
+        textCtrl->SetValue("none");
+        return -1;
+    }
+    textCtrl->SetValue(listCtrl->GetItemText(devNum, 0));
+    return devNum;
+}
+
+
 //-------------------------------------------------------------------------
 // ExchangeData()
 //-------------------------------------------------------------------------
-void AudioOptsDialog::ExchangeData(int inout)
+int AudioOptsDialog::ExchangeData(int inout)
 {
-    wxConfigBase *pConfig = wxConfigBase::Get();
     if(inout == EXCHANGE_DATA_IN)
     {
-        m_textCtrlRxIn->SetValue(wxGetApp().m_strRxInAudio);
-        m_textCtrlRxOut->SetValue(wxGetApp().m_strRxOutAudio);
-        m_textCtrlTxIn->SetValue(wxGetApp().m_textVoiceInput);
-        m_textCtrlTxOut->SetValue(wxGetApp().m_textVoiceOutput);
+        // Map sound card device numbers to tx/rx device numbers depending
+        // on number of sound cards in use
+
+        printf("EXCHANGE_DATA_IN:\n");
+        printf("  g_nSoundCards: %d\n", g_nSoundCards);
+        printf("  g_soundCard1InDeviceNum: %d\n", g_soundCard1InDeviceNum);
+        printf("  g_soundCard1OutDeviceNum: %d\n", g_soundCard1OutDeviceNum);
+        printf("  g_soundCard1SampleRate: %d\n", g_soundCard1SampleRate);
+        printf("  g_soundCard2InDeviceNum: %d\n", g_soundCard2InDeviceNum);
+        printf("  g_soundCard2OutDeviceNum: %d\n", g_soundCard2OutDeviceNum);
+        printf("  g_soundCard2SampleRate: %d\n", g_soundCard2SampleRate);
+
+        if (g_nSoundCards == 0) {
+            m_textCtrlRxIn ->SetValue("none"); rxInAudioDeviceNum  = -1;
+            m_textCtrlRxOut->SetValue("none"); rxOutAudioDeviceNum = -1;
+            m_textCtrlTxIn ->SetValue("none"); txInAudioDeviceNum  = -1;
+            m_textCtrlTxOut->SetValue("none"); txOutAudioDeviceNum = -1;           
+        }
+
+        if (g_nSoundCards == 1) {
+            rxInAudioDeviceNum  = setTextCtrlIfDevNumValid(m_textCtrlRxIn, 
+                                                           m_listCtrlRxInDevices, 
+                                                           g_soundCard1InDeviceNum);
+
+            rxOutAudioDeviceNum = setTextCtrlIfDevNumValid(m_textCtrlRxOut, 
+                                                           m_listCtrlRxOutDevices, 
+                                                           g_soundCard1OutDeviceNum);
+
+            if ((rxInAudioDeviceNum != -1) && (rxInAudioDeviceNum != -1)) {
+                m_cbSampleRateRxIn->SetValue(wxString::Format(wxT("%i"),g_soundCard1SampleRate));
+                m_cbSampleRateRxOut->SetValue(wxString::Format(wxT("%i"),g_soundCard1SampleRate));
+            }
+
+            m_textCtrlTxIn ->SetValue("none"); txInAudioDeviceNum  = -1;
+            m_textCtrlTxOut->SetValue("none"); txOutAudioDeviceNum = -1;           
+        }
+
+        if (g_nSoundCards == 2) {
+            rxInAudioDeviceNum  = setTextCtrlIfDevNumValid(m_textCtrlRxIn, 
+                                                           m_listCtrlRxInDevices, 
+                                                           g_soundCard1InDeviceNum);
+
+            rxOutAudioDeviceNum = setTextCtrlIfDevNumValid(m_textCtrlRxOut, 
+                                                           m_listCtrlRxOutDevices, 
+                                                           g_soundCard2OutDeviceNum);
+
+            txInAudioDeviceNum  = setTextCtrlIfDevNumValid(m_textCtrlTxIn, 
+                                                           m_listCtrlTxInDevices, 
+                                                           g_soundCard2InDeviceNum);
+
+            txOutAudioDeviceNum = setTextCtrlIfDevNumValid(m_textCtrlTxOut, 
+                                                           m_listCtrlTxOutDevices, 
+                                                           g_soundCard1OutDeviceNum);
+
+            if ((rxInAudioDeviceNum != -1) && (txOutAudioDeviceNum != -1)) {
+                m_cbSampleRateRxIn->SetValue(wxString::Format(wxT("%i"),g_soundCard1SampleRate));
+                m_cbSampleRateTxOut->SetValue(wxString::Format(wxT("%i"),g_soundCard1SampleRate));
+            }
+
+            if ((txInAudioDeviceNum != -1) && (rxOutAudioDeviceNum != -1)) {
+                m_cbSampleRateTxIn->SetValue(wxString::Format(wxT("%i"),g_soundCard2SampleRate));
+                m_cbSampleRateRxOut->SetValue(wxString::Format(wxT("%i"),g_soundCard2SampleRate));
+            }
+        }
+        printf("  rxInAudioDeviceNum: %d\n  rxOutAudioDeviceNum: %d\n  txInAudioDeviceNum: %d\n  txOutAudioDeviceNum: %d\n",
+               rxInAudioDeviceNum, rxOutAudioDeviceNum, txInAudioDeviceNum, txOutAudioDeviceNum);
     }
+
     if(inout == EXCHANGE_DATA_OUT)
     {
-        wxGetApp().m_strRxInAudio    = m_textCtrlRxIn->GetValue();
-        wxGetApp().m_strRxOutAudio   = m_textCtrlRxOut->GetValue();
-        wxGetApp().m_textVoiceInput  = m_textCtrlTxIn->GetValue();
-        wxGetApp().m_textVoiceOutput = m_textCtrlTxOut->GetValue();
-
-        pConfig->Write(wxT("/Audio/RxIn"),          wxGetApp().m_strRxInAudio);
-        pConfig->Write(wxT("/Audio/RxOut"),         wxGetApp().m_strRxOutAudio);
-        pConfig->Write(wxT("/Audio/TxIn"),          wxGetApp().m_textVoiceInput);
-        pConfig->Write(wxT("/Audio/TxOut"),         wxGetApp().m_textVoiceOutput);
-        pConfig->Write(wxT("/Audio/SampleRate"),    wxGetApp().m_strSampleRate);
+        int valid_one_card_config = 0;
+        int valid_two_card_config = 0;
+        wxString sampleRate1, sampleRate2;
+
+        printf("EXCHANGE_DATA_OUT:\n");
+        printf("  rxInAudioDeviceNum: %d\n  rxOutAudioDeviceNum: %d\n  txInAudioDeviceNum: %d\n  txOutAudioDeviceNum: %d\n",
+               rxInAudioDeviceNum, rxOutAudioDeviceNum, txInAudioDeviceNum, txOutAudioDeviceNum);
+
+        // ---------------------------------------------------------------
+        // check we have a valid 1 or 2 sound card configuration
+        // ---------------------------------------------------------------
+
+        // one sound card config, tx device numbers should be set to -1 
+
+        if ((rxInAudioDeviceNum != -1) && (rxOutAudioDeviceNum != -1) &&
+            (txInAudioDeviceNum == -1) && (txOutAudioDeviceNum == -1)) {
+            valid_one_card_config = 1; 
+
+            // in and out sample rate must be the same, as there is one callback
+            
+            sampleRate1 = m_cbSampleRateRxIn->GetValue();
+            if (!sampleRate1.IsSameAs(m_cbSampleRateRxOut->GetValue())) {
+                wxMessageBox(wxT("With a single sound card the Sample Rate of "
+                                 "From Radio and To Speaker/Headphones must be the same."), wxT(""), wxOK);
+                return -1;
+            }
+        }
+
+        // two card configuration
+
+        if ((rxInAudioDeviceNum != -1) && (rxOutAudioDeviceNum != -1) &&
+            (txInAudioDeviceNum != -1) && (txOutAudioDeviceNum != -1)) {
+
+            valid_two_card_config = 1; 
+
+            // Check we haven't doubled up on sound devices
+
+            if (rxInAudioDeviceNum == txInAudioDeviceNum) {
+                wxMessageBox(wxT("You must use different devices for From Radio and From Microphone"), wxT(""), wxOK);
+                return -1;
+            }
+
+            if (rxOutAudioDeviceNum == txOutAudioDeviceNum) {
+                wxMessageBox(wxT("You must use different devices for To Radio and To Speaker/Headphones"), wxT(""), wxOK);
+                return -1;
+            }
+
+            // Check sample rates for callback 1 devices are the same,
+            // as input and output are handled synchronously by one
+            // portaudio callback
+            
+            sampleRate1 = m_cbSampleRateRxIn->GetValue();
+            if (!sampleRate1.IsSameAs(m_cbSampleRateTxOut->GetValue())) {
+                wxMessageBox(wxT("With two sound cards the Sample Rate "
+                                 "of From Radio and To Radio must be the same."), wxT(""), wxOK);
+                return -1;
+            }
+            // check sample rate for callback 2 devices is the same
+
+            sampleRate2 = m_cbSampleRateTxIn->GetValue();
+            if (!sampleRate2.IsSameAs(m_cbSampleRateRxOut->GetValue())) {
+                wxMessageBox(wxT("With two sound cards the Sample Rate of "
+                                 "From Microphone and To Speaker/Headphones must be the same."), wxT(""), wxOK);
+                return -1;
+            }
+        }
+
+        printf("  valid_one_card_config: %d  valid_two_card_config: %d\n", valid_one_card_config, valid_two_card_config);
+
+        if (!valid_one_card_config && !valid_two_card_config) {
+            wxMessageBox(wxT("Invalid one or two sound card configuration"), wxT(""), wxOK);
+            return -1;
+        }
+
+        // ---------------------------------------------------------------
+        // Map Rx/TX device numbers to sound card device numbers used
+        // in callbacks. Portaudio uses one callback per sound card so
+        // we have to be soundcard oriented at run time rather than
+        // Tx/Rx oriented as in this dialog.
+        // ---------------------------------------------------------------
+
+        g_nSoundCards = 0;
+        g_soundCard1InDeviceNum = g_soundCard1OutDeviceNum = g_soundCard2InDeviceNum = g_soundCard2OutDeviceNum = -1;
+
+        if (valid_one_card_config) {
+
+            // Only callback 1 used
+
+            g_nSoundCards = 1;
+            g_soundCard1InDeviceNum  = rxInAudioDeviceNum;
+            g_soundCard1OutDeviceNum = rxOutAudioDeviceNum;
+            g_soundCard1SampleRate = wxAtoi(sampleRate1);
+        }
+
+        if (valid_two_card_config) {
+            g_nSoundCards = 2;
+            g_soundCard1InDeviceNum  = rxInAudioDeviceNum;
+            g_soundCard1OutDeviceNum = txOutAudioDeviceNum;
+            g_soundCard1SampleRate   = wxAtoi(sampleRate1);
+            g_soundCard2InDeviceNum  = txInAudioDeviceNum;
+            g_soundCard2OutDeviceNum = rxOutAudioDeviceNum;
+            g_soundCard2SampleRate   = wxAtoi(sampleRate2);
+        }
+
+        printf("  g_nSoundCards: %d\n", g_nSoundCards);
+        printf("  g_soundCard1InDeviceNum: %d\n", g_soundCard1InDeviceNum);
+        printf("  g_soundCard1OutDeviceNum: %d\n", g_soundCard1OutDeviceNum);
+        printf("  g_soundCard1SampleRate: %d\n", g_soundCard1SampleRate);
+        printf("  g_soundCard2InDeviceNum: %d\n", g_soundCard2InDeviceNum);
+        printf("  g_soundCard2OutDeviceNum: %d\n", g_soundCard2OutDeviceNum);
+        printf("  g_soundCard2SampleRate: %d\n", g_soundCard2SampleRate);
+
+        wxConfigBase *pConfig = wxConfigBase::Get();
+        pConfig->Write(wxT("/Audio/soundCard1InDeviceNum"),       g_soundCard1InDeviceNum);
+        pConfig->Write(wxT("/Audio/soundCard1OutDeviceNum"),      g_soundCard1OutDeviceNum);
+        pConfig->Write(wxT("/Audio/soundCard1SampleRate"),        g_soundCard1SampleRate );
+
+        pConfig->Write(wxT("/Audio/soundCard2InDeviceNum"),       g_soundCard2InDeviceNum);
+        pConfig->Write(wxT("/Audio/soundCard2OutDeviceNum"),      g_soundCard2OutDeviceNum);
+        pConfig->Write(wxT("/Audio/soundCard2SampleRate"),        g_soundCard2SampleRate );
+
         pConfig->Flush();
+        delete wxConfigBase::Set((wxConfigBase *) NULL);
     }
-    delete wxConfigBase::Set((wxConfigBase *) NULL);
+
+    return 0;
 }
-\r
-/*\r
-//-------------------------------------------------------------------------\r
-// OnDeviceSelect()\r
-//-------------------------------------------------------------------------\r
-void AudioOptsDialog::OnDeviceSelect(wxListEvent& event)\r
-{\r
-    wxListItem  info;\r
-    long item;\r
-    item = m_listCtrlRxInDevices->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);\r
-    wxMessageBox(m_listCtrlRxInDevices->GetItemText(item, 2), wxT("Item"), wxOK);\r
-}\r
-*/\r
-\r
-//-------------------------------------------------------------------------\r
-// DisplaySupportedSampleRates()\r
-//-------------------------------------------------------------------------\r
-void AudioOptsDialog::DisplaySupportedSampleRates(AudioInfoDisplay ai)\r
-{\r
-    static double standardSampleRates[] =\r
-    {\r
-        8000.0,     9600.0,\r
-        11025.0,    12000.0,\r
-        16000.0,    22050.0,\r
-        24000.0,    32000.0,\r
-        44100.0,    48000.0,\r
-        88200.0,    96000.0,\r
-        192000.0,   -1          // negative terminated  list\r
-    };\r
-    int i;\r
-    //int printCount;\r
-    //PaError err;\r
-    wxString str;\r
-\r
-    //printCount = 0;\r
-    for(i = 0; standardSampleRates[i] > 0; i++)\r
-    {\r
-        str.Printf("%8.2f", standardSampleRates[i]);\r
-        ai.m_cbSampleRate->AppendString(str);\r
-/*\r
-        err = Pa_IsFormatSupported(ai.inputParameters, outputParameters, standardSampleRates[i]);\r
-        if(err == paFormatIsSupported)\r
-        {\r
-            str.Printf("%8.2f", standardSampleRates[i]);\r
-            ai.m_cbSampleRate->AppendString(str);\r
-        }\r
-\r
-        err = Pa_IsFormatSupported(ai->inputParameters, outputParameters, standardSampleRates[i]);\r
-        if(err == paFormatIsSupported)\r
-        {\r
-            if(printCount == 0)\r
-            {\r
-                printf("\t%8.2f", standardSampleRates[i]);\r
-                printCount = 1;\r
-            }\r
-            else if(printCount == 4)\r
-            {\r
-                printf(",\n\t%8.2f", standardSampleRates[i]);\r
-                printCount = 1;\r
-            }\r
-            else\r
-            {\r
-                printf(", %8.2f", standardSampleRates[i]);\r
-                ++printCount;\r
-            }\r
-        }\r
-*/\r
-    }\r
-    ai.m_cbSampleRate->SetSelection(9);\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// GetAPIInfo()\r
-//-------------------------------------------------------------------------\r
-void AudioOptsDialog::showAPIInfo()\r
-{\r
-    wxString    strval;\r
-    int         apiCount        = 0;\r
-    int         numDevices      = 0;\r
-\r
-    strval = Pa_GetVersionText();\r
-    m_textStringVer->SetValue(strval);\r
-\r
-    numDevices = Pa_GetVersion();\r
-    strval.Printf(wxT("%d"), numDevices);\r
-    m_textIntVer->SetValue(strval);\r
-\r
-    apiCount = Pa_GetHostApiCount();\r
-    strval.Printf(wxT("%d"), apiCount);\r
-    m_textAPICount->SetValue(strval);\r
-\r
-    numDevices = Pa_GetDeviceCount();\r
-    strval.Printf(wxT("%d"), numDevices);\r
-    m_textCDevCount->SetValue(strval);\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// populateParams()\r
-//-------------------------------------------------------------------------\r
-void AudioOptsDialog::populateParams(AudioInfoDisplay ai)\r
-{\r
-    const       PaDeviceInfo *deviceInfo = NULL;\r
-    int         j       = 0;\r
-    wxListCtrl* ctrl    = ai.m_listDevices;\r
-    int         in_out  = ai.direction;\r
-    long        idx;\r
-    bool        defaultDisplayed = false;\r
-    int         numDevices;\r
-    wxListItem  listItem;\r
-    wxString    buf;\r
-    int         devn;\r
-    int         col = 0;\r
-\r
-    numDevices = Pa_GetDeviceCount();\r
-\r
-    if(ctrl->GetColumnCount() > 0)\r
-    {\r
-        ctrl->ClearAll();\r
-    }\r
-    listItem.SetAlign(wxLIST_FORMAT_CENTRE);\r
-    listItem.SetText(wxT("Dflt"));\r
-    idx = ctrl->InsertColumn(col, listItem);\r
-    ctrl->SetColumnWidth(col++, 37);\r
-\r
-    listItem.SetAlign(wxLIST_FORMAT_LEFT);\r
-    listItem.SetText(wxT("Device"));\r
-    idx = ctrl->InsertColumn(col, listItem);\r
-    ctrl->SetColumnWidth(col++, 190);\r
-\r
-    listItem.SetAlign(wxLIST_FORMAT_LEFT);\r
-    listItem.SetText(wxT("API"));\r
-    idx = ctrl->InsertColumn(col, listItem);\r
-    ctrl->SetColumnWidth(col++, 190);\r
-\r
-    if(in_out == AUDIO_IN)\r
-    {\r
-        listItem.SetAlign(wxLIST_FORMAT_CENTRE);\r
-        listItem.SetText(wxT("# Inputs"));\r
-        idx = ctrl->InsertColumn(col, listItem);\r
-        ctrl->SetColumnWidth(col++, 75);\r
-    }\r
-    else if(in_out == AUDIO_OUT)\r
-    {\r
-        listItem.SetAlign(wxLIST_FORMAT_CENTRE);\r
-        listItem.SetText(wxT("# Outputs"));\r
-        idx = ctrl->InsertColumn(col, listItem);\r
-        ctrl->SetColumnWidth(col++, 75);\r
-    }\r
-\r
-    listItem.SetAlign(wxLIST_FORMAT_CENTRE);\r
-    listItem.SetText(wxT("Min Latency"));\r
-    ctrl->InsertColumn(col, listItem);\r
-    ctrl->SetColumnWidth(col++, 100);\r
-\r
-    listItem.SetAlign(wxLIST_FORMAT_CENTRE);\r
-    listItem.SetText(wxT("Max Latency"));\r
-    ctrl->InsertColumn(col, listItem);\r
-    ctrl->SetColumnWidth(col++, 100);\r
-\r
-    for(devn = 0; devn < numDevices; devn++)\r
-    {\r
-        buf.Printf(wxT(""));\r
-        deviceInfo = Pa_GetDeviceInfo(devn);\r
-        if(in_out == AUDIO_IN)\r
-        {\r
-            if(deviceInfo->maxInputChannels > 0)\r
-            {\r
-                col = 0;\r
-                defaultDisplayed = false;\r
-                if(devn == Pa_GetDefaultInputDevice())\r
-                {\r
-                    buf.Printf("->>");\r
-                    defaultDisplayed = true;\r
-                }\r
-                else if(devn == Pa_GetHostApiInfo(deviceInfo->hostApi)->defaultInputDevice)\r
-                {\r
-                    buf.Printf("-->");\r
-                    defaultDisplayed = true;\r
-                }\r
-                else\r
-                {\r
-                    buf.Printf("---");\r
-                    defaultDisplayed = false;\r
-                }\r
-                idx = ctrl->InsertItem(idx, buf);\r
-                col++;\r
-                buf.Printf(wxT("%s"), deviceInfo->name);\r
-                ctrl->SetItem(idx, col++, buf);\r
-                if(defaultDisplayed)\r
-                {\r
-                    ai.m_textDevice->SetValue(buf);\r
-                }\r
-\r
-                buf.Printf(wxT("%s"), Pa_GetHostApiInfo(deviceInfo->hostApi)->name);\r
-                ctrl->SetItem(idx, col++, buf);\r
-\r
-                buf.Printf(wxT("%i"), deviceInfo->maxInputChannels);\r
-                ctrl->SetItem(idx, col++, buf);\r
-\r
-                buf.Printf(wxT("%8.4f"), deviceInfo->defaultLowInputLatency);\r
-                ctrl->SetItem(idx, col++, buf);\r
-\r
-                buf.Printf(wxT("%8.4f"), deviceInfo->defaultHighInputLatency);\r
-                ctrl->SetItem(idx, col++, buf);\r
-            }\r
-        }\r
-        else if(in_out == AUDIO_OUT)\r
-        {\r
-            col = 0;\r
-            if(deviceInfo->maxOutputChannels > 0)\r
-            {\r
-                defaultDisplayed = false;\r
-                if(devn == Pa_GetDefaultOutputDevice())\r
-                {\r
-                    buf.Printf("<<-");\r
-                    defaultDisplayed = true;\r
-                }\r
-                else if(devn == Pa_GetHostApiInfo(deviceInfo->hostApi)->defaultOutputDevice)\r
-                {\r
-                    buf.Printf("<--");\r
-                    defaultDisplayed = true;\r
-                }\r
-                else\r
-                {\r
-                    buf.Printf("---");\r
-                    defaultDisplayed = false;\r
-                }\r
-                idx = ctrl->InsertItem(idx, buf);\r
-                col++;\r
-                buf.Printf(wxT("%s"), deviceInfo->name);\r
-                ctrl->SetItem(idx, col++, buf);\r
-                if(defaultDisplayed)\r
-                {\r
-                    ai.m_textDevice->SetValue(buf);\r
-                }\r
-\r
-                buf.Printf(wxT("%s"), Pa_GetHostApiInfo(deviceInfo->hostApi)->name);\r
-                ctrl->SetItem(idx, col++, buf);\r
-\r
-                buf.Printf(wxT("%i"), deviceInfo->maxOutputChannels);\r
-                ctrl->SetItem(idx, col++, buf);\r
-\r
-                buf.Printf(wxT("%8.4f"), deviceInfo->defaultLowOutputLatency);\r
-                ctrl->SetItem(idx, col++, buf);\r
-\r
-                buf.Printf(wxT("%8.4f"), deviceInfo->defaultHighOutputLatency);\r
-                ctrl->SetItem(idx, col++, buf);\r
-            }\r
-        }\r
-        j++;\r
-    }\r
-    DisplaySupportedSampleRates(ai);\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// OnRxInDeviceSelect()\r
-//-------------------------------------------------------------------------\r
-void AudioOptsDialog::OnRxInDeviceSelect(wxListEvent& evt)\r
-{\r
-    wxString str;\r
-    int index = evt.GetIndex();\r
-\r
-    str = m_listCtrlRxInDevices->GetItemText(index, 1);\r
-    m_textCtrlRxIn->SetValue(str);\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// OnRxOutDeviceSelect()\r
-//-------------------------------------------------------------------------\r
-void AudioOptsDialog::OnRxOutDeviceSelect(wxListEvent& evt)\r
-{\r
-    wxString str;\r
-    int index = evt.GetIndex();\r
-\r
-    str = m_listCtrlRxOutDevices->GetItemText(index, 1);\r
-    m_textCtrlRxOut->SetValue(str);\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// OnTxInDeviceSelect()\r
-//-------------------------------------------------------------------------\r
-void AudioOptsDialog::OnTxInDeviceSelect(wxListEvent& evt)\r
-{\r
-    wxString str;\r
-    int index = evt.GetIndex();\r
-\r
-    str = m_listCtrlTxInDevices->GetItemText(index, 1);\r
-    m_textCtrlTxIn->SetValue(str);\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// OnTxOutDeviceSelect()\r
-//-------------------------------------------------------------------------\r
-void AudioOptsDialog::OnTxOutDeviceSelect(wxListEvent& evt)\r
-{\r
-    wxString str;\r
-    int index = evt.GetIndex();\r
-\r
-    str = m_listCtrlTxOutDevices->GetItemText(index, 1);\r
-    m_textCtrlTxOut->SetValue(str);\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// OnRefreshClick()\r
-//-------------------------------------------------------------------------\r
-void AudioOptsDialog::OnRefreshClick(wxCommandEvent& event)\r
-{\r
-    m_notebook1->SetSelection(0);\r
-    showAPIInfo();\r
-    populateParams(m_RxInDevices);\r
-    populateParams(m_RxOutDevices);\r
-    populateParams(m_TxInDevices);\r
-    populateParams(m_TxOutDevices);\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// OnApplyAudioParameters()\r
-//-------------------------------------------------------------------------\r
-void AudioOptsDialog::OnApplyAudioParameters(wxCommandEvent& event)\r
-{\r
+
+/*
+//-------------------------------------------------------------------------
+// OnDeviceSelect()
+//-------------------------------------------------------------------------
+void AudioOptsDialog::OnDeviceSelect(wxListEvent& event)
+{
+    wxListItem  info;
+    long item;
+    item = m_listCtrlRxInDevices->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+    wxMessageBox(m_listCtrlRxInDevices->GetItemText(item, 2), wxT("Item"), wxOK);
+}
+*/
+
+//-------------------------------------------------------------------------
+// DisplaySupportedSampleRates()
+//-------------------------------------------------------------------------
+void AudioOptsDialog::DisplaySupportedSampleRates(AudioInfoDisplay ai)
+{
+    static double standardSampleRates[] =
+    {
+        8000.0,     9600.0,
+        11025.0,    12000.0,
+        16000.0,    22050.0,
+        24000.0,    32000.0,
+        44100.0,    48000.0,
+        88200.0,    96000.0,
+        192000.0,   -1          // negative terminated  list
+    };
+    int i;
+    wxString str;
+
+    //printCount = 0;
+    for(i = 0; standardSampleRates[i] > 0; i++)
+    {
+        str.Printf("%6.0f", standardSampleRates[i]);
+        ai.m_cbSampleRate->AppendString(str);
+
+    }
+    ai.m_cbSampleRate->SetSelection(9);
+}
+
+//-------------------------------------------------------------------------
+// GetAPIInfo()
+//-------------------------------------------------------------------------
+void AudioOptsDialog::showAPIInfo()
+{
+    wxString    strval;
+    int         apiVersion;
+    int         apiCount        = 0;
+    int         numDevices      = 0;
+
+    strval = Pa_GetVersionText();
+    m_textStringVer->SetValue(strval);
+
+    apiVersion = Pa_GetVersion();
+    strval.Printf(wxT("%d"), apiVersion);
+    m_textIntVer->SetValue(strval);
+
+    apiCount = Pa_GetHostApiCount();
+    strval.Printf(wxT("%d"), apiCount);
+    m_textAPICount->SetValue(strval);
+
+    numDevices = Pa_GetDeviceCount();
+    strval.Printf(wxT("%d"), numDevices);
+    m_textCDevCount->SetValue(strval);
+}
+
+//-------------------------------------------------------------------------
+// populateParams()
+//-------------------------------------------------------------------------
+void AudioOptsDialog::populateParams(AudioInfoDisplay ai)
+{
+    const       PaDeviceInfo *deviceInfo = NULL;
+    int         j       = 0;
+    wxListCtrl* ctrl    = ai.m_listDevices;
+    int         in_out  = ai.direction;
+    long        idx;
+    bool        defaultDisplayed = false;
+    int         numDevices;
+    wxListItem  listItem;
+    wxString    buf;
+    int         devn;
+    int         col = 0;
+
+    numDevices = Pa_GetDeviceCount();
+    printf("numDevices: %d\n", numDevices);
+
+    if(ctrl->GetColumnCount() > 0)
+    {
+        ctrl->ClearAll();
+    }
+
+    #ifdef DFT_COL
+    listItem.SetAlign(wxLIST_FORMAT_CENTRE);
+    listItem.SetText(wxT("Dflt"));
+    idx = ctrl->InsertColumn(col, listItem);
+    ctrl->SetColumnWidth(col++, 37);
+    #endif
+
+    listItem.SetAlign(wxLIST_FORMAT_LEFT);
+    listItem.SetText(wxT("Device"));
+    idx = ctrl->InsertColumn(col, listItem);
+    ctrl->SetColumnWidth(col++, 190);
+
+    listItem.SetAlign(wxLIST_FORMAT_LEFT);
+    listItem.SetText(wxT("API"));
+    idx = ctrl->InsertColumn(col, listItem);
+    ctrl->SetColumnWidth(col++, 190);
+
+    if(in_out == AUDIO_IN)
+    {
+        listItem.SetAlign(wxLIST_FORMAT_CENTRE);
+        listItem.SetText(wxT("Default Sample Rate"));
+        idx = ctrl->InsertColumn(col, listItem);
+        ctrl->SetColumnWidth(col++, 160);
+    }
+    else if(in_out == AUDIO_OUT)
+    {
+        listItem.SetAlign(wxLIST_FORMAT_CENTRE);
+        listItem.SetText(wxT("Default Sample Rate"));
+        idx = ctrl->InsertColumn(col, listItem);
+        ctrl->SetColumnWidth(col++, 160);
+    }
+
+    listItem.SetAlign(wxLIST_FORMAT_CENTRE);
+    listItem.SetText(wxT("Min Latency"));
+    ctrl->InsertColumn(col, listItem);
+    ctrl->SetColumnWidth(col++, 100);
+
+    listItem.SetAlign(wxLIST_FORMAT_CENTRE);
+    listItem.SetText(wxT("Max Latency"));
+    ctrl->InsertColumn(col, listItem);
+    ctrl->SetColumnWidth(col++, 100);
+
+    for(devn = 0; devn < numDevices; devn++)
+    {
+        buf.Printf(wxT(""));
+        deviceInfo = Pa_GetDeviceInfo(devn);
+        if(in_out == AUDIO_IN)
+        {
+            if(deviceInfo->maxInputChannels > 0)
+            {
+                col = 0;
+
+                #ifdef DFT_COL
+                defaultDisplayed = false;
+                if(devn == Pa_GetDefaultInputDevice())
+                {
+                    buf.Printf("->>");
+                    defaultDisplayed = true;
+                }
+                else if(devn == Pa_GetHostApiInfo(deviceInfo->hostApi)->defaultInputDevice)
+                {
+                    buf.Printf("-->");
+                    defaultDisplayed = true;
+                }
+                else
+                {
+                    buf.Printf("---");
+                    defaultDisplayed = false;
+                }
+                idx = ctrl->InsertItem(idx, buf);
+                col++;
+                #endif
+
+                buf.Printf(wxT("%s"), deviceInfo->name);
+                idx = ctrl->InsertItem(ctrl->GetItemCount(), buf);
+                col++;
+                if(defaultDisplayed)
+                {
+                    ai.m_textDevice->SetValue(buf);
+                }
+
+                buf.Printf(wxT("%s"), Pa_GetHostApiInfo(deviceInfo->hostApi)->name);
+                ctrl->SetItem(idx, col++, buf);
+
+                buf.Printf(wxT("%6.0f"), deviceInfo->defaultSampleRate);
+                ctrl->SetItem(idx, col++, buf);
+
+                buf.Printf(wxT("%8.4f"), deviceInfo->defaultLowInputLatency);
+                ctrl->SetItem(idx, col++, buf);
+
+                buf.Printf(wxT("%8.4f"), deviceInfo->defaultHighInputLatency);
+                ctrl->SetItem(idx, col++, buf);
+            }
+        }
+        else if(in_out == AUDIO_OUT)
+        {
+            col = 0;
+            if(deviceInfo->maxOutputChannels > 0)
+            {
+                #ifdef DFT_COL
+                defaultDisplayed = false;
+                if(devn == Pa_GetDefaultOutputDevice())
+                {
+                    buf.Printf("<<-");
+                    defaultDisplayed = true;
+                }
+                else if(devn == Pa_GetHostApiInfo(deviceInfo->hostApi)->defaultOutputDevice)
+                {
+                    buf.Printf("<--");
+                    defaultDisplayed = true;
+                }
+                else
+                {
+                    buf.Printf("---");
+                    defaultDisplayed = false;
+                }
+                #endif
+
+                buf.Printf(wxT("%s"), deviceInfo->name);
+                idx = ctrl->InsertItem(ctrl->GetItemCount(), buf);
+                col++;
+                if(defaultDisplayed)
+                {
+                    ai.m_textDevice->SetValue(buf);
+                }
+
+                buf.Printf(wxT("%s"), Pa_GetHostApiInfo(deviceInfo->hostApi)->name);
+                ctrl->SetItem(idx, col++, buf);
+
+                buf.Printf(wxT("%6.0f"), deviceInfo->defaultSampleRate);
+                ctrl->SetItem(idx, col++, buf);
+
+                buf.Printf(wxT("%8.4f"), deviceInfo->defaultLowOutputLatency);
+                ctrl->SetItem(idx, col++, buf);
+
+                buf.Printf(wxT("%8.4f"), deviceInfo->defaultHighOutputLatency);
+                ctrl->SetItem(idx, col++, buf);
+            }
+        }
+        j++;
+
+    }
+
+    // add "none" option at end
+
+    buf.Printf(wxT("%s"), "none");
+    idx = ctrl->InsertItem(ctrl->GetItemCount(), buf);
+        
+    DisplaySupportedSampleRates(ai);
+}
+
+//-------------------------------------------------------------------------
+// OnRxInDeviceSelect()
+//-------------------------------------------------------------------------
+void AudioOptsDialog::OnRxInDeviceSelect(wxListEvent& evt)
+{
+    wxString dev, sampleRate;
+    int index = evt.GetIndex();
+
+    dev = m_listCtrlRxInDevices->GetItemText(index, 0);
+    m_textCtrlRxIn->SetValue(dev);
+    if (dev.IsSameAs("none"))
+        rxInAudioDeviceNum = -1;
+    else {
+        rxInAudioDeviceNum = index;
+        sampleRate = m_listCtrlRxInDevices->GetItemText(index, 2);
+        m_cbSampleRateRxIn->SetValue(sampleRate);
+    }
+}
+
+//-------------------------------------------------------------------------
+// OnRxOutDeviceSelect()
+//-------------------------------------------------------------------------
+void AudioOptsDialog::OnRxOutDeviceSelect(wxListEvent& evt)
+{
+    wxString dev, sampleRate;
+    int index = evt.GetIndex();
+
+    dev = m_listCtrlRxOutDevices->GetItemText(index, 0);
+    m_textCtrlRxOut->SetValue(dev);
+    if (dev.IsSameAs("none"))
+        rxOutAudioDeviceNum = -1;
+    else {
+        rxOutAudioDeviceNum = index;
+        sampleRate = m_listCtrlRxOutDevices->GetItemText(index, 2);
+        m_cbSampleRateRxOut->SetValue(sampleRate);
+    }
+}
+
+//-------------------------------------------------------------------------
+// OnTxInDeviceSelect()
+//-------------------------------------------------------------------------
+void AudioOptsDialog::OnTxInDeviceSelect(wxListEvent& evt)
+{
+    wxString dev, sampleRate;
+    int index = evt.GetIndex();
+
+    dev = m_listCtrlTxInDevices->GetItemText(index, 0);
+    m_textCtrlTxIn->SetValue(dev);
+    if (dev.IsSameAs("none"))
+        txInAudioDeviceNum = -1;
+    else {
+        txInAudioDeviceNum = index;
+        sampleRate = m_listCtrlTxInDevices->GetItemText(index, 2);
+        m_cbSampleRateTxIn->SetValue(sampleRate);
+    }
+}
+
+//-------------------------------------------------------------------------
+// OnTxOutDeviceSelect()
+//-------------------------------------------------------------------------
+void AudioOptsDialog::OnTxOutDeviceSelect(wxListEvent& evt)
+{
+    wxString dev, sampleRate;
+    int index = evt.GetIndex();
+
+    dev = m_listCtrlTxOutDevices->GetItemText(index, 0);
+    m_textCtrlTxOut->SetValue(dev);
+    if (dev.IsSameAs("none"))
+        txOutAudioDeviceNum = -1;
+    else {
+        txOutAudioDeviceNum = index;
+        sampleRate = m_listCtrlTxOutDevices->GetItemText(index, 2);
+        m_cbSampleRateTxOut->SetValue(sampleRate);
+    }
+}
+
+//-------------------------------------------------------------------------
+// OnRefreshClick()
+//-------------------------------------------------------------------------
+void AudioOptsDialog::OnRefreshClick(wxCommandEvent& event)
+{
+    // restart portaudio, to re-sample available devices
+
+    Pa_Terminate();
+    Pa_Init();
+
+    m_notebook1->SetSelection(0);
+    showAPIInfo();
+    populateParams(m_RxInDevices);
+    populateParams(m_RxOutDevices);
+    populateParams(m_TxInDevices);
+    populateParams(m_TxOutDevices);
+
+    // some devices may have dissapeared, so possibily change sound
+    // card config
+
+    ExchangeData(EXCHANGE_DATA_IN);
+}
+
+//-------------------------------------------------------------------------
+// OnApplyAudioParameters()
+//-------------------------------------------------------------------------
+void AudioOptsDialog::OnApplyAudioParameters(wxCommandEvent& event)
+{
     ExchangeData(EXCHANGE_DATA_OUT);
-    if(m_isPaInitialized)\r
-    {\r
-        if((pa_err = Pa_Terminate()) == paNoError)\r
-        {\r
-            m_isPaInitialized = false;\r
-        }\r
-        else\r
-        {\r
-            wxMessageBox(wxT("Port Audio failed to Terminate"), wxT("Pa_Terminate"), wxOK);\r
-        }\r
-    }\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// OnCancelAudioParameters()\r
-//-------------------------------------------------------------------------\r
-void AudioOptsDialog::OnCancelAudioParameters(wxCommandEvent& event)\r
-{\r
-    if(m_isPaInitialized)\r
-    {\r
-        if((pa_err = Pa_Terminate()) == paNoError)\r
-        {\r
-            m_isPaInitialized = false;\r
-        }\r
-        else\r
-        {\r
-            wxMessageBox(wxT("Port Audio failed to Terminate"), wxT("Pa_Terminate"), wxOK);\r
-        }\r
-    }\r
+    if(m_isPaInitialized)
+    {
+        if((pa_err = Pa_Terminate()) == paNoError)
+        {
+            m_isPaInitialized = false;
+        }
+        else
+        {
+            wxMessageBox(wxT("Port Audio failed to Terminate"), wxT("Pa_Terminate"), wxOK);
+        }
+    }
+}
+
+//-------------------------------------------------------------------------
+// OnCancelAudioParameters()
+//-------------------------------------------------------------------------
+void AudioOptsDialog::OnCancelAudioParameters(wxCommandEvent& event)
+{
+    if(m_isPaInitialized)
+    {
+        if((pa_err = Pa_Terminate()) == paNoError)
+        {
+            m_isPaInitialized = false;
+        }
+        else
+        {
+            wxMessageBox(wxT("Port Audio failed to Terminate"), wxT("Pa_Terminate"), wxOK);
+        }
+    }
     EndModal(wxCANCEL);
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// OnOkAudioParameters()\r
-//-------------------------------------------------------------------------\r
-void AudioOptsDialog::OnOkAudioParameters(wxCommandEvent& event)\r
-{\r
-    ExchangeData(EXCHANGE_DATA_OUT);
-    if(m_isPaInitialized)\r
-    {\r
-        if((pa_err = Pa_Terminate()) == paNoError)\r
-        {\r
-            m_isPaInitialized = false;\r
-        }\r
-        else\r
-        {\r
-            wxMessageBox(wxT("Port Audio failed to Terminate"), wxT("Pa_Terminate"), wxOK);\r
-        }\r
-    }\r
-    EndModal(wxOK);
-}\r
+}
+
+//-------------------------------------------------------------------------
+// OnOkAudioParameters()
+//-------------------------------------------------------------------------
+void AudioOptsDialog::OnOkAudioParameters(wxCommandEvent& event)
+{
+    int status = ExchangeData(EXCHANGE_DATA_OUT);
+
+    // We only accept OK if config sucessful
+
+    printf("status: %d m_isPaInitialized: %d\n", status, m_isPaInitialized);
+    if (status == 0) {
+        if(m_isPaInitialized)
+        {
+            if((pa_err = Pa_Terminate()) == paNoError)
+            {
+                printf("terminated OK\n");
+                m_isPaInitialized = false;
+            }
+            else
+            {
+                wxMessageBox(wxT("Port Audio failed to Terminate"), wxT("Pa_Terminate"), wxOK);
+            }
+        }
+        EndModal(wxOK);
+    }
+
+}
index 0daa8088c01b2db23027114a403d4397a2613282..3fa423d09afbbaf8c7269f68121ba767ff8ebec6 100644 (file)
@@ -1,4 +1,4 @@
-//=========================================================================\r
+//=========================================================================
 // Name:          AudioInfoDisplay.h
 // Purpose:       Declares simple wxWidgets application with GUI
 //                created using wxFormBuilder.
 //
 // Notes:         Note that all GUI creation code is declared in
 //                gui.h source file which is generated by wxFormBuilder.
-//=========================================================================\r
+//=========================================================================
 #ifndef __AudioOptsDialog__
 #define __AudioOptsDialog__
 
 #include "fdmdv2_main.h"
-\r
-#define ID_AUDIO_OPTIONS    1000\r
-#define AUDIO_IN            0\r
-#define AUDIO_OUT           1\r
-\r
-#include "portaudio.h"\r
+
+#define ID_AUDIO_OPTIONS    1000
+#define AUDIO_IN            0
+#define AUDIO_OUT           1
+
+#include "portaudio.h"
 #ifdef WIN32
 #if PA_USE_ASIO
 #include "pa_asio.h"
 #endif
 #endif
 
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=\r
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
 // AudioInfoDisplay
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=\r
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
 class AudioInfoDisplay
-{\r
-    public:\r
-        wxListCtrl*     m_listDevices;\r
-        int             direction;\r
-        wxTextCtrl*     m_textDevice;\r
-        wxComboBox*     m_cbSampleRate;\r
+{
+    public:
+        wxListCtrl*     m_listDevices;
+        int             direction;
+        wxTextCtrl*     m_textDevice;
+        wxComboBox*     m_cbSampleRate;
 };
-\r
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=\r
+
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
 // class AudioOptsDialog
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=\r
-class AudioOptsDialog : public wxDialog\r
-{\r
-    private:\r
-\r
-    protected:\r
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
+class AudioOptsDialog : public wxDialog
+{
+    private:
+
+    protected:
         PaError         pa_err;
-        bool            m_isPaInitialized;\r
-\r
-        //void DisplaySupportedSampleRates(const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters);\r
-        void DisplaySupportedSampleRates(AudioInfoDisplay ai);\r
+        bool            m_isPaInitialized;
+
+        int             rxInAudioDeviceNum;
+        int             rxOutAudioDeviceNum;
+        int             txInAudioDeviceNum;
+        int             txOutAudioDeviceNum;
+
+       //void DisplaySupportedSampleRates(const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters);
+        void DisplaySupportedSampleRates(AudioInfoDisplay ai);
         void populateParams(AudioInfoDisplay);
-        void showAPIInfo();\r
-\r
-        AudioInfoDisplay m_RxInDevices;\r
-        AudioInfoDisplay m_RxOutDevices;\r
-        AudioInfoDisplay m_TxInDevices;\r
-        AudioInfoDisplay m_TxOutDevices;\r
-        wxPanel* m_panel1;\r
-        wxNotebook* m_notebook1;\r
-        wxPanel* m_panelRx;\r
-        wxListCtrl* m_listCtrlRxInDevices;\r
-        wxStaticText* m_staticText51;\r
-        wxTextCtrl* m_textCtrlRxIn;\r
-        wxStaticText* m_staticText6;\r
-        wxComboBox* m_cbSampleRateRxIn;\r
-        wxListCtrl* m_listCtrlRxOutDevices;\r
-        wxStaticText* m_staticText9;\r
-        wxTextCtrl* m_textCtrlRxOut;\r
-        wxStaticText* m_staticText10;\r
-        wxComboBox* m_cbSampleRateRxOut;\r
-        wxPanel* m_panelTx;\r
-        wxListCtrl* m_listCtrlTxInDevices;\r
-        wxStaticText* m_staticText12;\r
-        wxTextCtrl* m_textCtrlTxIn;\r
-        wxStaticText* m_staticText11;\r
-        wxComboBox* m_cbSampleRateTxIn;\r
-        wxListCtrl* m_listCtrlTxOutDevices;\r
-        wxStaticText* m_staticText81;\r
-        wxTextCtrl* m_textCtrlTxOut;\r
-        wxStaticText* m_staticText71;\r
-        wxComboBox* m_cbSampleRateTxOut;\r
-        wxPanel* m_panelAPI;\r
-        wxStaticText* m_staticText7;\r
-        wxTextCtrl* m_textStringVer;\r
-        wxStaticText* m_staticText8;\r
-        wxTextCtrl* m_textIntVer;\r
-        wxStaticText* m_staticText5;\r
-        wxTextCtrl* m_textCDevCount;\r
-        wxStaticText* m_staticText4;\r
-        wxTextCtrl* m_textAPICount;\r
-        wxButton* m_btnRefresh;\r
-        wxStdDialogButtonSizer* m_sdbSizer1;\r
-        wxButton* m_sdbSizer1OK;\r
-        wxButton* m_sdbSizer1Apply;\r
-        wxButton* m_sdbSizer1Cancel;\r
-\r
-        // Virtual event handlers, overide them in your derived class\r
-        //virtual void OnActivateApp( wxActivateEvent& event ) { event.Skip(); }\r
-//        virtual void OnCloseFrame( wxCloseEvent& event ) { event.Skip(); }\r
-        void OnRxInDeviceSelect( wxListEvent& event );\r
-        void OnRxOutDeviceSelect( wxListEvent& event );\r
-        void OnTxInDeviceSelect( wxListEvent& event );\r
-        void OnTxOutDeviceSelect( wxListEvent& event );\r
-        void OnRefreshClick( wxCommandEvent& event );\r
-        void OnApplyAudioParameters( wxCommandEvent& event );\r
-        void OnCancelAudioParameters( wxCommandEvent& event );\r
-        void OnOkAudioParameters( wxCommandEvent& event );\r
-        // Virtual event handlers, overide them in your derived class\r
-        void OnClose( wxCloseEvent& event ) { event.Skip(); }\r
-        void OnHibernate( wxActivateEvent& event ) { event.Skip(); }\r
-        void OnIconize( wxIconizeEvent& event ) { event.Skip(); }\r
-        void OnInitDialog( wxInitDialogEvent& event );\r
-\r
-    public:\r
-\r
-        AudioOptsDialog( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Audio Options"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 300,300 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );\r
-        ~AudioOptsDialog();\r
-        void ExchangeData(int inout);\r
-};\r
+        void showAPIInfo();
+        int setTextCtrlIfDevNumValid(wxTextCtrl *textCtrl, wxListCtrl *listCtrl, int devNum);
+        void Pa_Init(void);
+
+        AudioInfoDisplay m_RxInDevices;
+        AudioInfoDisplay m_RxOutDevices;
+        AudioInfoDisplay m_TxInDevices;
+        AudioInfoDisplay m_TxOutDevices;
+        wxPanel* m_panel1;
+        wxNotebook* m_notebook1;
+        wxPanel* m_panelRx;
+        wxListCtrl* m_listCtrlRxInDevices;
+        wxStaticText* m_staticText51;
+        wxTextCtrl* m_textCtrlRxIn;
+        wxStaticText* m_staticText6;
+        wxComboBox* m_cbSampleRateRxIn;
+        wxListCtrl* m_listCtrlRxOutDevices;
+        wxStaticText* m_staticText9;
+        wxTextCtrl* m_textCtrlRxOut;
+        wxStaticText* m_staticText10;
+        wxComboBox* m_cbSampleRateRxOut;
+        wxPanel* m_panelTx;
+        wxListCtrl* m_listCtrlTxInDevices;
+        wxStaticText* m_staticText12;
+        wxTextCtrl* m_textCtrlTxIn;
+        wxStaticText* m_staticText11;
+        wxComboBox* m_cbSampleRateTxIn;
+        wxListCtrl* m_listCtrlTxOutDevices;
+        wxStaticText* m_staticText81;
+        wxTextCtrl* m_textCtrlTxOut;
+        wxStaticText* m_staticText71;
+        wxComboBox* m_cbSampleRateTxOut;
+        wxPanel* m_panelAPI;
+        wxStaticText* m_staticText7;
+        wxTextCtrl* m_textStringVer;
+        wxStaticText* m_staticText8;
+        wxTextCtrl* m_textIntVer;
+        wxStaticText* m_staticText5;
+        wxTextCtrl* m_textCDevCount;
+        wxStaticText* m_staticText4;
+        wxTextCtrl* m_textAPICount;
+        wxButton* m_btnRefresh;
+        wxStdDialogButtonSizer* m_sdbSizer1;
+        wxButton* m_sdbSizer1OK;
+        wxButton* m_sdbSizer1Apply;
+        wxButton* m_sdbSizer1Cancel;
+
+        // Virtual event handlers, overide them in your derived class
+        //virtual void OnActivateApp( wxActivateEvent& event ) { event.Skip(); }
+//        virtual void OnCloseFrame( wxCloseEvent& event ) { event.Skip(); }
+        void OnRxInDeviceSelect( wxListEvent& event );
+        void OnRxOutDeviceSelect( wxListEvent& event );
+        void OnTxInDeviceSelect( wxListEvent& event );
+        void OnTxOutDeviceSelect( wxListEvent& event );
+        void OnRefreshClick( wxCommandEvent& event );
+        void OnApplyAudioParameters( wxCommandEvent& event );
+        void OnCancelAudioParameters( wxCommandEvent& event );
+        void OnOkAudioParameters( wxCommandEvent& event );
+        // Virtual event handlers, overide them in your derived class
+        void OnClose( wxCloseEvent& event ) { event.Skip(); }
+        void OnHibernate( wxActivateEvent& event ) { event.Skip(); }
+        void OnIconize( wxIconizeEvent& event ) { event.Skip(); }
+        void OnInitDialog( wxInitDialogEvent& event );
+
+    public:
+
+        AudioOptsDialog( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Audio Options"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 300,300 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
+        ~AudioOptsDialog();
+        int ExchangeData(int inout);
+};
 #endif //__AudioOptsDialog__
index 8c9821ffa2bd73f9d362f8effd5fe20482ee0958..c1dae78428007675ffabfcf31fbef10570cee062 100644 (file)
@@ -61,13 +61,13 @@ struct FIFO        *g_plotSpeechOutFifo;
 struct FIFO        *g_plotSpeechInFifo;
 
 // Soundcard config
-int                 g_nSoundCards = 2;
-int                 g_soundCard1InDeviceNum = 0;
-int                 g_soundCard1OutDeviceNum = 0;
-int                 g_soundCard1SampleRate = 48000;
-int                 g_soundCard2InDeviceNum = 1;
-int                 g_soundCard2OutDeviceNum = 1;
-int                 g_soundCard2SampleRate = 44100;
+int                 g_nSoundCards;
+int                 g_soundCard1InDeviceNum;
+int                 g_soundCard1OutDeviceNum;
+int                 g_soundCard1SampleRate;
+int                 g_soundCard2InDeviceNum;
+int                 g_soundCard2OutDeviceNum;
+int                 g_soundCard2SampleRate;
 
 // Click to tune rx frequency offset states
 float               g_RxFreqOffsetHz;
@@ -140,23 +140,9 @@ int MainApp::OnExit()
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
 MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
 {
-    /*
-    // @class  $(Name)
-    // @author $(User)
-    // @date   $(Date)
-    // @file   $(CurrentFileName).$(CurrentFileExt)
-    // @brief
-    */
-//    m_radioRunning      = false;
-//    m_sound             = NULL;
     m_sfFile            = NULL;
     m_zoom              = 1.;
 
-    if(Pa_Initialize())
-    {
-        wxMessageBox(wxT("Port Audio failed to initialize"), wxT("Pa_Initialize"), wxOK);
-    }
-
     tools->AppendSeparator();
     wxMenuItem* m_menuItemToolsConfigDelete;
     m_menuItemToolsConfigDelete = new wxMenuItem(tools, wxID_ANY, wxString(_("&Delete stored config")) , wxT("Delete config file/keys"), wxITEM_NORMAL);
@@ -245,11 +231,20 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
         m_auiNbookCtrl->AddPage(m_panelFreqOffset, L"Frequency \u0394", true, wxNullBitmap);
     }
 
-    wxGetApp().m_strRxInAudio       = pConfig->Read(wxT("/Audio/RxIn"),         wxT("<m_strRxInAudio>"));
-    wxGetApp().m_strRxOutAudio      = pConfig->Read(wxT("/Audio/RxOut"),        wxT("<m_strRxOutAudio>"));
-    wxGetApp().m_textVoiceInput     = pConfig->Read(wxT("/Audio/TxIn"),         wxT("<m_textVoiceInput>"));
-    wxGetApp().m_textVoiceOutput    = pConfig->Read(wxT("/Audio/TxOut"),        wxT("<m_textVoiceOutput>"));
-    wxGetApp().m_strSampleRate      = pConfig->Read(wxT("/Audio/SampleRate"),   wxT("48000"));
+    g_soundCard1InDeviceNum  = pConfig->Read(wxT("/Audio/soundCard1InDeviceNum"),         -1);
+    g_soundCard1OutDeviceNum = pConfig->Read(wxT("/Audio/soundCard1OutDeviceNum"),        -1);
+    g_soundCard1SampleRate   = pConfig->Read(wxT("/Audio/soundCard1SampleRate"),          -1);
+
+    g_soundCard2InDeviceNum  = pConfig->Read(wxT("/Audio/soundCard2InDeviceNum"),         -1);
+    g_soundCard2OutDeviceNum = pConfig->Read(wxT("/Audio/soundCard2OutDeviceNum"),        -1);
+    g_soundCard2SampleRate   = pConfig->Read(wxT("/Audio/soundCard2SampleRate"),          -1);
+
+    g_nSoundCards = 0;
+    if ((g_soundCard1InDeviceNum > -1) && (g_soundCard1OutDeviceNum > -1)) {
+        g_nSoundCards = 1;
+        if ((g_soundCard2InDeviceNum > -1) && (g_soundCard2OutDeviceNum > -1))
+            g_nSoundCards = 2;
+    }
 
     wxGetApp().m_strRigCtrlPort     = pConfig->Read("/Rig/Port",                wxT("\\\\.\\com1"));
     wxGetApp().m_strRigCtrlBaud     = pConfig->Read("/Rig/Baud",                wxT("9600"));
@@ -330,11 +325,13 @@ MainFrame::~MainFrame()
         pConfig->Write(wxT("/Audio/SquelchActive"),     g_SquelchActive);
         pConfig->Write(wxT("/Audio/SquelchLevel"),     (int)(g_SquelchLevel*2.0));
 
-        pConfig->Write(wxT("/Audio/RxIn"),              wxGetApp().m_strRxInAudio);
-        pConfig->Write(wxT("/Audio/RxOut"),             wxGetApp().m_strRxOutAudio);
-        pConfig->Write(wxT("/Audio/TxIn"),              wxGetApp().m_textVoiceInput);
-        pConfig->Write(wxT("/Audio/TxOut"),             wxGetApp().m_textVoiceOutput);
-        pConfig->Write(wxT("/Audio/SampleRate"),        wxGetApp().m_strSampleRate);
+        pConfig->Write(wxT("/Audio/soundCard1InDeviceNum"),       g_soundCard1InDeviceNum);
+        pConfig->Write(wxT("/Audio/soundCard1OutDeviceNum"),      g_soundCard1OutDeviceNum);
+        pConfig->Write(wxT("/Audio/soundCard1SampleRate"),        g_soundCard1SampleRate );
+
+        pConfig->Write(wxT("/Audio/soundCard2InDeviceNum"),       g_soundCard2InDeviceNum);
+        pConfig->Write(wxT("/Audio/soundCard2OutDeviceNum"),      g_soundCard2OutDeviceNum);
+        pConfig->Write(wxT("/Audio/soundCard2SampleRate"),        g_soundCard2SampleRate );
 
         pConfig->Write(wxT("/Rig/Port"),                wxGetApp().m_strRigCtrlPort);
         pConfig->Write(wxT("/Rig/Baud"),                wxGetApp().m_strRigCtrlBaud);
@@ -986,63 +983,96 @@ wxString MainFrame::LoadUserImage(wxImage& image)
 //-------------------------------------------------------------------------
 void MainFrame::OnTogBtnOnOff(wxCommandEvent& event)
 {
-    if((!m_RxRunning))
-    {
-        printf("starting ...\n");
-        
+    wxString startStop = m_togBtnOnOff->GetLabel();
+
+    // we are attempting to start
+
+    if (startStop.IsSameAs("Start")) {
+
         m_togBtnSplit->Enable();
         m_togRxID->Enable();
         m_togTxID->Enable();
         m_togBtnAnalog->Enable();
-        //m_togBtnALC->Enable();
         m_btnTogTX->Enable();
         m_togBtnLoopRx->Enable();
         m_togBtnLoopTx->Enable();
+        m_togBtnOnOff->SetLabel(wxT("Stop"));
 
         // init modem and codec states
+
         g_pFDMDV  = fdmdv_create();
         g_pCodec2 = codec2_create(CODEC2_MODE_1400);
         g_State = 0;
 
         // init click-tune states
+
         g_RxFreqOffsetHz = 50.0;
         g_RxFreqOffsetFreqRect.real = cos(g_RxFreqOffsetHz);
         g_RxFreqOffsetFreqRect.imag = sin(g_RxFreqOffsetHz);
         g_RxFreqOffsetPhaseRect.real = cos(0.0);
         g_RxFreqOffsetPhaseRect.imag = sin(0.0);
         
-#ifdef _USE_TIMER
-        //DMW Reenable for the nonce... // DR: disable this puppy for now as it's causing a lot of error messages
-        m_plotTimer.Start(_REFRESH_TIMER_PERIOD, wxTIMER_CONTINUOUS);
-#endif // _USE_TIMER
+        // attempt to start sound cards and tx/rx processing
 
-        // start sound cards
         startRxStream();
 
-        if (m_RxRunning)
-        {
-            m_togBtnOnOff->SetLabel(wxT("Stop"));
+        if (m_RxRunning) {
+
+            #ifdef _USE_TIMER
+            m_plotTimer.Start(_REFRESH_TIMER_PERIOD, wxTIMER_CONTINUOUS);
+            #endif // _USE_TIMER
         }
     }
-    else
-    {
+   
+    // Stop was pressed or start up failed 
+
+    if (startStop.IsSameAs("Stop") || !m_RxRunning ) {
+
+        #ifdef _USE_TIMER
+        m_plotTimer.Stop();
+        #endif // _USE_TIMER
+
+        stopRxStream();
+
+        fdmdv_destroy(g_pFDMDV);
+        codec2_destroy(g_pCodec2);
+
         m_togBtnSplit->Disable();
         m_togRxID->Disable();
         m_togTxID->Disable();
         m_togBtnAnalog->Disable();
-        //m_togBtnALC->Disable();
         m_btnTogTX->Disable();
         m_togBtnLoopRx->Disable();
         m_togBtnLoopTx->Disable();
-#ifdef _USE_TIMER
-        //DMW Reenable for the nonce...
-        m_plotTimer.Stop();
-#endif // _USE_TIMER
-        stopRxStream();
         m_togBtnOnOff->SetLabel(wxT("Start"));
     }
 }
 
+//-------------------------------------------------------------------------
+// stopRxStream()
+//-------------------------------------------------------------------------
+void MainFrame::stopRxStream()
+{
+    if(m_RxRunning)
+    {
+        m_RxRunning = false;
+
+        m_rxPa->stop();
+        m_rxPa->streamClose();
+
+        if (g_nSoundCards == 2) {
+            m_txPa->stop();
+            m_txPa->streamClose();
+            delete m_txPa;
+        }
+
+        delete m_rxPa;
+        destroy_fifos();
+        destroy_src();
+        delete m_rxUserdata;
+    }
+}
+
 //----------------------------------------------------------
 // OnTogBtnLoopRx()
 //----------------------------------------------------------
@@ -1067,7 +1097,6 @@ void MainFrame::OnTogBtnLoopTx( wxCommandEvent& event )
 
 }
 
-
 void MainFrame::destroy_fifos(void)
 {
     fifo_destroy(m_rxUserdata->infifo1);
@@ -1094,8 +1123,8 @@ void MainFrame::autoDetectSoundCards(PortAudioWrap *pa)
     // trap zero sound devices
 
     if (pa->getDeviceCount() == 0) {
-    wxMessageBox(wxT("No sound devices found"), wxT("Error"), wxOK);
-    return;
+        wxMessageBox(wxT("No sound devices found"), wxT("Error"), wxOK);
+        return;
     }
 
     for(i=0; i<pa->getDeviceCount(); i++) {
@@ -1119,18 +1148,16 @@ int MainFrame::initPortAudioDevice(PortAudioWrap *pa, int inDevice, int outDevic
     char s[256];
 
     if (inDevice == paNoDevice) {
-    sprintf(s,"No input audio device available for Sound Card %d", soundCard);
-    wxString wxs(s);
-    wxMessageBox(wxs, wxT("Error"), wxOK);
+        sprintf(s,"No input audio device available for Sound Card %d", soundCard);
+        wxString wxs(s);
+        wxMessageBox(wxs, wxT("Error"), wxOK);
     }
     if (outDevice == paNoDevice) {
-    sprintf(s,"No output audio device available for Sound Card %d", soundCard);
-    wxString wxs(s);
-    wxMessageBox(wxs, wxT("Error"), wxOK);
+        sprintf(s,"No output audio device available for Sound Card %d", soundCard);
+        wxString wxs(s);
+        wxMessageBox(wxs, wxT("Error"), wxOK);
     }
 
-    printf("inDevice = %d outDevice = %d\n", inDevice, outDevice);
-
     // init input params
 
     pa->setInputDevice(inDevice);
@@ -1155,7 +1182,7 @@ int MainFrame::initPortAudioDevice(PortAudioWrap *pa, int inDevice, int outDevic
        equal PA_PFB, for example when I set PA_FPB to 960 I got
        framesPerBuffer = 1024.
     */
-    printf("Sound Card %d Sample rate %d\n", soundCard, sampleRate);
+
     pa->setFramesPerBuffer(PA_FPB);
     pa->setSampleRate(sampleRate);
     pa->setStreamFlags(0);
@@ -1177,32 +1204,42 @@ void MainFrame::startRxStream()
 
         m_RxRunning = true;
 
+        if(Pa_Initialize())
+        {
+            wxMessageBox(wxT("Port Audio failed to initialize"), wxT("Pa_Initialize"), wxOK);
+        }
+
         m_rxPa = new PortAudioWrap();
-        autoDetectSoundCards(m_rxPa);
+        //autoDetectSoundCards(m_rxPa);
 
+        if (g_nSoundCards == 0) {
+            wxMessageBox(wxT("No Sound Cards configured, use Tools - Audio Config to configure"), wxT("Error"), wxOK);
+            delete m_rxPa;
+            m_RxRunning = false;
+            return;
+        }
+                
         // Init Sound card 1 ----------------------------------------------
 
-        if ((g_soundCard1InDeviceNum != -1) || (g_soundCard1OutDeviceNum != -1)) {
+        assert((g_soundCard1InDeviceNum != -1) && (g_soundCard1OutDeviceNum != -1));
 
-            // user has specified the sound card device
+        // sanity check on sound card device numbers
 
-            if ((m_rxPa->getDeviceCount() < g_soundCard1InDeviceNum) ||
-                (m_rxPa->getDeviceCount() < g_soundCard1OutDeviceNum)) {
-                wxMessageBox(wxT("Sound Card 1 not present"), wxT("Error"), wxOK);
-                delete m_rxPa;
-                return;
-            }
+        printf("m_rxPa->getDeviceCount() %d\n", m_rxPa->getDeviceCount());
 
-            m_rxDevIn = g_soundCard1InDeviceNum;
-            m_rxDevOut = g_soundCard1OutDeviceNum;
-        }
-        else {
-            // not specified - use default
-            m_rxDevIn = m_rxPa->getDefaultInputDevice();
-            m_rxDevOut = m_rxPa->getDefaultOutputDevice();
+        if ((m_rxPa->getDeviceCount() < g_soundCard1InDeviceNum) ||
+            (m_rxPa->getDeviceCount() < g_soundCard1OutDeviceNum)) {
+            wxMessageBox(wxT("Sound Card 1 not present"), wxT("Error"), wxOK);
+            delete m_rxPa;
+            m_RxRunning = false;
+            return;
         }
 
+        m_rxDevIn = g_soundCard1InDeviceNum;
+        m_rxDevOut = g_soundCard1OutDeviceNum;
+
         if (initPortAudioDevice(m_rxPa, m_rxDevIn, m_rxDevOut, 1, g_soundCard1SampleRate) != 0) {
+            wxMessageBox(wxT("Can't start Sound Card 1"), wxT("Error"), wxOK);
             delete m_rxPa;
             m_RxRunning = false;
             return;
@@ -1215,13 +1252,15 @@ void MainFrame::startRxStream()
             m_txPa = new PortAudioWrap();
 
             assert((g_soundCard2InDeviceNum != -1) && (g_soundCard2OutDeviceNum != -1) );
-            printf("m_txPa->getDeviceCount() %d\n", m_txPa->getDeviceCount());
+
+            // sanity check on sound card device numbers
 
             if ((m_txPa->getDeviceCount() < g_soundCard2InDeviceNum) ||
                 (m_txPa->getDeviceCount() < g_soundCard2OutDeviceNum)) {
                 wxMessageBox(wxT("Sound Card 2 not present"), wxT("Error"), wxOK);
                 delete m_rxPa;
                 delete m_txPa;
+                m_RxRunning = false;
                 return;
             }
 
@@ -1229,6 +1268,7 @@ void MainFrame::startRxStream()
             m_txDevOut = g_soundCard2OutDeviceNum;
 
             if (initPortAudioDevice(m_txPa, m_txDevIn, m_txDevOut, 2, g_soundCard2SampleRate) != 0) {
+                wxMessageBox(wxT("Can't start Sound Card 2"), wxT("Error"), wxOK);
                 delete m_rxPa;
                 delete m_txPa;
                 m_RxRunning = false;
@@ -1359,35 +1399,6 @@ void MainFrame::startRxStream()
  
 }
 
-//-------------------------------------------------------------------------
-// stopRxStream()
-//-------------------------------------------------------------------------
-void MainFrame::stopRxStream()
-{
-    if(m_RxRunning)
-    {
-        m_RxRunning = false;
-
-        m_rxPa->stop();
-        m_rxPa->streamClose();
-
-    if (g_nSoundCards == 2) {
-        m_txPa->stop();
-        m_txPa->streamClose();
-        delete m_txPa;
-    }
-
-    delete m_rxPa;
-    destroy_fifos();
-    destroy_src();
-        delete m_rxUserdata;
-
-        fdmdv_destroy(g_pFDMDV);
-        codec2_destroy(g_pCodec2);
-    }
-
-}
-
 
 //----------------------------------------------------------------
 // update average of each spectrum point
index c0718ddbec00ea33c7465d9b510dcae002a897b7..7c543df3a25a6543d4d04788a65fb5e3126a71be 100644 (file)
@@ -66,6 +66,14 @@ enum {
 #define EXCHANGE_DATA_IN    0
 #define EXCHANGE_DATA_OUT   1
 
+extern int                 g_nSoundCards;
+extern int                 g_soundCard1InDeviceNum;
+extern int                 g_soundCard1OutDeviceNum;
+extern int                 g_soundCard1SampleRate;
+extern int                 g_soundCard2InDeviceNum;
+extern int                 g_soundCard2OutDeviceNum;
+extern int                 g_soundCard2SampleRate;
+
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
 // Class MainApp
 //