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.
This commit is contained in:
mchinen 2011-02-13 23:00:43 +00:00
parent 271c4b0112
commit 4a762fc936
5 changed files with 63 additions and 36 deletions

View File

@ -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<DeviceSourceMap> &DeviceManager::GetInputDeviceMaps()
{
if (!m_inited)
Rescan();
Init();
return mInputDeviceSourceMaps;
}
std::vector<DeviceSourceMap> &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;
}

View File

@ -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;

View File

@ -294,6 +294,7 @@ void OnToggleSWPlaythrough();
#ifdef AUTOMATED_INPUT_LEVEL_ADJUSTMENT
void OnToogleAutomatedInputLevelAdjustment();
#endif
void OnRescanDevices();
// Tracks Menu

View File

@ -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<DeviceSourceMap> &inMaps = DeviceManager::Instance()->GetInputDeviceMaps();
std::vector<DeviceSourceMap> &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);
}
}
}

View File

@ -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);