Audacity  3.0.3
Classes | Namespaces | Functions
DeviceManager.cpp File Reference
#include "DeviceManager.h"
#include <wx/log.h>
#include <thread>
#include "portaudio.h"
#include "AudioIOBase.h"
#include "DeviceChange.h"
Include dependency graph for DeviceManager.cpp:

Go to the source code of this file.

Classes

struct  anonymous_namespace{DeviceManager.cpp}::MyEvent
 

Namespaces

 anonymous_namespace{DeviceManager.cpp}
 

Functions

 wxDEFINE_EVENT (EVT_RESCANNED_DEVICES, wxEvent)
 
wxString MakeDeviceSourceString (const DeviceSourceMap *map)
 
static int DummyPaStreamCallback (const void *WXUNUSED(input), void *WXUNUSED(output), unsigned long WXUNUSED(frameCount), const PaStreamCallbackTimeInfo *WXUNUSED(timeInfo), PaStreamCallbackFlags WXUNUSED(statusFlags), void *WXUNUSED(userData))
 
static void FillHostDeviceInfo (DeviceSourceMap *map, const PaDeviceInfo *info, int deviceIndex, int isInput)
 
static void AddSourcesFromStream (int deviceIndex, const PaDeviceInfo *info, std::vector< DeviceSourceMap > *maps, PaStream *stream)
 
static bool IsInputDeviceAMapperDevice (const PaDeviceInfo *info)
 
static void AddSources (int deviceIndex, int rate, std::vector< DeviceSourceMap > *maps, int isInput)
 

Function Documentation

◆ AddSources()

static void AddSources ( int  deviceIndex,
int  rate,
std::vector< DeviceSourceMap > *  maps,
int  isInput 
)
static

Definition at line 182 of file DeviceManager.cpp.

183 {
184  int error = 0;
185  DeviceSourceMap map;
186  const PaDeviceInfo *info = Pa_GetDeviceInfo(deviceIndex);
187 
188  // This tries to open the device with the samplerate worked out above, which
189  // will be the highest available for play and record on the device, or
190  // 44.1kHz if the info cannot be fetched.
191 
192  PaStream *stream = NULL;
193 
194  PaStreamParameters parameters;
195 
196  parameters.device = deviceIndex;
197  parameters.sampleFormat = paFloat32;
198  parameters.hostApiSpecificStreamInfo = NULL;
199  parameters.channelCount = 1;
200 
201  // If the device is for input, open a stream so we can use portmixer to query
202  // the number of inputs. We skip this for outputs because there are no 'sources'
203  // and some platforms (e.g. XP) have the same device for input and output, (while
204  // Vista/Win7 separate these into two devices with the same names (but different
205  // portaudio indices)
206  // Also, for mapper devices we don't want to keep any sources, so check for it here
207  if (isInput && !IsInputDeviceAMapperDevice(info)) {
208  if (info)
209  parameters.suggestedLatency = info->defaultLowInputLatency;
210  else
211  parameters.suggestedLatency = 10.0;
212 
213  error = Pa_OpenStream(&stream,
214  &parameters,
215  NULL,
216  rate, paFramesPerBufferUnspecified,
217  paClipOff | paDitherOff,
218  DummyPaStreamCallback, NULL);
219  }
220 
221  if (stream && !error) {
222  AddSourcesFromStream(deviceIndex, info, maps, stream);
223  Pa_CloseStream(stream);
224  } else {
225  map.sourceIndex = -1;
226  map.totalSources = 0;
227  FillHostDeviceInfo(&map, info, deviceIndex, isInput);
228  maps->push_back(map);
229  }
230 
231  if(error) {
232  wxLogDebug(wxT("PortAudio stream error creating device list: ") +
233  map.hostString + wxT(":") + map.deviceString + wxT(": ") +
234  wxString(wxSafeConvertMB2WX(Pa_GetErrorText((PaError)error))));
235  }
236 }

