1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-03 17:19:43 +02:00

bug 11 partial fix - add host and num channels to DeviceToolbar

removal of device prefs and source selection from mixer toolbar to follow.
This commit is contained in:
mchinen 2011-01-09 05:12:09 +00:00
parent ff398a27b3
commit 8c645724a1
4 changed files with 324 additions and 140 deletions

View File

@ -459,8 +459,7 @@ void InitAudioIO()
const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
if (info) {
gPrefs->Write(wxT("/AudioIO/RecordingDevice"), DeviceName(info));
gPrefs->Write(wxT("/AudioIO/Host"),
wxString(Pa_GetHostApiInfo(info->hostApi)->name, wxConvLocal));
gPrefs->Write(wxT("/AudioIO/Host"), HostName(info));
}
}
@ -469,8 +468,7 @@ void InitAudioIO()
const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
if (info) {
gPrefs->Write(wxT("/AudioIO/PlaybackDevice"), DeviceName(info));
gPrefs->Write(wxT("/AudioIO/Host"),
wxString(Pa_GetHostApiInfo(info->hostApi)->name, wxConvLocal));
gPrefs->Write(wxT("/AudioIO/Host"), HostName(info));
}
}
}
@ -482,12 +480,16 @@ void DeinitAudioIO()
wxString DeviceName(const PaDeviceInfo* info)
{
wxString hostapiName(Pa_GetHostApiInfo(info->hostApi)->name, wxConvLocal);
wxString infoName(info->name, wxConvLocal);
return wxString::Format(wxT("%s: %s"),
hostapiName.c_str(),
infoName.c_str());
return infoName;
}
wxString HostName(const PaDeviceInfo* info)
{
wxString hostapiName(Pa_GetHostApiInfo(info->hostApi)->name, wxConvLocal);
return hostapiName;
}
bool AudioIO::ValidateDeviceNames(wxString play, wxString rec)
@ -2260,6 +2262,8 @@ int AudioIO::GetCommonlyAvailCapture()
int AudioIO::getRecordDevIndex(wxString devName)
{
wxString hostName = gPrefs->Read(wxT("/AudioIO/Host"), wxT(""));
// if we don't get given a device, look up the preferences
if (devName.IsEmpty())
{
@ -2271,7 +2275,8 @@ int AudioIO::getRecordDevIndex(wxString devName)
{
const PaDeviceInfo* info = Pa_GetDeviceInfo(i);
if (info && (DeviceName(info) == devName) && (info->maxInputChannels > 0))
if (info && (DeviceName(info) == devName) &&
HostName(info) == hostName && (info->maxInputChannels > 0))
{
// this device name matches the stored one, and works.
// So we say this is the answer and return it
@ -2306,6 +2311,7 @@ int AudioIO::getRecordSourceIndex(PxMixer *portMixer)
int AudioIO::getPlayDevIndex(wxString devName )
{
wxString hostName = gPrefs->Read(wxT("/AudioIO/Host"), wxT(""));
// if we don't get given a device, look up the preferences
if (devName.IsEmpty())
{
@ -2317,7 +2323,8 @@ int AudioIO::getPlayDevIndex(wxString devName )
{
const PaDeviceInfo* info = Pa_GetDeviceInfo(i);
if (info && (DeviceName(info) == devName) && (info->maxOutputChannels > 0))
if (info && (DeviceName(info) == devName) &&
HostName(info) == hostName && (info->maxOutputChannels > 0))
{
// this device name matches the stored one, and works.
// So we say this is the answer and return it
@ -2379,9 +2386,10 @@ wxString AudioIO::GetDeviceInfo()
}
wxString name = DeviceName(info);
wxString hostName = gPrefs->Read(wxT("/AudioIO/Host"), wxT(""));
s << wxT("Device ID: ") << j << e;
s << wxT("Device name: ") << name << e;
s << wxT("Host name: ") << hostName << e;
s << wxT("Input channels: ") << info->maxInputChannels << e;
s << wxT("Output channels: ") << info->maxOutputChannels << e;
s << wxT("Low Input Latency: ") << info->defaultLowInputLatency << e;

View File

@ -49,6 +49,7 @@ extern AUDACITY_DLL_API AudioIO *gAudioIO;
void InitAudioIO();
void DeinitAudioIO();
wxString DeviceName(const PaDeviceInfo* info);
wxString HostName(const PaDeviceInfo* info);
bool ValidateDeviceNames();
class AUDACITY_DLL_API AudioIOListener {

View File

@ -76,10 +76,9 @@ void DeviceToolBar::RecreateTipWindows()
static wxString MakeDeviceSourceString(DeviceSourceMap *map)
{
wxString ret;
if (map->totalSources <= 1)
ret = map->deviceString;
else
ret = map->deviceString + wxString(": ", wxConvLocal) + map->sourceString;
ret = map->deviceString;
if (map->totalSources > 1)
ret += wxString(": ", wxConvLocal) + map->sourceString;
return ret;
}
@ -96,20 +95,30 @@ static int DummyPaStreamCallback(
return 0;
}
static void AddSourcesFromStream(int deviceIndex, wxString &devName, wxArrayString *descs, std::vector<DeviceSourceMap> *maps, PaStream *stream)
static void FillHostDeviceInfo(DeviceSourceMap *map, const PaDeviceInfo *info, int deviceIndex)
{
wxString hostapiName(Pa_GetHostApiInfo(info->hostApi)->name, wxConvLocal);
wxString infoName(info->name, wxConvLocal);
map->deviceIndex = deviceIndex;
map->hostIndex = info->hostApi;
map->deviceString = infoName;
map->hostString = hostapiName;
map->numChannels = info->maxInputChannels;
}
static void AddSourcesFromStream(int deviceIndex, const PaDeviceInfo *info, std::vector<DeviceSourceMap> *maps, PaStream *stream)
{
int i;
PxMixer *portMixer;
DeviceSourceMap map;
map.deviceIndex = deviceIndex;
map.sourceIndex = -1;
map.deviceString = devName;
map.totalSources = 0;
FillHostDeviceInfo(&map, info, deviceIndex);
portMixer = Px_OpenMixer(stream, 0);
if (!portMixer) {
maps->push_back(map);
descs->Add(MakeDeviceSourceString(&((*maps)[maps->size() - 1])));
return;
}
@ -123,26 +132,25 @@ static void AddSourcesFromStream(int deviceIndex, wxString &devName, wxArrayStri
if (map.totalSources <= 1) {
map.sourceIndex = 0;
maps->push_back(map);
descs->Add(MakeDeviceSourceString(&((*maps)[maps->size() - 1])));
} else {
//open up a stream with the device so portmixer can get the info out of it.
for (i = 0; i < map.totalSources; i++) {
map.sourceIndex = i;
map.sourceString = wxString(Px_GetInputSourceName(portMixer, i), wxConvLocal);
maps->push_back(map);
descs->Add(MakeDeviceSourceString(&((*maps)[maps->size() - 1])));
}
}
Px_CloseMixer(portMixer);
}
static void AddSources(int deviceIndex, int rate, wxArrayString *descs, std::vector<DeviceSourceMap> *maps, int isInput)
static void AddSources(int deviceIndex, int rate, wxArrayString *hosts, std::vector<DeviceSourceMap> *maps, int isInput)
{
int error;
DeviceSourceMap map;
wxString devName;
wxString hostDevName;
const PaDeviceInfo *info = Pa_GetDeviceInfo(deviceIndex);
devName = DeviceName(Pa_GetDeviceInfo(deviceIndex));
hostDevName = DeviceName(info);
// This tries to open the device with the samplerate worked out above, which
// will be the highest available for play and record on the device, or
// 44.1kHz if the info cannot be fetched.
@ -155,10 +163,9 @@ static void AddSources(int deviceIndex, int rate, wxArrayString *descs, std::vec
parameters.sampleFormat = paFloat32;
parameters.hostApiSpecificStreamInfo = NULL;
parameters.channelCount = 1;
if (Pa_GetDeviceInfo(deviceIndex))
parameters.suggestedLatency = isInput ?
Pa_GetDeviceInfo(deviceIndex)->defaultLowInputLatency:
Pa_GetDeviceInfo(deviceIndex)->defaultLowOutputLatency;
if (info)
parameters.suggestedLatency = isInput ? info->defaultLowInputLatency:
info->defaultLowOutputLatency;
else
parameters.suggestedLatency = DEFAULT_LATENCY_CORRECTION/1000.0;
// try opening for record and playback
@ -169,15 +176,18 @@ static void AddSources(int deviceIndex, int rate, wxArrayString *descs, std::vec
paClipOff | paDitherOff,
DummyPaStreamCallback, NULL);
if (stream) {
AddSourcesFromStream(deviceIndex, devName, descs, maps, stream);
AddSourcesFromStream(deviceIndex, info, maps, stream);
Pa_CloseStream(stream);
} else {
map.deviceIndex = deviceIndex;
map.sourceIndex = -1;
map.deviceString = devName;
map.totalSources = 0;
FillHostDeviceInfo(&map, info, deviceIndex);
maps->push_back(map);
descs->Add(MakeDeviceSourceString(&((*maps)[maps->size() - 1])));
}
//add the host to the list if it isn't there yet
wxString hostName(Pa_GetHostApiInfo(info->hostApi)->name, wxConvLocal);
if (hosts->Index(hostName) == wxNOT_FOUND) {
hosts->Add(hostName);
}
}
@ -186,6 +196,10 @@ void DeviceToolBar::Populate()
int i;
wxArrayString inputs;
wxArrayString outputs;
wxArrayString hosts;
wxArrayString channels;
channels.Add(wxT("1 (Mono)"));
int nDevices = Pa_GetDeviceCount();
@ -195,14 +209,26 @@ void DeviceToolBar::Populate()
for (i = 0; i < nDevices; i++) {
const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
if (info->maxOutputChannels > 0) {
AddSources(i, info->defaultSampleRate, &outputs, &mOutputDeviceSourceMaps, 0);
AddSources(i, info->defaultSampleRate, &hosts, &mOutputDeviceSourceMaps, 0);
}
if (info->maxInputChannels > 0) {
AddSources(i, info->defaultSampleRate, &inputs, &mInputDeviceSourceMaps, 1);
AddSources(i, info->defaultSampleRate, &hosts, &mInputDeviceSourceMaps, 1);
}
}
// Hosts
mHost = new wxChoice(this,
wxID_ANY,
wxDefaultPosition,
wxDefaultSize,
hosts);
mHost->SetName(_("Audio Host"));
Add(mHost, 0, wxALIGN_CENTER);
if (hosts.GetCount() == 0)
mHost->Enable(false);
// Output device
mPlayBitmap = new wxBitmap(theTheme.Bitmap(bmpSpeaker));
@ -234,11 +260,34 @@ void DeviceToolBar::Populate()
wxDefaultSize,
inputs);
mInput->SetName(_("Input Device"));
Add(mInput, 0, wxALIGN_CENTER);
if (inputs.GetCount() == 0)
mInput->Enable(false);
wxStaticText *channelsLabel = new wxStaticText(this, wxID_ANY, wxT("# Channels:"),
wxDefaultPosition, wxDefaultSize,
wxALIGN_LEFT);
Add(channelsLabel, 0, wxALIGN_CENTER);
mInputChannels = new wxChoice(this,
wxID_ANY,
wxDefaultPosition,
wxDefaultSize,
channels);
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),
NULL,
this);
mHost->Connect(wxEVT_KILL_FOCUS,
wxFocusEventHandler(DeviceToolBar::OnFocus),
NULL,
this);
mOutput->Connect(wxEVT_SET_FOCUS,
wxFocusEventHandler(DeviceToolBar::OnFocus),
NULL,
@ -256,7 +305,8 @@ void DeviceToolBar::Populate()
NULL,
this);
UpdatePrefs();
FillHostDevices();
FillInputChannels();
}
void DeviceToolBar::OnFocus(wxFocusEvent &event)
@ -296,17 +346,32 @@ void DeviceToolBar::OnCaptureKey(wxCommandEvent &event)
void DeviceToolBar::UpdatePrefs()
{
wxString hostName;
wxString devName;
wxString sourceName;
wxString desc;
hostName = gPrefs->Read(wxT("/AudioIO/Host"), wxT(""));
devName = gPrefs->Read(wxT("/AudioIO/RecordingDevice"), wxT(""));
sourceName = gPrefs->Read(wxT("/AudioIO/RecordingSource"), wxT(""));
if (sourceName == wxT(""))
desc = devName;
else
desc = devName + wxString(": ", wxConvLocal) + sourceName;
mInput->SetStringSelection(desc);
if (mInput->FindString(desc) != wxNOT_FOUND)
mInput->SetStringSelection(desc);
else if (mInput->GetCount()) {
//use the 0th index if we have no familiar devices
mInput->SetSelection(0);
for (size_t i = 0; i < mInputDeviceSourceMaps.size(); i++) {
if (mInputDeviceSourceMaps[i].hostString == hostName &&
MakeDeviceSourceString(&mInputDeviceSourceMaps[i]) == mInput->GetString(0)) {
SetDevices(&mInputDeviceSourceMaps[i], NULL);
break;
}
}
}
devName = gPrefs->Read(wxT("/AudioIO/PlaybackDevice"), wxT(""));
sourceName = gPrefs->Read(wxT("/AudioIO/PlaybackSource"), wxT(""));
@ -316,6 +381,22 @@ void DeviceToolBar::UpdatePrefs()
desc = devName + wxString(": ", wxConvLocal) + sourceName;
mOutput->SetStringSelection(desc);
if (mOutput->FindString(desc) != wxNOT_FOUND)
mOutput->SetStringSelection(desc);
else if (mOutput->GetCount()) {
//use the 0th index if we have no familiar devices
mOutput->SetSelection(0);
for (size_t i = 0; i < mOutputDeviceSourceMaps.size(); i++) {
if (mOutputDeviceSourceMaps[i].hostString == hostName &&
MakeDeviceSourceString(&mOutputDeviceSourceMaps[i]) == mOutput->GetString(0)) {
SetDevices(NULL, &mOutputDeviceSourceMaps[i]);
break;
}
}
}
mHost->SetStringSelection(hostName);
RegenerateTooltips();
// Set label to pull in language change
@ -330,122 +411,207 @@ void DeviceToolBar::RegenerateTooltips()
#if wxUSE_TOOLTIPS
mOutput->SetToolTip(_("Output Device"));
mInput->SetToolTip(_("Input Device"));
mHost->SetToolTip(_("Audio Host"));
#endif
}
void DeviceToolBar::FillHostDevices()
{
//read what is in the prefs
wxString host = gPrefs->Read(wxT("/AudioIO/Host"), wxT(""));
size_t i;
int foundHostIndex = -1;
for (i = 0; i < mOutputDeviceSourceMaps.size(); i++) {
if (mOutputDeviceSourceMaps[i].hostString == host) {
foundHostIndex = mOutputDeviceSourceMaps[i].hostIndex;
break;
}
}
if (foundHostIndex == -1) {
for (i = 0; i < mInputDeviceSourceMaps.size(); i++) {
if (mInputDeviceSourceMaps[i].hostString == host) {
foundHostIndex = mInputDeviceSourceMaps[i].hostIndex;
break;
}
}
}
// If no host was found based on the prefs device host, load the first available one
if (foundHostIndex == -1) {
if (mOutputDeviceSourceMaps.size())
foundHostIndex = mOutputDeviceSourceMaps[0].hostIndex;
else if (mInputDeviceSourceMaps.size())
foundHostIndex = mInputDeviceSourceMaps[0].hostIndex;
}
// If we still have no host it means no devices, in which case do nothing.
if (foundHostIndex == -1)
return;
// Repopulate the Input/Output device list available to the user
mInput->Clear();
for (i = 0; i < mInputDeviceSourceMaps.size(); i++) {
if (foundHostIndex == mInputDeviceSourceMaps[i].hostIndex)
mInput->Append(MakeDeviceSourceString(&mInputDeviceSourceMaps[i]));
}
mInput->Enable(mInput->GetCount() ? true : false);
mInput->SetSize(mInput->GetBestFittingSize());
// mInput->Layout();
mOutput->Clear();
for (i = 0; i < mOutputDeviceSourceMaps.size(); i++) {
if (foundHostIndex == mOutputDeviceSourceMaps[i].hostIndex)
mOutput->Append(MakeDeviceSourceString(&mOutputDeviceSourceMaps[i]));
}
mOutput->Enable(mOutput->GetCount() ? true : false);
mOutput->SetSize(mOutput->GetBestFittingSize());
// mOutput->Layout();
// make the device display selection reflect the prefs if they exist
UpdatePrefs();
Layout();
this->Refresh();
Update();
// The setting of the Device is left up to OnChoice
}
//return 1 if host changed, 0 otherwise.
int DeviceToolBar::ChangeHost()
{
int hostSelectionIndex;
hostSelectionIndex = mHost->GetSelection();
wxString oldHost = gPrefs->Read(wxT("/AudioIO/Host"), wxT(""));
wxString newHost = hostSelectionIndex >= 0 ? mHost->GetString(mHost->GetSelection()) :
oldHost;
if (oldHost == newHost)
return 0;
//change the host and switch to correct devices.
gPrefs->Write(wxT("/AudioIO/Host"), newHost);
FillHostDevices();
return 1;
}
void DeviceToolBar::FillInputChannels()
{
wxString host = gPrefs->Read(wxT("/AudioIO/Host"), wxT(""));
wxString device = gPrefs->Read(wxT("/AudioIO/RecordingDevice"), wxT(""));
wxString source = gPrefs->Read(wxT("/AudioIO/RecordingSource"), wxT(""));
long oldChannels = 1, newChannels;
gPrefs->Read(wxT("/AudioIO/RecordChannels"), &oldChannels);
int index = -1;
size_t i, j;
mInputChannels->Clear();
for (i = 0; i < mInputDeviceSourceMaps.size(); i++) {
if (source == mInputDeviceSourceMaps[i].sourceString &&
device == mInputDeviceSourceMaps[i].deviceString &&
host == mInputDeviceSourceMaps[i].hostString) {
// add one selection for each channel of this source
for (j = 0; j < mInputDeviceSourceMaps[i].numChannels; j++) {
wxString name;
if (j == 0) {
name = _("1 (Mono)");
}
else if (j == 1) {
name = _("2 (Stereo)");
}
else {
name = wxString::Format(wxT("%d"), j + 1);
}
mInputChannels->Append(name);
}
newChannels = mInputDeviceSourceMaps[i].numChannels;
if (oldChannels < newChannels && oldChannels >= 1)
newChannels = oldChannels;
mInputChannels->SetSelection(newChannels - 1);
gPrefs->Write(wxT("/AudioIO/RecordChannels"), newChannels);
mInputChannels->Enable(mInputChannels->GetCount() ? true : false);
index = i;
break;
}
}
if (index == -1)
mInputChannels->Enable(false);
}
void DeviceToolBar::SetDevices(DeviceSourceMap *in, DeviceSourceMap *out)
{
if (in) {
gPrefs->Write(wxT("/AudioIO/RecordingDevice"), in->deviceString);
gPrefs->Write(wxT("/AudioIO/RecordingSourceIndex"), in->sourceIndex);
if (in->sourceIndex >= 0) {
gPrefs->Write(wxT("/AudioIO/RecordingSource"),in->sourceString);
} else
gPrefs->Write(wxT("/AudioIO/RecordingSource"), wxT(""));
FillInputChannels();
}
if (out) {
gPrefs->Write(wxT("/AudioIO/PlaybackDevice"), out->deviceString);
if (out->sourceIndex >= 0) {
gPrefs->Write(wxT("/AudioIO/PlaybackSource"), out->sourceString);
} else
gPrefs->Write(wxT("/AudioIO/RecordingSource"), wxT(""));
}
}
void DeviceToolBar::OnChoice(wxCommandEvent &event)
{
int inputSelectionIndex;
int outputSelectionIndex;
int channelsSelectionIndex;
inputSelectionIndex = mInput->GetSelection();
outputSelectionIndex = mOutput->GetSelection();
//if we've changed hosts, we've handled the device switching already.
if (!ChangeHost()) {
inputSelectionIndex = mInput->GetSelection();
outputSelectionIndex = mOutput->GetSelection();
channelsSelectionIndex = mInputChannels->GetSelection();
wxString oldInput = gPrefs->Read(wxT("/AudioIO/RecordingDevice"), wxT(""));
wxString newInput = inputSelectionIndex >= 0 ?
mInputDeviceSourceMaps[inputSelectionIndex].deviceString:
oldInput;
wxString oldOutput = gPrefs->Read(wxT("/AudioIO/PlaybackDevice"), wxT(""));
wxString newOutput = outputSelectionIndex >= 0 ?
mOutputDeviceSourceMaps[outputSelectionIndex].deviceString:
oldOutput;
int oldInIndex = -1, newInIndex = -1, oldOutIndex = -1, newOutIndex = -1;
int nDevices = Pa_GetDeviceCount();
int i;
bool foundCompatibleDevice = false;
// Find device indices for input and output
for (i = 0; i < nDevices; ++i)
{
const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
wxString name = DeviceName(info);
if (name == oldInput) oldInIndex = i;
if (name == newInput) newInIndex = i;
if (name == oldOutput) oldOutIndex = i;
if (name == newOutput) newOutIndex = i;
}
// This shouldn't happen for new choices (it's OK for old ones)
if (newInIndex < 0 || newOutIndex < 0)
{
wxLogDebug(wxT("DeviceToolBar::OnChoice(): couldn't find device indices"));
return;
}
const PaDeviceInfo *inInfo = Pa_GetDeviceInfo(newInIndex);
const PaDeviceInfo *outInfo = Pa_GetDeviceInfo(newOutIndex);
if (oldInIndex != newInIndex)
{
// We changed input; be sure the output device has the same API
if (inInfo->hostApi != outInfo->hostApi) {
// First try setting the same device as the input
// I think it is okay to set the string selection as devicename
// because I *believe* that the input sources only refer to inputs
// but if we end up with blanks in the combobox post selection due
// to api mismatch, then this needs to change.
if (!mOutput->SetStringSelection(DeviceName(inInfo)))
{
// Not found; set output device to default for the API
const PaHostApiInfo *apiInfo = Pa_GetHostApiInfo(inInfo->hostApi);
outInfo = Pa_GetDeviceInfo(apiInfo->defaultOutputDevice);
mOutput->SetStringSelection(DeviceName(outInfo));
}
if (channelsSelectionIndex >= 0) {
gPrefs->Write(wxT("/AudioIO/RecordChannels"),
channelsSelectionIndex + 1);
}
}
else if (oldOutIndex != newOutIndex)
{
// We changed output; be sure the input device has the same API
if (outInfo->hostApi != inInfo->hostApi) {
// First try setting the same device as the output
for (i = 0; i < (int)mInputDeviceSourceMaps.size(); i++) {
if (mInputDeviceSourceMaps[i].deviceString == DeviceName(outInfo)) {
mInput->SetStringSelection(MakeDeviceSourceString(&mInputDeviceSourceMaps[i]));
foundCompatibleDevice = true;
break;
}
}
if (!foundCompatibleDevice) {
// Not found; set input device to default for the API
const PaHostApiInfo *apiInfo = Pa_GetHostApiInfo(outInfo->hostApi);
inInfo = Pa_GetDeviceInfo(apiInfo->defaultInputDevice);
for (i = 0; i < (int)mInputDeviceSourceMaps.size(); i++) {
if (mInputDeviceSourceMaps[i].deviceString == DeviceName(inInfo)) {
break;
}
}
mInput->SetStringSelection(MakeDeviceSourceString(&mInputDeviceSourceMaps[i]));
}
wxString host = gPrefs->Read(wxT("/AudioIO/Host"), wxT(""));
wxString oldInput = gPrefs->Read(wxT("/AudioIO/RecordingDevice"), wxT(""));
wxString newInput = inputSelectionIndex >= 0 ?
MakeDeviceSourceString(&mInputDeviceSourceMaps[inputSelectionIndex]):
oldInput;
wxString oldOutput = gPrefs->Read(wxT("/AudioIO/PlaybackDevice"), wxT(""));
wxString newOutput = outputSelectionIndex >= 0 ?
MakeDeviceSourceString(&mOutputDeviceSourceMaps[outputSelectionIndex]):
oldOutput;
int newInIndex = -1, newOutIndex = -1;
size_t i;
// Find device indices for input and output
for (i = 0; i < mInputDeviceSourceMaps.size(); ++i) {
wxString name;
name = MakeDeviceSourceString(&mInputDeviceSourceMaps[i]);
if (name == newInput && mInputDeviceSourceMaps[i].hostString == host)
newInIndex = i;
}
for (i = 0; i < mOutputDeviceSourceMaps.size(); ++i) {
wxString name;
name = MakeDeviceSourceString(&mOutputDeviceSourceMaps[i]);
if (name == newOutput && mOutputDeviceSourceMaps[i].hostString == host)
newOutIndex = i;
}
// This shouldn't happen for new choices (it's OK for old ones)
if (newInIndex < 0 || newOutIndex < 0) {
wxLogDebug(wxT("DeviceToolBar::OnChoice(): couldn't find device indices"));
return;
}
SetDevices(&mInputDeviceSourceMaps[newInIndex], &mOutputDeviceSourceMaps[newOutIndex]);
}
inputSelectionIndex = mInput->GetSelection();
outputSelectionIndex = mOutput->GetSelection();
gPrefs->Write(wxT("/AudioIO/Host"),
wxString(Pa_GetHostApiInfo(inInfo->hostApi)->name, wxConvLocal));
if (inputSelectionIndex >= 0) {
gPrefs->Write(wxT("/AudioIO/RecordingDevice"),
mInputDeviceSourceMaps[inputSelectionIndex].deviceString);
gPrefs->Write(wxT("/AudioIO/RecordingSourceIndex"),
mInputDeviceSourceMaps[inputSelectionIndex].sourceIndex);
if (mInputDeviceSourceMaps[inputSelectionIndex].sourceIndex >= 0) {
gPrefs->Write(wxT("/AudioIO/RecordingSource"),
mInputDeviceSourceMaps[inputSelectionIndex].sourceString);
} else
gPrefs->Write(wxT("/AudioIO/RecordingSource"), wxT(""));
}
if (outputSelectionIndex >= 0) {
gPrefs->Write(wxT("/AudioIO/PlaybackDevice"),
mOutputDeviceSourceMaps[outputSelectionIndex].deviceString);
if (mOutputDeviceSourceMaps[outputSelectionIndex].sourceIndex >= 0) {
gPrefs->Write(wxT("/AudioIO/PlaybackSource"),
mOutputDeviceSourceMaps[outputSelectionIndex].sourceString);
} else
gPrefs->Write(wxT("/AudioIO/RecordingSource"), wxT(""));
}
if (gAudioIO)
gAudioIO->HandleDeviceChange();
GetActiveProject()->UpdatePrefs();

View File

@ -22,9 +22,12 @@ class wxChoice;
typedef struct DeviceSourceMap {
int deviceIndex;
int sourceIndex;
int hostIndex;
int totalSources;
int numChannels;
wxString sourceString;
wxString deviceString;
wxString hostString;
} DeviceSourceMap;
class DeviceToolBar:public ToolBar {
@ -49,6 +52,10 @@ class DeviceToolBar:public ToolBar {
void OnChoice(wxCommandEvent & event);
private:
int ChangeHost();
void FillHostDevices();
void FillInputChannels();
void SetDevices(DeviceSourceMap *in, DeviceSourceMap *out);
void RegenerateTooltips();
wxBitmap *mPlayBitmap;
@ -56,6 +63,8 @@ class DeviceToolBar:public ToolBar {
wxChoice *mInput;
wxChoice *mOutput;
wxChoice *mInputChannels;
wxChoice *mHost;
std::vector<DeviceSourceMap> mInputDeviceSourceMaps;
std::vector<DeviceSourceMap> mOutputDeviceSourceMaps;