mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-31 07:59:27 +02:00
svn:eol-style was not set to native for DeviceManager.cpp/h
This commit is contained in:
parent
b9725a6c13
commit
fec888198a
@ -1,308 +1,308 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity - A Digital Audio Editor
|
||||
Copyright 1999-2010 Audacity Team
|
||||
Michael Chinen
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "portaudio.h"
|
||||
#include "portmixer.h"
|
||||
|
||||
#include "Audacity.h"
|
||||
// For compilers that support precompilation, includes "wx/wx.h".
|
||||
#include <wx/wxprec.h>
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include <wx/choice.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/intl.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/statbmp.h>
|
||||
#include <wx/tooltip.h>
|
||||
#endif
|
||||
|
||||
#include "Project.h"
|
||||
|
||||
#include "AudioIO.h"
|
||||
|
||||
#include "DeviceManager.h"
|
||||
#include "toolbars/DeviceToolBar.h"
|
||||
|
||||
DeviceManager DeviceManager::dm;
|
||||
|
||||
/// Gets the singleton instance
|
||||
DeviceManager* DeviceManager::Instance()
|
||||
{
|
||||
return &dm;
|
||||
}
|
||||
|
||||
/// Releases memory assosiated with the singleton
|
||||
void DeviceManager::Destroy()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const std::vector<DeviceSourceMap> &DeviceManager::GetInputDeviceMaps()
|
||||
{
|
||||
if (!m_inited)
|
||||
Init();
|
||||
return mInputDeviceSourceMaps;
|
||||
}
|
||||
const std::vector<DeviceSourceMap> &DeviceManager::GetOutputDeviceMaps()
|
||||
{
|
||||
if (!m_inited)
|
||||
Init();
|
||||
return mOutputDeviceSourceMaps;
|
||||
}
|
||||
|
||||
|
||||
wxString MakeDeviceSourceString(const 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
|
||||
//as this means open in blocking mode, so we use a dummy one.
|
||||
static int DummyPaStreamCallback(
|
||||
const void *input, void *output,
|
||||
unsigned long frameCount,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void FillHostDeviceInfo(DeviceSourceMap *map, const PaDeviceInfo *info, int deviceIndex, int isInput)
|
||||
{
|
||||
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 = isInput ? info->maxInputChannels : info->maxOutputChannels;
|
||||
}
|
||||
|
||||
static void AddSourcesFromStream(int deviceIndex, const PaDeviceInfo *info, std::vector<DeviceSourceMap> *maps, PaStream *stream)
|
||||
{
|
||||
int i;
|
||||
PxMixer *portMixer;
|
||||
DeviceSourceMap map;
|
||||
|
||||
map.sourceIndex = -1;
|
||||
map.totalSources = 0;
|
||||
// Only inputs have sources, so we call FillHostDeviceInfo with a 1 to indicate this
|
||||
FillHostDeviceInfo(&map, info, deviceIndex, 1);
|
||||
portMixer = Px_OpenMixer(stream, 0);
|
||||
if (!portMixer) {
|
||||
maps->push_back(map);
|
||||
return;
|
||||
}
|
||||
|
||||
//if there is only one source, we don't need to concatenate the source
|
||||
//or enumerate, because it is something meaningless like 'master'
|
||||
//(as opposed to 'mic in' or 'line in'), and the user doesn't have any choice.
|
||||
//note that some devices have no input sources at all but are still valid.
|
||||
//the behavior we do is the same for 0 and 1 source cases.
|
||||
map.totalSources = Px_GetNumInputSources(portMixer);
|
||||
|
||||
if (map.totalSources <= 1) {
|
||||
map.sourceIndex = 0;
|
||||
maps->push_back(map);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
Px_CloseMixer(portMixer);
|
||||
}
|
||||
|
||||
static bool IsInputDeviceAMapperDevice(const PaDeviceInfo *info)
|
||||
{
|
||||
// For Windows only, portaudio returns the default mapper object
|
||||
// as the first index after a new hostApi index is detected (true for MME and DS)
|
||||
// this is a bit of a hack, but there's no other way to find out which device is a mapper,
|
||||
// I've looked at string comparisons, but if the system is in a different language this breaks.
|
||||
#ifdef __WXMSW__
|
||||
static int lastHostApiTypeId = -1;
|
||||
int hostApiTypeId = Pa_GetHostApiInfo(info->hostApi)->type;
|
||||
if(hostApiTypeId != lastHostApiTypeId &&
|
||||
(hostApiTypeId == paMME || hostApiTypeId == paDirectSound)) {
|
||||
lastHostApiTypeId = hostApiTypeId;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void AddSources(int deviceIndex, int rate, std::vector<DeviceSourceMap> *maps, int isInput)
|
||||
{
|
||||
int error = 0;
|
||||
DeviceSourceMap map;
|
||||
const PaDeviceInfo *info = Pa_GetDeviceInfo(deviceIndex);
|
||||
|
||||
// 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.
|
||||
|
||||
PaStream *stream = NULL;
|
||||
|
||||
PaStreamParameters parameters;
|
||||
|
||||
parameters.device = deviceIndex;
|
||||
parameters.sampleFormat = paFloat32;
|
||||
parameters.hostApiSpecificStreamInfo = NULL;
|
||||
parameters.channelCount = 1;
|
||||
|
||||
// If the device is for input, open a stream so we can use portmixer to query
|
||||
// the number of inputs. We skip this for outputs because there are no 'sources'
|
||||
// and some platforms (e.g. XP) have the same device for input and output, (while
|
||||
// Vista/Win7 seperate these into two devices with the same names (but different
|
||||
// portaudio indecies)
|
||||
// Also, for mapper devices we don't want to keep any sources, so check for it here
|
||||
if (isInput && !IsInputDeviceAMapperDevice(info)) {
|
||||
if (info)
|
||||
parameters.suggestedLatency = info->defaultLowInputLatency;
|
||||
else
|
||||
parameters.suggestedLatency = 10.0;
|
||||
|
||||
error = Pa_OpenStream(&stream,
|
||||
¶meters,
|
||||
NULL,
|
||||
rate, paFramesPerBufferUnspecified,
|
||||
paClipOff | paDitherOff,
|
||||
DummyPaStreamCallback, NULL);
|
||||
}
|
||||
|
||||
if (stream && !error) {
|
||||
AddSourcesFromStream(deviceIndex, info, maps, stream);
|
||||
Pa_CloseStream(stream);
|
||||
} else {
|
||||
map.sourceIndex = -1;
|
||||
map.totalSources = 0;
|
||||
FillHostDeviceInfo(&map, info, deviceIndex, isInput);
|
||||
maps->push_back(map);
|
||||
}
|
||||
|
||||
if(error) {
|
||||
wxLogDebug(wxT("PortAudio stream error creating device list: ") +
|
||||
map.hostString + wxT(":") + map.deviceString + wxT(": ") +
|
||||
wxString(Pa_GetErrorText( (PaError)error), wxConvLocal));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Gets a new list of devices by terminating and restarting portaudio
|
||||
/// Assumes that DeviceManager is only used on the main thread.
|
||||
void DeviceManager::Rescan()
|
||||
{
|
||||
// get rid of the previous scan info
|
||||
this->mInputDeviceSourceMaps.clear();
|
||||
this->mOutputDeviceSourceMaps.clear();
|
||||
|
||||
// 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.
|
||||
if (gAudioIO) {
|
||||
if (gAudioIO->IsMonitoring())
|
||||
{
|
||||
gAudioIO->StopStream();
|
||||
while (gAudioIO->IsBusy())
|
||||
wxMilliSleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
// restart portaudio - this updates the device list
|
||||
Pa_Terminate();
|
||||
Pa_Initialize();
|
||||
}
|
||||
|
||||
int nDevices = Pa_GetDeviceCount();
|
||||
int i;
|
||||
|
||||
//The heirarchy for devices is Host/device/source.
|
||||
//Some newer systems aggregate this.
|
||||
//So we need to call port mixer for every device to get the sources
|
||||
for (i = 0; i < nDevices; i++) {
|
||||
const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
|
||||
if (info->maxOutputChannels > 0) {
|
||||
AddSources(i, info->defaultSampleRate, &mOutputDeviceSourceMaps, 0);
|
||||
}
|
||||
|
||||
if (info->maxInputChannels > 0) {
|
||||
AddSources(i, info->defaultSampleRate, &mInputDeviceSourceMaps, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
//private constructor - Singleton.
|
||||
DeviceManager::DeviceManager()
|
||||
{
|
||||
m_inited = false;
|
||||
}
|
||||
|
||||
DeviceManager::~DeviceManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DeviceManager::Init()
|
||||
{
|
||||
Rescan();
|
||||
}
|
||||
/**********************************************************************
|
||||
|
||||
Audacity - A Digital Audio Editor
|
||||
Copyright 1999-2010 Audacity Team
|
||||
Michael Chinen
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "portaudio.h"
|
||||
#include "portmixer.h"
|
||||
|
||||
#include "Audacity.h"
|
||||
// For compilers that support precompilation, includes "wx/wx.h".
|
||||
#include <wx/wxprec.h>
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include <wx/choice.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/intl.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/statbmp.h>
|
||||
#include <wx/tooltip.h>
|
||||
#endif
|
||||
|
||||
#include "Project.h"
|
||||
|
||||
#include "AudioIO.h"
|
||||
|
||||
#include "DeviceManager.h"
|
||||
#include "toolbars/DeviceToolBar.h"
|
||||
|
||||
DeviceManager DeviceManager::dm;
|
||||
|
||||
/// Gets the singleton instance
|
||||
DeviceManager* DeviceManager::Instance()
|
||||
{
|
||||
return &dm;
|
||||
}
|
||||
|
||||
/// Releases memory assosiated with the singleton
|
||||
void DeviceManager::Destroy()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const std::vector<DeviceSourceMap> &DeviceManager::GetInputDeviceMaps()
|
||||
{
|
||||
if (!m_inited)
|
||||
Init();
|
||||
return mInputDeviceSourceMaps;
|
||||
}
|
||||
const std::vector<DeviceSourceMap> &DeviceManager::GetOutputDeviceMaps()
|
||||
{
|
||||
if (!m_inited)
|
||||
Init();
|
||||
return mOutputDeviceSourceMaps;
|
||||
}
|
||||
|
||||
|
||||
wxString MakeDeviceSourceString(const 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
|
||||
//as this means open in blocking mode, so we use a dummy one.
|
||||
static int DummyPaStreamCallback(
|
||||
const void *input, void *output,
|
||||
unsigned long frameCount,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void FillHostDeviceInfo(DeviceSourceMap *map, const PaDeviceInfo *info, int deviceIndex, int isInput)
|
||||
{
|
||||
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 = isInput ? info->maxInputChannels : info->maxOutputChannels;
|
||||
}
|
||||
|
||||
static void AddSourcesFromStream(int deviceIndex, const PaDeviceInfo *info, std::vector<DeviceSourceMap> *maps, PaStream *stream)
|
||||
{
|
||||
int i;
|
||||
PxMixer *portMixer;
|
||||
DeviceSourceMap map;
|
||||
|
||||
map.sourceIndex = -1;
|
||||
map.totalSources = 0;
|
||||
// Only inputs have sources, so we call FillHostDeviceInfo with a 1 to indicate this
|
||||
FillHostDeviceInfo(&map, info, deviceIndex, 1);
|
||||
portMixer = Px_OpenMixer(stream, 0);
|
||||
if (!portMixer) {
|
||||
maps->push_back(map);
|
||||
return;
|
||||
}
|
||||
|
||||
//if there is only one source, we don't need to concatenate the source
|
||||
//or enumerate, because it is something meaningless like 'master'
|
||||
//(as opposed to 'mic in' or 'line in'), and the user doesn't have any choice.
|
||||
//note that some devices have no input sources at all but are still valid.
|
||||
//the behavior we do is the same for 0 and 1 source cases.
|
||||
map.totalSources = Px_GetNumInputSources(portMixer);
|
||||
|
||||
if (map.totalSources <= 1) {
|
||||
map.sourceIndex = 0;
|
||||
maps->push_back(map);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
Px_CloseMixer(portMixer);
|
||||
}
|
||||
|
||||
static bool IsInputDeviceAMapperDevice(const PaDeviceInfo *info)
|
||||
{
|
||||
// For Windows only, portaudio returns the default mapper object
|
||||
// as the first index after a new hostApi index is detected (true for MME and DS)
|
||||
// this is a bit of a hack, but there's no other way to find out which device is a mapper,
|
||||
// I've looked at string comparisons, but if the system is in a different language this breaks.
|
||||
#ifdef __WXMSW__
|
||||
static int lastHostApiTypeId = -1;
|
||||
int hostApiTypeId = Pa_GetHostApiInfo(info->hostApi)->type;
|
||||
if(hostApiTypeId != lastHostApiTypeId &&
|
||||
(hostApiTypeId == paMME || hostApiTypeId == paDirectSound)) {
|
||||
lastHostApiTypeId = hostApiTypeId;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void AddSources(int deviceIndex, int rate, std::vector<DeviceSourceMap> *maps, int isInput)
|
||||
{
|
||||
int error = 0;
|
||||
DeviceSourceMap map;
|
||||
const PaDeviceInfo *info = Pa_GetDeviceInfo(deviceIndex);
|
||||
|
||||
// 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.
|
||||
|
||||
PaStream *stream = NULL;
|
||||
|
||||
PaStreamParameters parameters;
|
||||
|
||||
parameters.device = deviceIndex;
|
||||
parameters.sampleFormat = paFloat32;
|
||||
parameters.hostApiSpecificStreamInfo = NULL;
|
||||
parameters.channelCount = 1;
|
||||
|
||||
// If the device is for input, open a stream so we can use portmixer to query
|
||||
// the number of inputs. We skip this for outputs because there are no 'sources'
|
||||
// and some platforms (e.g. XP) have the same device for input and output, (while
|
||||
// Vista/Win7 seperate these into two devices with the same names (but different
|
||||
// portaudio indecies)
|
||||
// Also, for mapper devices we don't want to keep any sources, so check for it here
|
||||
if (isInput && !IsInputDeviceAMapperDevice(info)) {
|
||||
if (info)
|
||||
parameters.suggestedLatency = info->defaultLowInputLatency;
|
||||
else
|
||||
parameters.suggestedLatency = 10.0;
|
||||
|
||||
error = Pa_OpenStream(&stream,
|
||||
¶meters,
|
||||
NULL,
|
||||
rate, paFramesPerBufferUnspecified,
|
||||
paClipOff | paDitherOff,
|
||||
DummyPaStreamCallback, NULL);
|
||||
}
|
||||
|
||||
if (stream && !error) {
|
||||
AddSourcesFromStream(deviceIndex, info, maps, stream);
|
||||
Pa_CloseStream(stream);
|
||||
} else {
|
||||
map.sourceIndex = -1;
|
||||
map.totalSources = 0;
|
||||
FillHostDeviceInfo(&map, info, deviceIndex, isInput);
|
||||
maps->push_back(map);
|
||||
}
|
||||
|
||||
if(error) {
|
||||
wxLogDebug(wxT("PortAudio stream error creating device list: ") +
|
||||
map.hostString + wxT(":") + map.deviceString + wxT(": ") +
|
||||
wxString(Pa_GetErrorText( (PaError)error), wxConvLocal));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Gets a new list of devices by terminating and restarting portaudio
|
||||
/// Assumes that DeviceManager is only used on the main thread.
|
||||
void DeviceManager::Rescan()
|
||||
{
|
||||
// get rid of the previous scan info
|
||||
this->mInputDeviceSourceMaps.clear();
|
||||
this->mOutputDeviceSourceMaps.clear();
|
||||
|
||||
// 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.
|
||||
if (gAudioIO) {
|
||||
if (gAudioIO->IsMonitoring())
|
||||
{
|
||||
gAudioIO->StopStream();
|
||||
while (gAudioIO->IsBusy())
|
||||
wxMilliSleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
// restart portaudio - this updates the device list
|
||||
Pa_Terminate();
|
||||
Pa_Initialize();
|
||||
}
|
||||
|
||||
int nDevices = Pa_GetDeviceCount();
|
||||
int i;
|
||||
|
||||
//The heirarchy for devices is Host/device/source.
|
||||
//Some newer systems aggregate this.
|
||||
//So we need to call port mixer for every device to get the sources
|
||||
for (i = 0; i < nDevices; i++) {
|
||||
const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
|
||||
if (info->maxOutputChannels > 0) {
|
||||
AddSources(i, info->defaultSampleRate, &mOutputDeviceSourceMaps, 0);
|
||||
}
|
||||
|
||||
if (info->maxInputChannels > 0) {
|
||||
AddSources(i, info->defaultSampleRate, &mInputDeviceSourceMaps, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
//private constructor - Singleton.
|
||||
DeviceManager::DeviceManager()
|
||||
{
|
||||
m_inited = false;
|
||||
}
|
||||
|
||||
DeviceManager::~DeviceManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DeviceManager::Init()
|
||||
{
|
||||
Rescan();
|
||||
}
|
||||
|
@ -1,75 +1,75 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
DeviceManager.h
|
||||
|
||||
Created by Michael Chinen (mchinen) on 2/12/11
|
||||
Audacity(R) is copyright (c) 1999-2011 Audacity Team.
|
||||
License: GPL v2. See License.txt.
|
||||
|
||||
******************************************************************//**
|
||||
|
||||
\class DeviceManager
|
||||
\brief A singleton that manages the audio devices known to Audacity
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
#ifndef __AUDACITY_DEVICEMANAGER__
|
||||
#define __AUDACITY_DEVICEMANAGER__
|
||||
|
||||
#include <vector>
|
||||
#include "wx/wx.h"
|
||||
|
||||
typedef struct DeviceSourceMap {
|
||||
int deviceIndex;
|
||||
int sourceIndex;
|
||||
int hostIndex;
|
||||
int totalSources;
|
||||
int numChannels;
|
||||
wxString sourceString;
|
||||
wxString deviceString;
|
||||
wxString hostString;
|
||||
} DeviceSourceMap;
|
||||
|
||||
wxString MakeDeviceSourceString(const DeviceSourceMap *map);
|
||||
|
||||
class DeviceManager
|
||||
{
|
||||
public:
|
||||
/// Gets the singleton instance
|
||||
static DeviceManager* Instance();
|
||||
|
||||
/// Releases memory assosiated with the singleton
|
||||
static void Destroy();
|
||||
|
||||
/// Gets a new list of devices by terminating and restarting portaudio
|
||||
/// Assumes that DeviceManager is only used on the main thread.
|
||||
void Rescan();
|
||||
|
||||
DeviceSourceMap* GetDefaultOutputDevice(int hostIndex);
|
||||
DeviceSourceMap* GetDefaultInputDevice(int hostIndex);
|
||||
|
||||
const std::vector<DeviceSourceMap> &GetInputDeviceMaps();
|
||||
const std::vector<DeviceSourceMap> &GetOutputDeviceMaps();
|
||||
|
||||
protected:
|
||||
//private constructor - Singleton.
|
||||
DeviceManager();
|
||||
virtual ~DeviceManager();
|
||||
/// Does an initial scan.
|
||||
/// Called by GetInputDeviceMaps and GetOutputDeviceMaps when needed.
|
||||
void Init();
|
||||
|
||||
DeviceSourceMap* GetDefaultDevice(int hostIndex, int isInput);
|
||||
|
||||
bool m_inited;
|
||||
|
||||
std::vector<DeviceSourceMap> mInputDeviceSourceMaps;
|
||||
std::vector<DeviceSourceMap> mOutputDeviceSourceMaps;
|
||||
|
||||
static DeviceManager dm;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
DeviceManager.h
|
||||
|
||||
Created by Michael Chinen (mchinen) on 2/12/11
|
||||
Audacity(R) is copyright (c) 1999-2011 Audacity Team.
|
||||
License: GPL v2. See License.txt.
|
||||
|
||||
******************************************************************//**
|
||||
|
||||
\class DeviceManager
|
||||
\brief A singleton that manages the audio devices known to Audacity
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
#ifndef __AUDACITY_DEVICEMANAGER__
|
||||
#define __AUDACITY_DEVICEMANAGER__
|
||||
|
||||
#include <vector>
|
||||
#include "wx/wx.h"
|
||||
|
||||
typedef struct DeviceSourceMap {
|
||||
int deviceIndex;
|
||||
int sourceIndex;
|
||||
int hostIndex;
|
||||
int totalSources;
|
||||
int numChannels;
|
||||
wxString sourceString;
|
||||
wxString deviceString;
|
||||
wxString hostString;
|
||||
} DeviceSourceMap;
|
||||
|
||||
wxString MakeDeviceSourceString(const DeviceSourceMap *map);
|
||||
|
||||
class DeviceManager
|
||||
{
|
||||
public:
|
||||
/// Gets the singleton instance
|
||||
static DeviceManager* Instance();
|
||||
|
||||
/// Releases memory assosiated with the singleton
|
||||
static void Destroy();
|
||||
|
||||
/// Gets a new list of devices by terminating and restarting portaudio
|
||||
/// Assumes that DeviceManager is only used on the main thread.
|
||||
void Rescan();
|
||||
|
||||
DeviceSourceMap* GetDefaultOutputDevice(int hostIndex);
|
||||
DeviceSourceMap* GetDefaultInputDevice(int hostIndex);
|
||||
|
||||
const std::vector<DeviceSourceMap> &GetInputDeviceMaps();
|
||||
const std::vector<DeviceSourceMap> &GetOutputDeviceMaps();
|
||||
|
||||
protected:
|
||||
//private constructor - Singleton.
|
||||
DeviceManager();
|
||||
virtual ~DeviceManager();
|
||||
/// Does an initial scan.
|
||||
/// Called by GetInputDeviceMaps and GetOutputDeviceMaps when needed.
|
||||
void Init();
|
||||
|
||||
DeviceSourceMap* GetDefaultDevice(int hostIndex, int isInput);
|
||||
|
||||
bool m_inited;
|
||||
|
||||
std::vector<DeviceSourceMap> mInputDeviceSourceMaps;
|
||||
std::vector<DeviceSourceMap> mOutputDeviceSourceMaps;
|
||||
|
||||
static DeviceManager dm;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user