References AddSourcesFromStream(), DeviceSourceMap::deviceString, DummyPaStreamCallback(), FillHostDeviceInfo(), DeviceSourceMap::hostString, IsInputDeviceAMapperDevice(), DeviceSourceMap::sourceIndex, and DeviceSourceMap::totalSources.

Referenced by DeviceManager::Rescan().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ AddSourcesFromStream()

static void AddSourcesFromStream ( int  deviceIndex,
const PaDeviceInfo *  info,
std::vector< DeviceSourceMap > *  maps,
PaStream stream 
)
static

Definition at line 119 of file DeviceManager.cpp.

120 {
121 #ifdef USE_PORTMIXER
122  int i;
123 #endif
124  DeviceSourceMap map;
125 
126  map.sourceIndex = -1;
127  map.totalSources = 0;
128  // Only inputs have sources, so we call FillHostDeviceInfo with a 1 to indicate this
129  FillHostDeviceInfo(&map, info, deviceIndex, 1);
130 
131 #ifdef USE_PORTMIXER
132  PxMixer *portMixer = Px_OpenMixer(stream, deviceIndex, -1, 0);
133  if (!portMixer) {
134  maps->push_back(map);
135  return;
136  }
137 
138  //if there is only one source, we don't need to concatenate the source
139  //or enumerate, because it is something meaningless like 'master'
140  //(as opposed to 'mic in' or 'line in'), and the user doesn't have any choice.
141  //note that some devices have no input sources at all but are still valid.
142  //the behavior we do is the same for 0 and 1 source cases.
143  map.totalSources = Px_GetNumInputSources(portMixer);
144 #endif
145 
146  if (map.totalSources <= 1) {
147  map.sourceIndex = 0;
148  maps->push_back(map);
149  }
150 #ifdef USE_PORTMIXER
151  else {
152  //open up a stream with the device so portmixer can get the info out of it.
153  for (i = 0; i < map.totalSources; i++) {
154  map.sourceIndex = i;
155  map.sourceString = wxString(wxSafeConvertMB2WX(Px_GetInputSourceName(portMixer, i)));
156  maps->push_back(map);
157  }
158  }
159  Px_CloseMixer(portMixer);
160 #endif
161 }

References FillHostDeviceInfo(), DeviceSourceMap::sourceIndex, DeviceSourceMap::sourceString, and DeviceSourceMap::totalSources.

Referenced by AddSources().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DummyPaStreamCallback()

static int DummyPaStreamCallback ( const void *  WXUNUSEDinput,
void *  WXUNUSEDoutput,
unsigned long   WXUNUSEDframeCount,
const PaStreamCallbackTimeInfo *  WXUNUSEDtimeInfo,
PaStreamCallbackFlags   WXUNUSEDstatusFlags,
void *  WXUNUSEDuserData 
)
static

Definition at line 97 of file DeviceManager.cpp.

103 {
104  return 0;
105 }

Referenced by AddSources().

Here is the caller graph for this function:

◆ FillHostDeviceInfo()

static void FillHostDeviceInfo ( DeviceSourceMap map,
const PaDeviceInfo *  info,
int  deviceIndex,
int  isInput 
)
static

Definition at line 107 of file DeviceManager.cpp.

108 {
109  wxString hostapiName = wxSafeConvertMB2WX(Pa_GetHostApiInfo(info->hostApi)->name);
110  wxString infoName = wxSafeConvertMB2WX(info->name);
111 
112  map->deviceIndex = deviceIndex;
113  map->hostIndex = info->hostApi;
114  map->deviceString = infoName;
115  map->hostString = hostapiName;
116  map->numChannels = isInput ? info->maxInputChannels : info->maxOutputChannels;
117 }

References DeviceSourceMap::deviceIndex, DeviceSourceMap::deviceString, DeviceSourceMap::hostIndex, DeviceSourceMap::hostString, and DeviceSourceMap::numChannels.

