Commit 3ca01d58 authored by Yuwei Huang's avatar Yuwei Huang Committed by Chromium LUCI CQ

[remoting host][mac] Add routine to list audio devices

It isn't straightforward for the user to figure out the UID of an audio
device, so this CL provides an extra host routine to list all available
audio devices and their UID. The user can trigger it by running:

  remoting_me2me_host.app/Contents/MacOS/remoting_me2me_host --list-audio-devices

An example output looks like this:

  Audio devices:
    Device name: BlackHole 16ch
    Device UID: BlackHole_UID

    Device name: MacBook Pro Microphone
    Device UID: BuiltInMicrophoneDevice

    Device name: MacBook Pro Speakers
    Device UID: BuiltInSpeakerDevice

Bug: 1161363
Change-Id: I060d08956a9635cb6d8e165a90f891399fb63be5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2630741
Commit-Queue: Yuwei Huang <yuweih@chromium.org>
Reviewed-by: default avatarJoe Downing <joedow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#844323}
parent 0487aaa3
...@@ -94,6 +94,77 @@ AudioCapturerInstanceSet* AudioCapturerInstanceSet::Get() { ...@@ -94,6 +94,77 @@ AudioCapturerInstanceSet* AudioCapturerInstanceSet::Get() {
} // namespace } // namespace
// static
std::vector<AudioCapturerMac::AudioDeviceInfo>
AudioCapturerMac::GetAudioDevices() {
AudioObjectPropertyAddress property_address;
property_address.mScope = kAudioObjectPropertyScopeGlobal;
property_address.mElement = kAudioObjectPropertyElementMaster;
UInt32 property_size;
// Get all audio device IDs (which are UInt32).
property_address.mSelector = kAudioHardwarePropertyDevices;
OSStatus result = AudioObjectGetPropertyDataSize(
kAudioObjectSystemObject, &property_address, 0, NULL, &property_size);
if (result != noErr) {
LOG(ERROR)
<< "AudioObjectGetPropertyDataSize(kAudioHardwarePropertyDevices) "
<< "failed. Error: " << result;
return {};
}
UInt32 num_devices = property_size / sizeof(AudioDeviceID);
auto device_ids = std::make_unique<AudioDeviceID[]>(num_devices);
result =
AudioObjectGetPropertyData(kAudioObjectSystemObject, &property_address, 0,
NULL, &property_size, device_ids.get());
if (result != noErr) {
LOG(ERROR) << "AudioObjectGetPropertyData(kAudioHardwarePropertyDevices) "
<< "failed. Error: " << result;
return {};
}
std::vector<AudioDeviceInfo> audio_devices;
for (UInt32 i = 0u; i < num_devices; i++) {
AudioDeviceInfo audio_device;
AudioDeviceID device_id = device_ids.get()[i];
// Get the device name.
property_address.mSelector = kAudioObjectPropertyName;
base::ScopedCFTypeRef<CFStringRef> device_name;
property_size = sizeof(CFStringRef);
result = AudioObjectGetPropertyData(device_id, &property_address, 0, NULL,
&property_size,
device_name.InitializeInto());
if (result != noErr) {
LOG(ERROR) << "AudioObjectGetPropertyData(" << device_id
<< ", kAudioObjectPropertyName) "
<< "failed. Error: " << result;
continue;
}
audio_device.device_name = base::SysCFStringRefToUTF8(device_name);
// Now find out its UID.
property_address.mSelector = kAudioDevicePropertyDeviceUID;
base::ScopedCFTypeRef<CFStringRef> device_uid;
property_size = sizeof(CFStringRef);
result =
AudioObjectGetPropertyData(device_id, &property_address, 0, NULL,
&property_size, device_uid.InitializeInto());
if (result != noErr) {
LOG(ERROR) << "AudioObjectGetPropertyData(" << device_id
<< ", kAudioDevicePropertyDeviceUID) "
<< "failed. Error: " << result;
continue;
}
audio_device.device_uid = base::SysCFStringRefToUTF8(device_uid);
audio_devices.push_back(audio_device);
}
return audio_devices;
}
AudioCapturerMac::AudioCapturerMac(const std::string& audio_device_uid) AudioCapturerMac::AudioCapturerMac(const std::string& audio_device_uid)
: audio_device_uid_(audio_device_uid), : audio_device_uid_(audio_device_uid),
silence_detector_(kAudioSilenceThreshold) { silence_detector_(kAudioSilenceThreshold) {
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <AudioToolbox/AudioToolbox.h> #include <AudioToolbox/AudioToolbox.h>
#include <string> #include <string>
#include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
...@@ -26,6 +27,17 @@ namespace remoting { ...@@ -26,6 +27,17 @@ namespace remoting {
// audio on Mac through the loopback device. // audio on Mac through the loopback device.
class AudioCapturerMac : public AudioCapturer { class AudioCapturerMac : public AudioCapturer {
public: public:
struct AudioDeviceInfo {
// Human readable name for the device. Might not be unique.
std::string device_name;
// A unique ID for the device.
std::string device_uid;
};
// Gets information about all available audio devices.
static std::vector<AudioDeviceInfo> GetAudioDevices();
explicit AudioCapturerMac(const std::string& audio_device_uid); explicit AudioCapturerMac(const std::string& audio_device_uid);
~AudioCapturerMac() override; ~AudioCapturerMac() override;
......
...@@ -60,8 +60,17 @@ const char kUsageMessage[] = ...@@ -60,8 +60,17 @@ const char kUsageMessage[] =
"Usage: %s [options]\n" "Usage: %s [options]\n"
"\n" "\n"
"Options:\n" "Options:\n"
#if defined(OS_LINUX)
" --audio-pipe-name=<pipe> - Sets the pipe name to capture audio on " " --audio-pipe-name=<pipe> - Sets the pipe name to capture audio on "
"Linux.\n" "Linux.\n"
#endif // defined(OS_LINUX)
#if defined(OS_APPLE)
" --list-audio-devices - List all audio devices and their device "
"UID.\n"
#endif // defined(OS_APPLE)
" --console - Runs the daemon interactively.\n" " --console - Runs the daemon interactively.\n"
" --elevate=<binary> - Runs <binary> elevated.\n" " --elevate=<binary> - Runs <binary> elevated.\n"
" --host-config=<config> - Specifies the host configuration.\n" " --host-config=<config> - Specifies the host configuration.\n"
......
...@@ -115,6 +115,7 @@ ...@@ -115,6 +115,7 @@
#if defined(OS_APPLE) #if defined(OS_APPLE)
#include "base/mac/mac_util.h" #include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h" #include "base/mac/scoped_cftyperef.h"
#include "remoting/host/audio_capturer_mac.h"
#include "remoting/host/desktop_capturer_checker.h" #include "remoting/host/desktop_capturer_checker.h"
#include "remoting/host/mac/permission_utils.h" #include "remoting/host/mac/permission_utils.h"
#endif // defined(OS_APPLE) #endif // defined(OS_APPLE)
...@@ -515,6 +516,17 @@ bool HostProcess::InitWithCommandLine(const base::CommandLine* cmd_line) { ...@@ -515,6 +516,17 @@ bool HostProcess::InitWithCommandLine(const base::CommandLine* cmd_line) {
permission_granted_ = mac::CanRecordScreen(); permission_granted_ = mac::CanRecordScreen();
return false; return false;
} }
if (cmd_line->HasSwitch(kListAudioDevicesSwitchName)) {
std::vector<AudioCapturerMac::AudioDeviceInfo> audio_devices =
AudioCapturerMac::GetAudioDevices();
printf("Audio devices:\n");
for (const auto& audio_device : audio_devices) {
printf("\n");
printf(" Device name: %s\n", audio_device.device_name.c_str());
printf(" Device UID: %s\n", audio_device.device_uid.c_str());
}
return false;
}
#endif // defined(OS_APPLE) #endif // defined(OS_APPLE)
#if defined(REMOTING_MULTI_PROCESS) #if defined(REMOTING_MULTI_PROCESS)
......
...@@ -45,6 +45,7 @@ const char kCheckAccessibilityPermissionSwitchName[] = ...@@ -45,6 +45,7 @@ const char kCheckAccessibilityPermissionSwitchName[] =
"check-accessibility-permission"; "check-accessibility-permission";
const char kCheckScreenRecordingPermissionSwitchName[] = const char kCheckScreenRecordingPermissionSwitchName[] =
"check-screen-recording-permission"; "check-screen-recording-permission";
const char kListAudioDevicesSwitchName[] = "list-audio-devices";
#endif // defined OS_APPLE #endif // defined OS_APPLE
} // namespace remoting } // namespace remoting
...@@ -71,6 +71,9 @@ extern const char kCheckAccessibilityPermissionSwitchName[]; ...@@ -71,6 +71,9 @@ extern const char kCheckAccessibilityPermissionSwitchName[];
// Command line switch to check for Screen Recording permission. // Command line switch to check for Screen Recording permission.
extern const char kCheckScreenRecordingPermissionSwitchName[]; extern const char kCheckScreenRecordingPermissionSwitchName[];
// Command line switch to list all audio devices and their UID.
extern const char kListAudioDevicesSwitchName[];
#endif // defined OS_APPLE #endif // defined OS_APPLE
} // namespace remoting } // namespace remoting
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment