mirror of
https://github.com/cookiengineer/audacity
synced 2025-10-18 00:21:18 +02:00
re-add and update device preferences to match new device model.
also restores portaudio device defaults functionality when the device can't be found.
This commit is contained in:
@@ -57,6 +57,46 @@ std::vector<DeviceSourceMap> &DeviceManager::GetOutputDeviceMaps()
|
||||
return mOutputDeviceSourceMaps;
|
||||
}
|
||||
|
||||
|
||||
wxString MakeDeviceSourceString(DeviceSourceMap *map)
|
||||
{
|
||||
wxString ret;
|
||||
ret = map->deviceString;
|
||||
if (map->totalSources > 1)
|
||||
ret += wxString(": ", wxConvLocal) + map->sourceString;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DeviceSourceMap* DeviceManager::GetDefaultDevice(int hostIndex, int isInput)
|
||||
{
|
||||
if (hostIndex < 0 || hostIndex >= Pa_GetHostApiCount()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct PaHostApiInfo *apiinfo = Pa_GetHostApiInfo(hostIndex); // get info on API
|
||||
std::vector<DeviceSourceMap> & maps = isInput ? mInputDeviceSourceMaps : mOutputDeviceSourceMaps;
|
||||
size_t i;
|
||||
int targetDevice = isInput ? apiinfo->defaultInputDevice : apiinfo->defaultOutputDevice;
|
||||
|
||||
for (i = 0; i < maps.size(); i++) {
|
||||
if (maps[i].deviceIndex == targetDevice)
|
||||
return &maps[i];
|
||||
}
|
||||
|
||||
wxLogDebug(wxT("GetDefaultDevice() no default device"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DeviceSourceMap* DeviceManager::GetDefaultOutputDevice(int hostIndex)
|
||||
{
|
||||
return GetDefaultDevice(hostIndex, 0);
|
||||
}
|
||||
DeviceSourceMap* DeviceManager::GetDefaultInputDevice(int hostIndex)
|
||||
{
|
||||
return GetDefaultDevice(hostIndex, 1);
|
||||
}
|
||||
|
||||
//--------------- Device Enumeration --------------------------
|
||||
|
||||
//Port Audio requires we open the stream with a callback or a lot of devices will fail
|
||||
|
@@ -32,6 +32,8 @@ typedef struct DeviceSourceMap {
|
||||
wxString hostString;
|
||||
} DeviceSourceMap;
|
||||
|
||||
wxString MakeDeviceSourceString(DeviceSourceMap *map);
|
||||
|
||||
class DeviceManager
|
||||
{
|
||||
public:
|
||||
@@ -45,6 +47,9 @@ class DeviceManager
|
||||
/// Assumes that DeviceManager is only used on the main thread.
|
||||
void Rescan();
|
||||
|
||||
DeviceSourceMap* GetDefaultOutputDevice(int hostIndex);
|
||||
DeviceSourceMap* GetDefaultInputDevice(int hostIndex);
|
||||
|
||||
std::vector<DeviceSourceMap> &GetInputDeviceMaps();
|
||||
std::vector<DeviceSourceMap> &GetOutputDeviceMaps();
|
||||
|
||||
@@ -56,6 +61,8 @@ class DeviceManager
|
||||
/// Called by GetInputDeviceMaps and GetOutputDeviceMaps when needed.
|
||||
void Init();
|
||||
|
||||
DeviceSourceMap* GetDefaultDevice(int hostIndex, int isInput);
|
||||
|
||||
bool m_inited;
|
||||
|
||||
std::vector<DeviceSourceMap> mInputDeviceSourceMaps;
|
||||
|
@@ -36,6 +36,7 @@ other settings.
|
||||
#include "../Internat.h"
|
||||
#include "../Prefs.h"
|
||||
#include "../ShuttleGui.h"
|
||||
#include "../DeviceManager.h"
|
||||
|
||||
#include "DevicePrefs.h"
|
||||
|
||||
@@ -69,6 +70,7 @@ void DevicePrefs::Populate()
|
||||
// Get current setting for devices
|
||||
mPlayDevice = gPrefs->Read(wxT("/AudioIO/PlaybackDevice"), wxT(""));
|
||||
mRecordDevice = gPrefs->Read(wxT("/AudioIO/RecordingDevice"), wxT(""));
|
||||
mRecordSource = gPrefs->Read(wxT("/AudioIO/RecordingSource"), wxT(""));
|
||||
mRecordChannels = gPrefs->Read(wxT("/AudioIO/RecordChannels"), 2L);
|
||||
|
||||
//------------------------- Main section --------------------
|
||||
@@ -187,37 +189,42 @@ void DevicePrefs::OnHost(wxCommandEvent & e)
|
||||
mHost->SetSelection(0);
|
||||
}
|
||||
|
||||
mPlay->Clear();
|
||||
mRecord->Clear();
|
||||
std::vector<DeviceSourceMap> &inMaps = DeviceManager::Instance()->GetInputDeviceMaps();
|
||||
std::vector<DeviceSourceMap> &outMaps = DeviceManager::Instance()->GetOutputDeviceMaps();
|
||||
|
||||
wxArrayString playnames;
|
||||
wxArrayString recordnames;
|
||||
|
||||
size_t i;
|
||||
int devindex; /* temp variable to hold the numeric ID of each device in turn */
|
||||
wxString device;
|
||||
wxString recDevice;
|
||||
|
||||
for (int i = 0; i < nDevices; i++) {
|
||||
const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
|
||||
if (info->hostApi == index) { /* if the device is for the current HostAPI */
|
||||
wxString name(info->name, wxConvLocal);
|
||||
wxString device = DeviceName(info);
|
||||
recDevice = mRecordDevice;
|
||||
if (this->mRecordSource != wxT(""))
|
||||
recDevice += wxString(": ", wxConvLocal) + mRecordSource;
|
||||
|
||||
|
||||
if (info->maxOutputChannels > 0) {
|
||||
playnames.Add(name);
|
||||
devindex = mPlay->Append(name, (void *) info);
|
||||
if (device == mPlayDevice) { /* if this is the default device, select it */
|
||||
mPlay->SetSelection(devindex);
|
||||
}
|
||||
}
|
||||
|
||||
if (info->maxInputChannels > 0) {
|
||||
recordnames.Add(name);
|
||||
devindex = mRecord->Append(name, (void *) info);
|
||||
if (device == mRecordDevice) {
|
||||
mRecord->Clear();
|
||||
for (i = 0; i < inMaps.size(); i++) {
|
||||
if (index == inMaps[i].hostIndex) {
|
||||
device = MakeDeviceSourceString(&inMaps[i]);
|
||||
devindex = mRecord->Append(device);
|
||||
mRecord->SetClientData(devindex, &inMaps[i]);
|
||||
if (device == recDevice) { /* if this is the default device, select it */
|
||||
mRecord->SetSelection(devindex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mPlay->Clear();
|
||||
for (i = 0; i < outMaps.size(); i++) {
|
||||
if (index == outMaps[i].hostIndex) {
|
||||
device = MakeDeviceSourceString(&outMaps[i]);
|
||||
devindex = mPlay->Append(device);
|
||||
mPlay->SetClientData(devindex, &outMaps[i]);
|
||||
if (device == mPlayDevice) { /* if this is the default device, select it */
|
||||
mPlay->SetSelection(devindex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* deal with not having any devices at all */
|
||||
@@ -236,8 +243,9 @@ void DevicePrefs::OnHost(wxCommandEvent & e)
|
||||
* this API, as defined by PortAudio. We then fall back to using 0 only if
|
||||
* that fails */
|
||||
if (mPlay->GetCount() && mPlay->GetSelection() == wxNOT_FOUND) {
|
||||
wxLogDebug(wxT("DevicePrefs::OnHost(): no play device selected"));
|
||||
mPlay->SetStringSelection(GetDefaultPlayDevice(index));
|
||||
DeviceSourceMap *defaultMap = DeviceManager::Instance()->GetDefaultOutputDevice(index);
|
||||
if (defaultMap)
|
||||
mPlay->SetStringSelection(MakeDeviceSourceString(defaultMap));
|
||||
|
||||
if (mPlay->GetSelection() == wxNOT_FOUND) {
|
||||
mPlay->SetSelection(0);
|
||||
@@ -245,8 +253,9 @@ void DevicePrefs::OnHost(wxCommandEvent & e)
|
||||
}
|
||||
|
||||
if (mRecord->GetCount() && mRecord->GetSelection() == wxNOT_FOUND) {
|
||||
wxLogDebug(wxT("DevicePrefs::OnHost(): no record device selected"));
|
||||
mRecord->SetStringSelection(GetDefaultRecordDevice(index));
|
||||
DeviceSourceMap *defaultMap = DeviceManager::Instance()->GetDefaultInputDevice(index);
|
||||
if (defaultMap)
|
||||
mRecord->SetStringSelection(MakeDeviceSourceString(defaultMap));
|
||||
|
||||
if (mPlay->GetSelection() == wxNOT_FOUND) {
|
||||
mPlay->SetSelection(0);
|
||||
@@ -254,8 +263,8 @@ void DevicePrefs::OnHost(wxCommandEvent & e)
|
||||
}
|
||||
|
||||
ShuttleGui S(this, eIsCreating);
|
||||
S.SetSizeHints(mPlay, playnames);
|
||||
S.SetSizeHints(mRecord, recordnames);
|
||||
S.SetSizeHints(mPlay, mPlay->GetStrings());
|
||||
S.SetSizeHints(mRecord, mRecord->GetStrings());
|
||||
OnDevice(e);
|
||||
}
|
||||
|
||||
@@ -269,9 +278,9 @@ void DevicePrefs::OnDevice(wxCommandEvent & e)
|
||||
int sel = mChannels->GetSelection();
|
||||
int cnt = 0;
|
||||
|
||||
const PaDeviceInfo *info = (const PaDeviceInfo *) mRecord->GetClientData(ndx);
|
||||
if (info != NULL) {
|
||||
cnt = info->maxInputChannels;
|
||||
DeviceSourceMap *inMap = (DeviceSourceMap *) mRecord->GetClientData(ndx);
|
||||
if (inMap != NULL) {
|
||||
cnt = inMap->numChannels;
|
||||
}
|
||||
|
||||
if (sel != wxNOT_FOUND) {
|
||||
@@ -324,67 +333,36 @@ void DevicePrefs::OnDevice(wxCommandEvent & e)
|
||||
Layout();
|
||||
}
|
||||
|
||||
wxString DevicePrefs::GetDefaultPlayDevice(int index)
|
||||
{
|
||||
if (index < 0 || index >= Pa_GetHostApiCount()) {
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
const struct PaHostApiInfo *apiinfo = Pa_GetHostApiInfo(index); // get info on API
|
||||
wxLogDebug(wxT("GetDefaultPlayDevice(): HostAPI index %d, name %s"), index, wxString(apiinfo->name, wxConvLocal).c_str());
|
||||
wxLogDebug(wxT("GetDefaultPlayDevice() default output %d"), apiinfo->defaultOutputDevice);
|
||||
const PaDeviceInfo* devinfo = Pa_GetDeviceInfo(apiinfo->defaultOutputDevice);
|
||||
if (devinfo == NULL) {
|
||||
wxLogDebug(wxT("GetDefaultPlayDevice() no default output device"));
|
||||
return wxString("", wxConvLocal);
|
||||
}
|
||||
wxString name(devinfo->name, wxConvLocal);
|
||||
wxLogDebug(wxT("GetDefaultPlayDevice() default output device name %s"), name.c_str());
|
||||
return name;
|
||||
}
|
||||
|
||||
wxString DevicePrefs::GetDefaultRecordDevice(int index)
|
||||
{
|
||||
if (index < 0 || index >= Pa_GetHostApiCount()) {
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
const struct PaHostApiInfo *apiinfo = Pa_GetHostApiInfo(index); // get info on API
|
||||
wxLogDebug(wxT("GetDefaultRecordDevice(): HostAPI index %d, name %s"), index, wxString(apiinfo->name, wxConvLocal).c_str());
|
||||
wxLogDebug(wxT("GetDefaultRecordDevice() default input %d"), apiinfo->defaultInputDevice);
|
||||
const PaDeviceInfo* devinfo = Pa_GetDeviceInfo(apiinfo->defaultInputDevice);
|
||||
if (devinfo == NULL) {
|
||||
wxLogDebug(wxT("GetDefaultRecordDevice() no default input device"));
|
||||
return wxString("", wxConvLocal);
|
||||
}
|
||||
wxString name(devinfo->name, wxConvLocal);
|
||||
wxLogDebug(wxT("GetDefaultRecordDevice() default input device name %s"), name.c_str());
|
||||
return name;
|
||||
}
|
||||
|
||||
bool DevicePrefs::Apply()
|
||||
{
|
||||
ShuttleGui S(this, eIsSavingToPrefs);
|
||||
PopulateOrExchange(S);
|
||||
|
||||
const PaDeviceInfo *info = NULL;
|
||||
DeviceSourceMap *map = NULL;
|
||||
|
||||
if (mPlay->GetCount() > 0) {
|
||||
info = (const PaDeviceInfo *) mPlay->GetClientData(
|
||||
map = (DeviceSourceMap *) mPlay->GetClientData(
|
||||
mPlay->GetSelection());
|
||||
}
|
||||
if (info) {
|
||||
gPrefs->Write(wxT("/AudioIO/PlaybackDevice"),
|
||||
DeviceName(info));
|
||||
if (map) {
|
||||
gPrefs->Write(wxT("/AudioIO/PlaybackDevice"), map->deviceString);
|
||||
}
|
||||
|
||||
info = NULL;
|
||||
map = NULL;
|
||||
if (mRecord->GetCount() > 0) {
|
||||
info = (const PaDeviceInfo *) mRecord->GetClientData(mRecord->GetSelection());
|
||||
map = (DeviceSourceMap *) mRecord->GetClientData(mRecord->GetSelection());
|
||||
}
|
||||
if (info) {
|
||||
if (map) {
|
||||
gPrefs->Write(wxT("/AudioIO/RecordingDevice"),
|
||||
DeviceName(info));
|
||||
map->deviceString);
|
||||
gPrefs->Write(wxT("/AudioIO/RecordingSourceIndex"),
|
||||
map->sourceIndex);
|
||||
if (map->totalSources >= 1) {
|
||||
gPrefs->Write(wxT("/AudioIO/RecordingSource"),
|
||||
map->sourceString);
|
||||
} else {
|
||||
gPrefs->Write(wxT("/AudioIO/RecordingSource"),
|
||||
wxT(""));
|
||||
}
|
||||
|
||||
gPrefs->Write(wxT("/AudioIO/RecordChannels"),
|
||||
mChannels->GetSelection() + 1);
|
||||
@@ -392,15 +370,3 @@ bool DevicePrefs::Apply()
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
|
||||
// version control system. Please do not modify past this point.
|
||||
//
|
||||
// Local Variables:
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
//
|
||||
// vim: et sts=3 sw=3
|
||||
// arch-tag: d6904b91-a320-4194-8d60-caa9175b6bb4
|
||||
|
@@ -38,22 +38,12 @@ class DevicePrefs:public PrefsPanel
|
||||
void OnHost(wxCommandEvent & e);
|
||||
void OnDevice(wxCommandEvent & e);
|
||||
|
||||
/* @return The default playback device name for the selected HostAPI
|
||||
*
|
||||
* Created so we can set a default that respects the user's choice of API,
|
||||
* unlike Pa_GetDefaultOutputDevice() which always returns the default
|
||||
* device in the default API.
|
||||
* @param index Which HostAPI in the lists mHostNames / mHostIndexes /
|
||||
* mHostLabels the user has selected.
|
||||
*/
|
||||
wxString GetDefaultPlayDevice(int index);
|
||||
wxString GetDefaultRecordDevice(int index);
|
||||
|
||||
wxArrayString mHostNames;
|
||||
wxArrayString mHostLabels;
|
||||
|
||||
wxString mPlayDevice;
|
||||
wxString mRecordDevice;
|
||||
wxString mRecordSource;
|
||||
long mRecordChannels;
|
||||
|
||||
wxChoice *mHost;
|
||||
|
@@ -43,6 +43,7 @@
|
||||
#include "PrefsPanel.h"
|
||||
|
||||
#include "BatchPrefs.h"
|
||||
#include "DevicePrefs.h"
|
||||
#include "DirectoriesPrefs.h"
|
||||
#include "EffectsPrefs.h"
|
||||
#include "GUIPrefs.h"
|
||||
@@ -88,6 +89,7 @@ PrefsDialog::PrefsDialog(wxWindow * parent)
|
||||
|
||||
wxWindow *w;
|
||||
// Parameters are: AppPage( page, name, IsSelected, imageId)
|
||||
w = new DevicePrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0);
|
||||
w = new PlaybackPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0);
|
||||
w = new RecordingPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0);
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
|
@@ -80,16 +80,6 @@ void DeviceToolBar::RecreateTipWindows()
|
||||
{
|
||||
}
|
||||
|
||||
static wxString MakeDeviceSourceString(DeviceSourceMap *map)
|
||||
{
|
||||
wxString ret;
|
||||
ret = map->deviceString;
|
||||
if (map->totalSources > 1)
|
||||
ret += wxString(": ", wxConvLocal) + map->sourceString;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DeviceToolBar::DeinitChildren()
|
||||
{
|
||||
mPlayBitmap = NULL;
|
||||
@@ -264,7 +254,14 @@ void DeviceToolBar::UpdatePrefs()
|
||||
for (size_t i = 0; i < inMaps.size(); i++) {
|
||||
if (inMaps[i].hostString == hostName &&
|
||||
MakeDeviceSourceString(&inMaps[i]) == mInput->GetString(0)) {
|
||||
// use the default. It should exist but check just in case, falling back on the 0 index.
|
||||
DeviceSourceMap *defaultMap = DeviceManager::Instance()->GetDefaultInputDevice(inMaps[i].hostIndex);
|
||||
if (defaultMap) {
|
||||
mInput->SetStringSelection(MakeDeviceSourceString(defaultMap));
|
||||
SetDevices(defaultMap, NULL);
|
||||
} else {
|
||||
SetDevices(&inMaps[i], NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -288,7 +285,14 @@ void DeviceToolBar::UpdatePrefs()
|
||||
for (size_t i = 0; i < outMaps.size(); i++) {
|
||||
if (outMaps[i].hostString == hostName &&
|
||||
MakeDeviceSourceString(&outMaps[i]) == mOutput->GetString(0)) {
|
||||
// use the default. It should exist but check just in case, falling back on the 0 index.
|
||||
DeviceSourceMap *defaultMap = DeviceManager::Instance()->GetDefaultOutputDevice(inMaps[i].hostIndex);
|
||||
if (defaultMap) {
|
||||
mOutput->SetStringSelection(MakeDeviceSourceString(defaultMap));
|
||||
SetDevices(NULL, defaultMap);
|
||||
} else {
|
||||
SetDevices(NULL, &outMaps[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user