Referenced by AddSources(), and AddSourcesFromStream().

Here is the caller graph for this function:

◆ IsInputDeviceAMapperDevice()

static bool IsInputDeviceAMapperDevice ( const PaDeviceInfo *  info)
static

Definition at line 163 of file DeviceManager.cpp.

164 {
165  // For Windows only, portaudio returns the default mapper object
166  // as the first index after a NEW hostApi index is detected (true for MME and DS)
167  // this is a bit of a hack, but there's no other way to find out which device is a mapper,
168  // I've looked at string comparisons, but if the system is in a different language this breaks.
169 #ifdef __WXMSW__
170  static int lastHostApiTypeId = -1;
171  int hostApiTypeId = Pa_GetHostApiInfo(info->hostApi)->type;
172  if(hostApiTypeId != lastHostApiTypeId &&
173  (hostApiTypeId == paMME || hostApiTypeId == paDirectSound)) {
174  lastHostApiTypeId = hostApiTypeId;
175  return true;
176  }
177 #endif
178 
179  return false;
180 }

Referenced by AddSources().

Here is the caller graph for this function:

◆ MakeDeviceSourceString()

wxString MakeDeviceSourceString ( const DeviceSourceMap map)

Definition at line 54 of file DeviceManager.cpp.

55 {
56  wxString ret;
57  ret = map->deviceString;
58  if (map->totalSources > 1)
59  ret += wxT(": ") + map->sourceString;
60 
61  return ret;
62 }

References DeviceSourceMap::deviceString, DeviceSourceMap::sourceString, and DeviceSourceMap::totalSources.

Referenced by DeviceToolBar::ChangeDevice(), DeviceToolBar::FillHostDevices(), DevicePrefs::OnHost(), and DeviceToolBar::UpdatePrefs().

Here is the caller graph for this function:

◆ wxDEFINE_EVENT()

wxDEFINE_EVENT ( EVT_RESCANNED_DEVICES  ,
wxEvent   
)
DeviceSourceMap::numChannels
int numChannels
Definition: DeviceManager.h:40
PaStream
void PaStream
Definition: AudioIOBase.h:23
FillHostDeviceInfo
static void FillHostDeviceInfo(DeviceSourceMap *map, const PaDeviceInfo *info, int deviceIndex, int isInput)
Definition: DeviceManager.cpp:107
DeviceSourceMap::deviceString
wxString deviceString
Definition: DeviceManager.h:42
IsInputDeviceAMapperDevice
static bool IsInputDeviceAMapperDevice(const PaDeviceInfo *info)
Definition: DeviceManager.cpp:163
DeviceSourceMap
Definition: DeviceManager.h:35
PaError
int PaError
Definition: AudioIO.h:53
AddSourcesFromStream
static void AddSourcesFromStream(int deviceIndex, const PaDeviceInfo *info, std::vector< DeviceSourceMap > *maps, PaStream *stream)
Definition: DeviceManager.cpp:119
DeviceSourceMap::totalSources
int totalSources
Definition: DeviceManager.h:39
DeviceSourceMap::deviceIndex
int deviceIndex
Definition: DeviceManager.h:36
DeviceSourceMap::sourceIndex
int sourceIndex
Definition: DeviceManager.h:37
DeviceSourceMap::hostString
wxString hostString
Definition: DeviceManager.h:43
DeviceSourceMap::hostIndex
int hostIndex
Definition: DeviceManager.h:38
DeviceSourceMap::sourceString
wxString sourceString
Definition: DeviceManager.h:41
DummyPaStreamCallback
static int DummyPaStreamCallback(const void *WXUNUSED(input), void *WXUNUSED(output), unsigned long WXUNUSED(frameCount), const PaStreamCallbackTimeInfo *WXUNUSED(timeInfo), PaStreamCallbackFlags WXUNUSED(statusFlags), void *WXUNUSED(userData))
Definition: DeviceManager.cpp:97