From 4a762fc9361187d42912c1b353a2fb1d8d4f0cd8 Mon Sep 17 00:00:00 2001 From: mchinen Date: Sun, 13 Feb 2011 23:00:43 +0000 Subject: [PATCH] bug 29/11 - add rescan capability for devices. This is a workaround for the portaudio issue where changing the default device in xp will corrupt the portaudio device indecies. This combined with the portmixer fix (earlier today) should address bug 29. --- src/DeviceManager.cpp | 31 ++++++++++++++++--- src/Menus.cpp | 7 +++++ src/Menus.h | 1 + src/toolbars/DeviceToolBar.cpp | 56 ++++++++++++++++------------------ src/toolbars/DeviceToolBar.h | 4 ++- 5 files changed, 63 insertions(+), 36 deletions(-) diff --git a/src/DeviceManager.cpp b/src/DeviceManager.cpp index 15a9791f0..7cb36fd22 100644 --- a/src/DeviceManager.cpp +++ b/src/DeviceManager.cpp @@ -9,9 +9,11 @@ #include "portaudio.h" #include "portmixer.h" -#include "../Audacity.h" +#include "Audacity.h" +#include "AudioIO.h" #include "DeviceManager.h" +#include "toolbars/DeviceToolBar.h" DeviceManager DeviceManager::dm; @@ -30,13 +32,13 @@ void DeviceManager::Destroy() std::vector &DeviceManager::GetInputDeviceMaps() { if (!m_inited) - Rescan(); + Init(); return mInputDeviceSourceMaps; } std::vector &DeviceManager::GetOutputDeviceMaps() { if (!m_inited) - Rescan(); + Init(); return mOutputDeviceSourceMaps; } @@ -190,8 +192,18 @@ void DeviceManager::Rescan() // if we are doing a second scan then restart portaudio to get new devices if (m_inited) { // check to see if there is a stream open - can happen if monitoring, - // but otherwise Rescan() should not be available to the user. - + // but otherwise Rescan() should not be available to the user. + if (gAudioIO) { + if (gAudioIO->IsMonitoring()) + { + gAudioIO->StopStream(); + while (gAudioIO->IsBusy()) + wxMilliSleep(100); + } + gAudioIO->HandleDeviceChange(); + } + + // restart portaudio - this updates the device list Pa_Terminate(); Pa_Initialize(); } @@ -213,6 +225,15 @@ void DeviceManager::Rescan() } } + // If this was not an initial scan update each device toolbar. + // Hosts may have disappeared or appeared so a complete repopulate is needed. + if (m_inited) { + DeviceToolBar *dt; + for (size_t i = 0; i < gAudacityProjects.GetCount(); i++) { + dt = gAudacityProjects[i]->GetDeviceToolBar(); + dt->RefillCombos(); + } + } m_inited = true; } diff --git a/src/Menus.cpp b/src/Menus.cpp index d67e26ad8..53c5775b2 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -108,6 +108,7 @@ simplifies construction of menu items. #include "FileDialog.h" #include "SplashDialog.h" #include "widgets/ErrorDialog.h" +#include "DeviceManager.h" #include "CaptureEvents.h" @@ -643,6 +644,7 @@ void AudacityProject::CreateMenusAndCommands() #ifdef AUTOMATED_INPUT_LEVEL_ADJUSTMENT c->AddCheck(wxT("AutomatedInputLevelAdjustmentOnOff"), _("Automated Input Level Adjustment (on/off)"), FN(OnToogleAutomatedInputLevelAdjustment), 0); #endif + c->AddItem(wxT("RescanDevices"), _("Rescan Audio Devices"), FN(OnRescanDevices)); if (!mCleanSpeechMode) { @@ -5391,6 +5393,11 @@ void AudacityProject::OnSoundActivated() dialog.ShowModal(); } +void AudacityProject::OnRescanDevices() +{ + DeviceManager::Instance()->Rescan(); +} + int AudacityProject::DoAddLabel(double left, double right) { LabelTrack *lt = NULL; diff --git a/src/Menus.h b/src/Menus.h index da04af41a..d59429e8c 100644 --- a/src/Menus.h +++ b/src/Menus.h @@ -294,6 +294,7 @@ void OnToggleSWPlaythrough(); #ifdef AUTOMATED_INPUT_LEVEL_ADJUSTMENT void OnToogleAutomatedInputLevelAdjustment(); #endif +void OnRescanDevices(); // Tracks Menu diff --git a/src/toolbars/DeviceToolBar.cpp b/src/toolbars/DeviceToolBar.cpp index 9a41a208f..7595061af 100644 --- a/src/toolbars/DeviceToolBar.cpp +++ b/src/toolbars/DeviceToolBar.cpp @@ -103,31 +103,18 @@ void DeviceToolBar::DeinitChildren() void DeviceToolBar::Populate() { - wxArrayString inputs; - wxArrayString outputs; - wxArrayString hosts; - wxArrayString channels; - DeinitChildren(); - - channels.Add(wxT("1 (Mono)")); - // Hosts - FillHosts(hosts); mHost = new wxChoice(this, wxID_ANY, wxDefaultPosition, - wxDefaultSize, - hosts); + wxDefaultSize); mHost->SetName(_("Audio Host")); Add(mHost, 0, wxALIGN_CENTER); - if (hosts.GetCount() == 0) - mHost->Enable(false); // Output device mPlayBitmap = new wxBitmap(theTheme.Bitmap(bmpSpeaker)); - Add(new wxStaticBitmap(this, wxID_ANY, *mPlayBitmap), 0, wxALIGN_CENTER); @@ -135,13 +122,9 @@ void DeviceToolBar::Populate() mOutput = new wxChoice(this, wxID_ANY, wxDefaultPosition, - wxDefaultSize, - outputs); + wxDefaultSize); mOutput->SetName(_("Output Device")); - Add(mOutput, 0, wxALIGN_CENTER); - if (outputs.GetCount() == 0) - mOutput->Enable(false); // Input device mRecordBitmap = new wxBitmap(theTheme.Bitmap(bmpMic)); @@ -153,23 +136,16 @@ void DeviceToolBar::Populate() mInput = new wxChoice(this, wxID_ANY, wxDefaultPosition, - wxDefaultSize, - inputs); + wxDefaultSize); mInput->SetName(_("Input Device")); Add(mInput, 0, wxALIGN_CENTER); - if (inputs.GetCount() == 0) - mInput->Enable(false); - mInputChannels = new wxChoice(this, wxID_ANY, wxDefaultPosition, - wxDefaultSize, - channels); + wxDefaultSize); mInputChannels->SetName(_("Input Channels")); Add(mInputChannels, 0, wxALIGN_CENTER); - // hide the number of channels until we have some to display - mInputChannels->Enable(false); mHost->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(DeviceToolBar::OnFocus), @@ -204,6 +180,12 @@ void DeviceToolBar::Populate() NULL, this); + RefillCombos(); +} + +void DeviceToolBar::RefillCombos() +{ + FillHosts(); FillHostDevices(); FillInputChannels(); // make the device display selection reflect the prefs if they exist @@ -474,20 +456,26 @@ void DeviceToolBar::RepositionCombos() Update(); } -void DeviceToolBar::FillHosts(wxArrayString &hosts) +void DeviceToolBar::FillHosts() { + wxArrayString hosts; size_t i; std::vector &inMaps = DeviceManager::Instance()->GetInputDeviceMaps(); std::vector &outMaps = DeviceManager::Instance()->GetOutputDeviceMaps(); // go over our lists add the host to the list if it isn't there yet - for (i = 0; i < inMaps.size(); i++) if (hosts.Index(inMaps[i].hostString) == wxNOT_FOUND) hosts.Add(inMaps[i].hostString); for (i = 0; i < outMaps.size(); i++) if (hosts.Index(outMaps[i].hostString) == wxNOT_FOUND) hosts.Add(outMaps[i].hostString); + + mHost->Clear(); + mHost->Append(hosts); + + if (hosts.GetCount() == 0) + mHost->Enable(false); } void DeviceToolBar::FillHostDevices() @@ -499,6 +487,12 @@ void DeviceToolBar::FillHostDevices() wxString host = gPrefs->Read(wxT("/AudioIO/Host"), wxT("")); size_t i; int foundHostIndex = -1; + + // if the host is not in the hosts combo then we rescanned. + // set it to blank so we search for another host. + if (mHost->FindString(host) == wxNOT_FOUND) + host = wxT(""); + for (i = 0; i < outMaps.size(); i++) { if (outMaps[i].hostString == host) { foundHostIndex = outMaps[i].hostIndex; @@ -535,6 +529,7 @@ void DeviceToolBar::FillHostDevices() if (host == wxT("")) { host = inMaps[i].hostString; gPrefs->Write(wxT("/AudioIO/Host"), host); + mHost->SetStringSelection(host); } } } @@ -547,6 +542,7 @@ void DeviceToolBar::FillHostDevices() if (host == wxT("")) { host = outMaps[i].hostString; gPrefs->Write(wxT("/AudioIO/Host"), host); + mHost->SetStringSelection(host); } } } diff --git a/src/toolbars/DeviceToolBar.h b/src/toolbars/DeviceToolBar.h index f2643fa43..6e1d0f909 100644 --- a/src/toolbars/DeviceToolBar.h +++ b/src/toolbars/DeviceToolBar.h @@ -53,10 +53,12 @@ class DeviceToolBar:public ToolBar { void ShowHostDialog(); void ShowChannelsDialog(); + void RefillCombos(); + private: int ChangeHost(); void ChangeDevice(bool isInput); - void FillHosts(wxArrayString &hosts); + void FillHosts(); void FillHostDevices(); void FillInputChannels(); void SetDevices(DeviceSourceMap *in, DeviceSourceMap *out);