diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index bf6452e48..022217bcd 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -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; diff --git a/src/AudioIO.h b/src/AudioIO.h index e8f6dcf63..61b43d207 100644 --- a/src/AudioIO.h +++ b/src/AudioIO.h @@ -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 { diff --git a/src/toolbars/DeviceToolBar.cpp b/src/toolbars/DeviceToolBar.cpp index d88856b9f..9ed12e62b 100644 --- a/src/toolbars/DeviceToolBar.cpp +++ b/src/toolbars/DeviceToolBar.cpp @@ -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 *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 *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 *maps, int isInput) +static void AddSources(int deviceIndex, int rate, wxArrayString *hosts, std::vector *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(); diff --git a/src/toolbars/DeviceToolBar.h b/src/toolbars/DeviceToolBar.h index 3faf3560d..dbf6a6fcf 100644 --- a/src/toolbars/DeviceToolBar.h +++ b/src/toolbars/DeviceToolBar.h @@ -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 mInputDeviceSourceMaps; std::vector mOutputDeviceSourceMaps;