From: drowe67 Date: Mon, 26 May 2014 21:20:40 +0000 (+0000) Subject: Stephen's indep sound card selection logic and setting min size X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=3a51192f5e13dd1ba2fc35469ce50b265ed3e9e9;p=freetel-svn-tracking.git Stephen's indep sound card selection logic and setting min size git-svn-id: https://svn.code.sf.net/p/freetel/code@1595 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/fdmdv2/src/fdmdv2_main.cpp b/fdmdv2/src/fdmdv2_main.cpp index ba93e3db..74e76957 100644 --- a/fdmdv2/src/fdmdv2_main.cpp +++ b/fdmdv2/src/fdmdv2_main.cpp @@ -137,6 +137,8 @@ bool MainApp::OnInit() SetVendorName(wxT("CODEC2-Project")); SetAppName(wxT("FreeDV")); // not needed, it's the default value + // DR - this is wrong define so won't be used on windows build, should be __WXMSW__ + // So registry will be used for Win32 #ifdef _WXMSW_ // Force use of file-based configuration persistance on Windows platforma wxConfig *pConfig = new wxConfig(); @@ -182,6 +184,8 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent) { m_zoom = 1.; + SetMinSize(wxSize(400,400)); + // Init Hamlib library, but we dont start talking to any rigs yet wxGetApp().m_hamlib = new Hamlib(); @@ -1983,16 +1987,26 @@ void MainFrame::stopRxStream() m_txRxThread->Wait(); wxLogDebug("thread stopped"); - m_rxPa->stop(); - m_rxPa->streamClose(); + m_rxInPa->stop(); + m_rxInPa->streamClose(); + delete m_rxInPa; + if(m_rxOutPa != m_rxInPa) { + m_rxOutPa->stop(); + m_rxOutPa->streamClose(); + delete m_rxOutPa; + } if (g_nSoundCards == 2) { - m_txPa->stop(); - m_txPa->streamClose(); - delete m_txPa; + m_txInPa->stop(); + m_txInPa->streamClose(); + delete m_txInPa; + if(m_txInPa != m_txOutPa) { + m_txOutPa->stop(); + m_txOutPa->streamClose(); + delete m_txOutPa; + } } - delete m_rxPa; destroy_fifos(); destroy_src(); deleteEQFilters(g_rxUserdata); @@ -2028,18 +2042,22 @@ void MainFrame::initPortAudioDevice(PortAudioWrap *pa, int inDevice, int outDev // init input params pa->setInputDevice(inDevice); - pa->setInputChannelCount(inputChannels); // stereo input - pa->setInputSampleFormat(PA_SAMPLE_TYPE); - pa->setInputLatency(pa->getInputDefaultLowLatency()); - pa->setInputHostApiStreamInfo(NULL); + if(inDevice != paNoDevice) { + pa->setInputChannelCount(inputChannels); // stereo input + pa->setInputSampleFormat(PA_SAMPLE_TYPE); + pa->setInputLatency(pa->getInputDefaultLowLatency()); + pa->setInputHostApiStreamInfo(NULL); + } // init output params - pa->setOutputDevice(outDevice); - pa->setOutputChannelCount(2); // stereo output - pa->setOutputSampleFormat(PA_SAMPLE_TYPE); - pa->setOutputLatency(pa->getOutputDefaultLowLatency()); - pa->setOutputHostApiStreamInfo(NULL); + pa->setOutputDevice(outDevice); + if(outDevice != paNoDevice) { + pa->setOutputChannelCount(2); // stereo output + pa->setOutputSampleFormat(PA_SAMPLE_TYPE); + pa->setOutputLatency(pa->getOutputDefaultLowLatency()); + pa->setOutputHostApiStreamInfo(NULL); + } // init params that affect input and output @@ -2062,6 +2080,8 @@ void MainFrame::startRxStream() int src_error; const PaDeviceInfo *deviceInfo1 = NULL, *deviceInfo2 = NULL; int inputChannels1, inputChannels2; + bool two_rx=false; + bool two_tx=false; if(!m_RxRunning) { m_RxRunning = true; @@ -2071,11 +2091,22 @@ void MainFrame::startRxStream() wxMessageBox(wxT("Port Audio failed to initialize"), wxT("Pa_Initialize"), wxOK); } - m_rxPa = new PortAudioWrap(); + m_rxInPa = new PortAudioWrap(); + if(g_soundCard1InDeviceNum != g_soundCard1OutDeviceNum) + two_rx=true; + if(g_soundCard2InDeviceNum != g_soundCard2OutDeviceNum) + two_tx=true; + + if(two_rx) + m_rxOutPa = new PortAudioWrap(); + else + m_rxOutPa = m_rxInPa; if (g_nSoundCards == 0) { wxMessageBox(wxT("No Sound Cards configured, use Tools - Audio Config to configure"), wxT("Error"), wxOK); - delete m_rxPa; + delete m_rxInPa; + if(two_rx) + delete m_rxOutPa; m_RxRunning = false; return; } @@ -2083,10 +2114,12 @@ void MainFrame::startRxStream() // Init Sound card 1 ---------------------------------------------- // sanity check on sound card device numbers - if ((m_rxPa->getDeviceCount() <= g_soundCard1InDeviceNum) || - (m_rxPa->getDeviceCount() <= g_soundCard1OutDeviceNum)) { + if ((m_rxInPa->getDeviceCount() <= g_soundCard1InDeviceNum) || + (m_rxOutPa->getDeviceCount() <= g_soundCard1OutDeviceNum)) { wxMessageBox(wxT("Sound Card 1 not present"), wxT("Error"), wxOK); - delete m_rxPa; + delete m_rxInPa; + if(two_rx) + delete m_rxOutPa; m_RxRunning = false; return; } @@ -2096,7 +2129,9 @@ void MainFrame::startRxStream() deviceInfo1 = Pa_GetDeviceInfo(g_soundCard1InDeviceNum); if (deviceInfo1 == NULL) { wxMessageBox(wxT("Couldn't get device info from Port Audio for Sound Card 1"), wxT("Error"), wxOK); - delete m_rxPa; + delete m_rxInPa; + if(two_rx) + delete m_rxOutPa; m_RxRunning = false; return; } @@ -2105,26 +2140,41 @@ void MainFrame::startRxStream() else inputChannels1 = 2; - initPortAudioDevice(m_rxPa, g_soundCard1InDeviceNum, g_soundCard1OutDeviceNum, 1, + if(two_rx) { + initPortAudioDevice(m_rxInPa, g_soundCard1InDeviceNum, paNoDevice, 1, + g_soundCard1SampleRate, inputChannels1); + initPortAudioDevice(m_rxOutPa, paNoDevice, g_soundCard1OutDeviceNum, 1, + g_soundCard1SampleRate, inputChannels1); + } + else + initPortAudioDevice(m_rxInPa, g_soundCard1InDeviceNum, g_soundCard1OutDeviceNum, 1, g_soundCard1SampleRate, inputChannels1); // Init Sound Card 2 ------------------------------------------------ if (g_nSoundCards == 2) { - m_txPa = new PortAudioWrap(); + m_txInPa = new PortAudioWrap(); + if(two_tx) + m_txOutPa = new PortAudioWrap(); + else + m_txOutPa = m_txInPa; // sanity check on sound card device numbers - //printf("m_txPa->getDeviceCount(): %d\n", m_txPa->getDeviceCount()); + //printf("m_txInPa->getDeviceCount(): %d\n", m_txInPa->getDeviceCount()); //printf("g_soundCard2InDeviceNum: %d\n", g_soundCard2InDeviceNum); //printf("g_soundCard2OutDeviceNum: %d\n", g_soundCard2OutDeviceNum); - if ((m_txPa->getDeviceCount() <= g_soundCard2InDeviceNum) || - (m_txPa->getDeviceCount() <= g_soundCard2OutDeviceNum)) { + if ((m_txInPa->getDeviceCount() <= g_soundCard2InDeviceNum) || + (m_txOutPa->getDeviceCount() <= g_soundCard2OutDeviceNum)) { wxMessageBox(wxT("Sound Card 2 not present"), wxT("Error"), wxOK); - delete m_rxPa; - delete m_txPa; + delete m_rxInPa; + if(two_rx) + delete m_rxOutPa; + delete m_txInPa; + if(two_tx) + delete m_txOutPa; m_RxRunning = false; return; } @@ -2132,7 +2182,12 @@ void MainFrame::startRxStream() deviceInfo2 = Pa_GetDeviceInfo(g_soundCard2InDeviceNum); if (deviceInfo2 == NULL) { wxMessageBox(wxT("Couldn't get device info from Port Audio for Sound Card 1"), wxT("Error"), wxOK); - delete m_rxPa; + delete m_rxInPa; + if(two_rx) + delete m_rxOutPa; + delete m_txInPa; + if(two_tx) + delete m_txOutPa; m_RxRunning = false; return; } @@ -2141,7 +2196,14 @@ void MainFrame::startRxStream() else inputChannels2 = 2; - initPortAudioDevice(m_txPa, g_soundCard2InDeviceNum, g_soundCard2OutDeviceNum, 2, + if(two_tx) { + initPortAudioDevice(m_txInPa, g_soundCard2InDeviceNum, paNoDevice, 2, + g_soundCard2SampleRate, inputChannels2); + initPortAudioDevice(m_txOutPa, paNoDevice, g_soundCard2OutDeviceNum, 2, + g_soundCard2SampleRate, inputChannels2); + } + else + initPortAudioDevice(m_txInPa, g_soundCard2InDeviceNum, g_soundCard2OutDeviceNum, 2, g_soundCard2SampleRate, inputChannels2); } @@ -2182,15 +2244,19 @@ void MainFrame::startRxStream() // Start sound card 1 ---------------------------------------------------------- - m_rxPa->setUserData(g_rxUserdata); - m_rxErr = m_rxPa->setCallback(rxCallback); + m_rxInPa->setUserData(g_rxUserdata); + m_rxErr = m_rxInPa->setCallback(rxCallback); - m_rxErr = m_rxPa->streamOpen(); + m_rxErr = m_rxInPa->streamOpen(); if(m_rxErr != paNoError) { wxMessageBox(wxT("Sound Card 1 Open/Setup error."), wxT("Error"), wxOK); - delete m_rxPa; - delete m_txPa; + delete m_rxInPa; + if(two_rx) + delete m_rxOutPa; + delete m_txInPa; + if(two_tx) + delete m_txOutPa; destroy_fifos(); destroy_src(); deleteEQFilters(g_rxUserdata); @@ -2199,11 +2265,15 @@ void MainFrame::startRxStream() return; } - m_rxErr = m_rxPa->streamStart(); + m_rxErr = m_rxInPa->streamStart(); if(m_rxErr != paNoError) { wxMessageBox(wxT("Sound Card 1 Stream Start Error."), wxT("Error"), wxOK); - delete m_rxPa; - delete m_txPa; + delete m_rxInPa; + if(two_rx) + delete m_rxOutPa; + delete m_txInPa; + if(two_tx) + delete m_txOutPa; destroy_fifos(); destroy_src(); deleteEQFilters(g_rxUserdata); @@ -2212,6 +2282,48 @@ void MainFrame::startRxStream() return; } + // Start separate output stream if needed + + if(two_rx) { + m_rxOutPa->setUserData(g_rxUserdata); + m_rxErr = m_rxOutPa->setCallback(rxCallback); + + m_rxErr = m_rxOutPa->streamOpen(); + + if(m_rxErr != paNoError) { + wxMessageBox(wxT("Sound Card 1 Second Stream Open/Setup error."), wxT("Error"), wxOK); + delete m_rxInPa; + delete m_rxOutPa; + delete m_txOutPa; + if(two_tx) + delete m_txOutPa; + destroy_fifos(); + destroy_src(); + deleteEQFilters(g_rxUserdata); + delete g_rxUserdata; + m_RxRunning = false; + return; + } + + m_rxErr = m_rxOutPa->streamStart(); + if(m_rxErr != paNoError) { + wxMessageBox(wxT("Sound Card 1 Second Stream Start Error."), wxT("Error"), wxOK); + m_rxInPa->stop(); + m_rxInPa->streamClose(); + delete m_rxInPa; + delete m_rxOutPa; + delete m_txOutPa; + if(two_tx) + delete m_txOutPa; + destroy_fifos(); + destroy_src(); + deleteEQFilters(g_rxUserdata); + delete g_rxUserdata; + m_RxRunning = false; + return; + } + } + // Start sound card 2 ---------------------------------------------------------- if (g_nSoundCards == 2) { @@ -2221,16 +2333,24 @@ void MainFrame::startRxStream() // chance of them both being called at the same time? We // could need a mutex ... - m_txPa->setUserData(g_rxUserdata); - m_txErr = m_txPa->setCallback(txCallback); - m_txErr = m_txPa->streamOpen(); + m_txInPa->setUserData(g_rxUserdata); + m_txErr = m_txInPa->setCallback(txCallback); + m_txErr = m_txInPa->streamOpen(); if(m_txErr != paNoError) { +fprintf(stderr, "Err: %d\n", m_txErr); wxMessageBox(wxT("Sound Card 2 Open/Setup error."), wxT("Error"), wxOK); - m_rxPa->stop(); - m_rxPa->streamClose(); - delete m_rxPa; - delete m_txPa; + m_rxInPa->stop(); + m_rxInPa->streamClose(); + delete m_rxInPa; + if(two_rx) { + m_rxOutPa->stop(); + m_rxOutPa->streamClose(); + delete m_rxOutPa; + } + delete m_txInPa; + if(two_tx) + delete m_txOutPa; destroy_fifos(); destroy_src(); deleteEQFilters(g_rxUserdata); @@ -2238,13 +2358,20 @@ void MainFrame::startRxStream() m_RxRunning = false; return; } - m_txErr = m_txPa->streamStart(); + m_txErr = m_txInPa->streamStart(); if(m_txErr != paNoError) { wxMessageBox(wxT("Sound Card 2 Start Error."), wxT("Error"), wxOK); - m_rxPa->stop(); - m_rxPa->streamClose(); - delete m_rxPa; - delete m_txPa; + m_rxInPa->stop(); + m_rxInPa->streamClose(); + delete m_rxInPa; + if(two_rx) { + m_rxOutPa->stop(); + m_rxOutPa->streamClose(); + delete m_rxOutPa; + } + delete m_txInPa; + if(two_tx) + delete m_txOutPa; destroy_fifos(); destroy_src(); deleteEQFilters(g_rxUserdata); @@ -2252,6 +2379,63 @@ void MainFrame::startRxStream() m_RxRunning = false; return; } + // Start separate output stream if needed + + if (two_tx) { + + // question: can we use same callback data + // (g_rxUserdata)or both sound card callbacks? Is there a + // chance of them both being called at the same time? We + // could need a mutex ... + + m_txOutPa->setUserData(g_rxUserdata); + m_txErr = m_txOutPa->setCallback(txCallback); + m_txErr = m_txOutPa->streamOpen(); + + if(m_txErr != paNoError) { + wxMessageBox(wxT("Sound Card 2 Second Stream Open/Setup error."), wxT("Error"), wxOK); + m_rxInPa->stop(); + m_rxInPa->streamClose(); + delete m_rxInPa; + if(two_rx) { + m_rxOutPa->stop(); + m_rxOutPa->streamClose(); + delete m_rxOutPa; + } + m_txInPa->stop(); + m_txInPa->streamClose(); + delete m_txInPa; + delete m_txOutPa; + destroy_fifos(); + destroy_src(); + deleteEQFilters(g_rxUserdata); + delete g_rxUserdata; + m_RxRunning = false; + return; + } + m_txErr = m_txOutPa->streamStart(); + if(m_txErr != paNoError) { + wxMessageBox(wxT("Sound Card 2 Second Stream Start Error."), wxT("Error"), wxOK); + m_rxInPa->stop(); + m_rxInPa->streamClose(); + m_txInPa->stop(); + m_txInPa->streamClose(); + delete m_txInPa; + if(two_rx) { + m_rxOutPa->stop(); + m_rxOutPa->streamClose(); + delete m_rxOutPa; + } + delete m_txInPa; + delete m_txOutPa; + destroy_fifos(); + destroy_src(); + deleteEQFilters(g_rxUserdata); + delete g_rxUserdata; + m_RxRunning = false; + return; + } + } } // start tx/rx processing thread @@ -2667,35 +2851,39 @@ int MainFrame::rxCallback( assert(framesPerBuffer < MAX_FPB); - for(i = 0; i < framesPerBuffer; i++, rptr += cbData->inputChannels1) - { - indata[i] = *rptr; - } - if (fifo_write(cbData->infifo1, indata, framesPerBuffer)) { - //wxLogDebug("infifo1 full\n"); - } + if(rptr) { + for(i = 0; i < framesPerBuffer; i++, rptr += cbData->inputChannels1) + { + indata[i] = *rptr; + } + if (fifo_write(cbData->infifo1, indata, framesPerBuffer)) { + //wxLogDebug("infifo1 full\n"); + } + } // OK now set up output samples for this callback - if (fifo_read(cbData->outfifo1, outdata, framesPerBuffer) == 0) - { - // write signal to both channels */ - for(i = 0; i < framesPerBuffer; i++, wptr += 2) - { - wptr[0] = outdata[i]; - wptr[1] = outdata[i]; - } - } - else - { - //wxLogDebug("outfifo1 empty\n"); - // zero output if no data available - for(i = 0; i < framesPerBuffer; i++, wptr += 2) - { - wptr[0] = 0; - wptr[1] = 0; - } - } + if(wptr) { + if (fifo_read(cbData->outfifo1, outdata, framesPerBuffer) == 0) + { + // write signal to both channels */ + for(i = 0; i < framesPerBuffer; i++, wptr += 2) + { + wptr[0] = outdata[i]; + wptr[1] = outdata[i]; + } + } + else + { + //wxLogDebug("outfifo1 empty\n"); + // zero output if no data available + for(i = 0; i < framesPerBuffer; i++, wptr += 2) + { + wptr[0] = 0; + wptr[1] = 0; + } + } + } return paContinue; } @@ -3210,43 +3398,51 @@ int MainFrame::txCallback( assert(framesPerBuffer < MAX_FPB); - for(i = 0; i < framesPerBuffer; i++, rptr += cbData->inputChannels2) - { - indata[i] = *rptr; - } + if(rptr) { + for(i = 0; i < framesPerBuffer; i++, rptr += cbData->inputChannels2) + { + indata[i] = *rptr; + } + } //#define SC2_LOOPBACK #ifdef SC2_LOOPBACK + //TODO: This doesn't work unless using the same soundcard! - for(i = 0; i < framesPerBuffer; i++, wptr += 2) - { - wptr[0] = indata[i]; - wptr[1] = indata[i]; - } + if(wptr) { + for(i = 0; i < framesPerBuffer; i++, wptr += 2) + { + wptr[0] = indata[i]; + wptr[1] = indata[i]; + } + } #else - fifo_write(cbData->infifo2, indata, framesPerBuffer); + if(rptr) + fifo_write(cbData->infifo2, indata, framesPerBuffer); // OK now set up output samples for this callback - if (fifo_read(cbData->outfifo2, outdata, framesPerBuffer) == 0) - { - // write signal to both channels */ - for(i = 0; i < framesPerBuffer; i++, wptr += 2) - { - wptr[0] = outdata[i]; - wptr[1] = outdata[i]; - } - } - else - { - // zero output if no data available - for(i = 0; i < framesPerBuffer; i++, wptr += 2) - { - wptr[0] = 0; - wptr[1] = 0; - } - } + if(wptr) { + if (fifo_read(cbData->outfifo2, outdata, framesPerBuffer) == 0) + { + // write signal to both channels */ + for(i = 0; i < framesPerBuffer; i++, wptr += 2) + { + wptr[0] = outdata[i]; + wptr[1] = outdata[i]; + } + } + else + { + // zero output if no data available + for(i = 0; i < framesPerBuffer; i++, wptr += 2) + { + wptr[0] = 0; + wptr[1] = 0; + } + } + } #endif return paContinue; }