summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Andrews <athenian200@outlook.com>2021-08-24 14:35:49 -0500
committerJeremy Andrews <athenian200@outlook.com>2021-08-24 14:35:49 -0500
commit893fc903790e1ca5bba598113c49d94a165e333b (patch)
tree3d5c4f557b0ddf422d75b3616015cde10b390cd5
parent41b1b3947c99d5f9478e0d3bd60a95b781c69431 (diff)
downloaduxp-893fc903790e1ca5bba598113c49d94a165e333b.tar.gz
Issue #1806 - Part 4: Add more audio troubleshooting information.
This should help us troubleshoot audio issues better in the future in general, since we'll know more about the hardware involved, etc.
-rw-r--r--dom/base/nsDOMWindowUtils.cpp48
-rw-r--r--dom/interfaces/base/nsIDOMWindowUtils.idl23
-rw-r--r--dom/media/AudioDeviceInfo.cpp167
-rw-r--r--dom/media/AudioDeviceInfo.h53
-rw-r--r--dom/media/CubebUtils.cpp93
-rw-r--r--dom/media/CubebUtils.h7
-rw-r--r--dom/media/moz.build3
-rw-r--r--dom/media/nsIAudioDeviceInfo.idl54
-rw-r--r--toolkit/content/aboutSupport.js106
-rw-r--r--toolkit/content/aboutSupport.xhtml85
-rw-r--r--toolkit/locales/en-US/chrome/global/aboutSupport.dtd13
-rw-r--r--toolkit/locales/en-US/chrome/global/aboutSupport.properties6
-rw-r--r--toolkit/modules/Troubleshoot.jsm46
13 files changed, 698 insertions, 6 deletions
diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp
index d05f3b71fc..3606a1b0bc 100644
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -74,6 +74,7 @@
#include "Layers.h"
#include "gfxPrefs.h"
+#include "mozilla/dom/AudioDeviceInfo.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/dom/IDBFactoryBinding.h"
@@ -2371,6 +2372,53 @@ nsDOMWindowUtils::GetCurrentAudioBackend(nsAString& aBackend)
}
NS_IMETHODIMP
+nsDOMWindowUtils::GetCurrentMaxAudioChannels(uint32_t* aChannels)
+{
+ *aChannels = CubebUtils::MaxNumberOfChannels();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMWindowUtils::GetCurrentPreferredChannelLayout(nsAString& aLayout)
+{
+ CubebUtils::GetPreferredChannelLayout(aLayout);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMWindowUtils::GetCurrentPreferredSampleRate(uint32_t* aRate)
+{
+ *aRate = CubebUtils::PreferredSampleRate();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMWindowUtils::AudioDevices(uint16_t aSide, nsIArray** aDevices)
+{
+ NS_ENSURE_ARG_POINTER(aDevices);
+ NS_ENSURE_ARG((aSide == AUDIO_INPUT) || (aSide == AUDIO_OUTPUT));
+ *aDevices = nullptr;
+
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsIMutableArray> devices =
+ do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsTArray<RefPtr<AudioDeviceInfo>> collection;
+ CubebUtils::GetDeviceCollection(collection,
+ aSide == AUDIO_INPUT
+ ? CubebUtils::Side::Input
+ : CubebUtils::Side::Output);
+ for (auto device: collection) {
+ devices->AppendElement(device, false);
+ }
+
+ devices.forget(aDevices);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
nsDOMWindowUtils::StartFrameTimeRecording(uint32_t *startIndex)
{
NS_ENSURE_ARG_POINTER(startIndex);
diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl
index 70ec7e0ae6..e563a19985 100644
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -29,6 +29,7 @@ native nscolor(nscolor);
[ptr] native gfxContext(gfxContext);
typedef unsigned long long nsViewID;
+interface nsIArray;
interface nsICycleCollectorListener;
interface nsIDOMNode;
interface nsIDOMNodeList;
@@ -1426,6 +1427,28 @@ interface nsIDOMWindowUtils : nsISupports {
readonly attribute AString currentAudioBackend;
/**
+ * Returns the max channel counts of the current audio device.
+ */
+ readonly attribute unsigned long currentMaxAudioChannels;
+
+ /**
+ * Returns the preferred channel layout of the current audio device.
+ */
+ readonly attribute AString currentPreferredChannelLayout;
+
+ /**
+ * Returns the preferred sample rate of the current audio device.
+ */
+ readonly attribute unsigned long currentPreferredSampleRate;
+
+ /**
+ * Returns all the audio input/output devices.
+ */
+ const unsigned short AUDIO_INPUT = 0;
+ const unsigned short AUDIO_OUTPUT = 1;
+ nsIArray audioDevices(in unsigned short aSide);
+
+ /**
* Record (and return) frame-intervals for frames which were presented
* between calling StartFrameTimeRecording and StopFrameTimeRecording.
*
diff --git a/dom/media/AudioDeviceInfo.cpp b/dom/media/AudioDeviceInfo.cpp
new file mode 100644
index 0000000000..af5eda72b1
--- /dev/null
+++ b/dom/media/AudioDeviceInfo.cpp
@@ -0,0 +1,167 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "AudioDeviceInfo.h"
+
+NS_IMPL_ISUPPORTS(AudioDeviceInfo, nsIAudioDeviceInfo)
+
+AudioDeviceInfo::AudioDeviceInfo(const nsAString& aName,
+ const nsAString& aGroupId,
+ const nsAString& aVendor,
+ uint16_t aType,
+ uint16_t aState,
+ uint16_t aPreferred,
+ uint16_t aSupportedFormat,
+ uint16_t aDefaultFormat,
+ uint32_t aMaxChannels,
+ uint32_t aDefaultRate,
+ uint32_t aMaxRate,
+ uint32_t aMinRate,
+ uint32_t aMaxLatency,
+ uint32_t aMinLatency)
+ : mName(aName)
+ , mGroupId(aGroupId)
+ , mVendor(aVendor)
+ , mType(aType)
+ , mState(aState)
+ , mPreferred(aPreferred)
+ , mSupportedFormat(aSupportedFormat)
+ , mDefaultFormat(aDefaultFormat)
+ , mMaxChannels(aMaxChannels)
+ , mDefaultRate(aDefaultRate)
+ , mMaxRate(aMaxRate)
+ , mMinRate(aMinRate)
+ , mMaxLatency(aMaxLatency)
+ , mMinLatency(aMinLatency)
+{
+ MOZ_ASSERT(mType == TYPE_UNKNOWN ||
+ mType == TYPE_INPUT ||
+ mType == TYPE_OUTPUT, "Wrong type");
+ MOZ_ASSERT(mState == STATE_DISABLED ||
+ mState == STATE_UNPLUGGED ||
+ mState == STATE_ENABLED, "Wrong state");
+ MOZ_ASSERT(mPreferred == PREF_NONE ||
+ mPreferred == PREF_ALL ||
+ mPreferred & (PREF_MULTIMEDIA | PREF_VOICE | PREF_NOTIFICATION),
+ "Wrong preferred value");
+ MOZ_ASSERT(mSupportedFormat & (FMT_S16LE | FMT_S16BE | FMT_F32LE | FMT_F32BE),
+ "Wrong supported format");
+ MOZ_ASSERT(mDefaultFormat == FMT_S16LE ||
+ mDefaultFormat == FMT_S16BE ||
+ mDefaultFormat == FMT_F32LE ||
+ mDefaultFormat == FMT_F32BE, "Wrong default format");
+}
+
+/* readonly attribute DOMString name; */
+NS_IMETHODIMP
+AudioDeviceInfo::GetName(nsAString& aName)
+{
+ aName = mName;
+ return NS_OK;
+}
+
+/* readonly attribute DOMString groupId; */
+NS_IMETHODIMP
+AudioDeviceInfo::GetGroupId(nsAString& aGroupId)
+{
+ aGroupId = mGroupId;
+ return NS_OK;
+}
+
+/* readonly attribute DOMString vendor; */
+NS_IMETHODIMP
+AudioDeviceInfo::GetVendor(nsAString& aVendor)
+{
+ aVendor = mVendor;
+ return NS_OK;
+}
+
+/* readonly attribute unsigned short type; */
+NS_IMETHODIMP
+AudioDeviceInfo::GetType(uint16_t* aType)
+{
+ *aType = mType;
+ return NS_OK;
+}
+
+/* readonly attribute unsigned short state; */
+NS_IMETHODIMP
+AudioDeviceInfo::GetState(uint16_t* aState)
+{
+ *aState = mState;
+ return NS_OK;
+}
+
+/* readonly attribute unsigned short preferred; */
+NS_IMETHODIMP
+AudioDeviceInfo::GetPreferred(uint16_t* aPreferred)
+{
+ *aPreferred = mPreferred;
+ return NS_OK;
+}
+
+/* readonly attribute unsigned short supportedFormat; */
+NS_IMETHODIMP
+AudioDeviceInfo::GetSupportedFormat(uint16_t* aSupportedFormat)
+{
+ *aSupportedFormat = mSupportedFormat;
+ return NS_OK;
+}
+
+/* readonly attribute unsigned short defaultFormat; */
+NS_IMETHODIMP
+AudioDeviceInfo::GetDefaultFormat(uint16_t* aDefaultFormat)
+{
+ *aDefaultFormat = mDefaultFormat;
+ return NS_OK;
+}
+
+/* readonly attribute unsigned long maxChannels; */
+NS_IMETHODIMP
+AudioDeviceInfo::GetMaxChannels(uint32_t* aMaxChannels)
+{
+ *aMaxChannels = mMaxChannels;
+ return NS_OK;
+}
+
+/* readonly attribute unsigned long defaultRate; */
+NS_IMETHODIMP
+AudioDeviceInfo::GetDefaultRate(uint32_t* aDefaultRate)
+{
+ *aDefaultRate = mDefaultRate;
+ return NS_OK;
+}
+
+/* readonly attribute unsigned long maxRate; */
+NS_IMETHODIMP
+AudioDeviceInfo::GetMaxRate(uint32_t* aMaxRate)
+{
+ *aMaxRate = mMaxRate;
+ return NS_OK;
+}
+
+/* readonly attribute unsigned long minRate; */
+NS_IMETHODIMP
+AudioDeviceInfo::GetMinRate(uint32_t* aMinRate)
+{
+ *aMinRate = mMinRate;
+ return NS_OK;
+}
+
+/* readonly attribute unsigned long maxLatency; */
+NS_IMETHODIMP
+AudioDeviceInfo::GetMaxLatency(uint32_t* aMaxLatency)
+{
+ *aMaxLatency = mMaxLatency;
+ return NS_OK;
+}
+
+/* readonly attribute unsigned long minLatency; */
+NS_IMETHODIMP
++
+-AudioDeviceInfo::GetMinLatency(uint32_t* aMinLatency)
+{
+ *aMinLatency = mMinLatency;
+ return NS_OK;
+}
diff --git a/dom/media/AudioDeviceInfo.h b/dom/media/AudioDeviceInfo.h
new file mode 100644
index 0000000000..25b13a137c
--- /dev/null
+++ b/dom/media/AudioDeviceInfo.h
@@ -0,0 +1,53 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_AudioDeviceInfo_H
+#define MOZILLA_AudioDeviceInfo_H
+
+#include "nsIAudioDeviceInfo.h"
+#include "nsString.h"
+
+// This is mapped to the cubeb_device_info.
+class AudioDeviceInfo final : public nsIAudioDeviceInfo
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIAUDIODEVICEINFO
+
+ explicit AudioDeviceInfo(const nsAString& aName,
+ const nsAString& aGroupId,
+ const nsAString& aVendor,
+ uint16_t aType,
+ uint16_t aState,
+ uint16_t aPreferred,
+ uint16_t aSupportedFormat,
+ uint16_t aDefaultFormat,
+ uint32_t aMaxChannels,
+ uint32_t aDefaultRate,
++
+- uint32_t aMaxRate,
+ uint32_t aMinRate,
+ uint32_t aMaxLatency,
+ uint32_t aMinLatency);
+
+private:
+ virtual ~AudioDeviceInfo() = default;
+
+ nsString mName;
+ nsString mGroupId;
+ nsString mVendor;
+ uint16_t mType;
+ uint16_t mState;
+ uint16_t mPreferred;
+ uint16_t mSupportedFormat;
+ uint16_t mDefaultFormat;
+ uint32_t mMaxChannels;
+ uint32_t mDefaultRate;
+ uint32_t mMaxRate;
+ uint32_t mMinRate;
+ uint32_t mMaxLatency;
+ uint32_t mMinLatency;
+};
+
+#endif // MOZILLA_AudioDeviceInfo_H
diff --git a/dom/media/CubebUtils.cpp b/dom/media/CubebUtils.cpp
index 12f4b03f03..f5f5cb3b12 100644
--- a/dom/media/CubebUtils.cpp
+++ b/dom/media/CubebUtils.cpp
@@ -348,5 +348,98 @@ void GetCurrentBackend(nsAString& aBackend)
aBackend.AssignLiteral("unknown");
}
+uint16_t ConvertCubebType(cubeb_device_type aType)
+{
+ uint16_t map[] = {
+ nsIAudioDeviceInfo::TYPE_UNKNOWN, // CUBEB_DEVICE_TYPE_UNKNOWN
+ nsIAudioDeviceInfo::TYPE_INPUT, // CUBEB_DEVICE_TYPE_INPUT,
+ nsIAudioDeviceInfo::TYPE_OUTPUT // CUBEB_DEVICE_TYPE_OUTPUT
+ };
+ return map[aType];
+}
+
+uint16_t ConvertCubebState(cubeb_device_state aState)
+{
+ uint16_t map[] = {
+ nsIAudioDeviceInfo::STATE_DISABLED, // CUBEB_DEVICE_STATE_DISABLED
+ nsIAudioDeviceInfo::STATE_UNPLUGGED, // CUBEB_DEVICE_STATE_UNPLUGGED
+ nsIAudioDeviceInfo::STATE_ENABLED // CUBEB_DEVICE_STATE_ENABLED
+ };
+ return map[aState];
+}
+
+uint16_t ConvertCubebPreferred(cubeb_device_pref aPreferred)
+{
+ if (aPreferred == CUBEB_DEVICE_PREF_NONE) {
+ return nsIAudioDeviceInfo::PREF_NONE;
+ } else if (aPreferred == CUBEB_DEVICE_PREF_ALL) {
+ return nsIAudioDeviceInfo::PREF_ALL;
+ }
+
+ uint16_t preferred = 0;
+ if (aPreferred & CUBEB_DEVICE_PREF_MULTIMEDIA) {
+ preferred |= nsIAudioDeviceInfo::PREF_MULTIMEDIA;
+ }
+ if (aPreferred & CUBEB_DEVICE_PREF_VOICE) {
+ preferred |= nsIAudioDeviceInfo::PREF_VOICE;
+ }
+ if (aPreferred & CUBEB_DEVICE_PREF_NOTIFICATION) {
+ preferred |= nsIAudioDeviceInfo::PREF_NOTIFICATION;
+ }
+ return preferred;
+}
+
+uint16_t ConvertCubebFormat(cubeb_device_fmt aFormat)
+{
+ uint16_t format = 0;
+ if (aFormat & CUBEB_DEVICE_FMT_S16LE) {
+ format |= nsIAudioDeviceInfo::FMT_S16LE;
+ }
+ if (aFormat & CUBEB_DEVICE_FMT_S16BE) {
+ format |= nsIAudioDeviceInfo::FMT_S16BE;
+ }
+ if (aFormat & CUBEB_DEVICE_FMT_F32LE) {
+ format |= nsIAudioDeviceInfo::FMT_F32LE;
+ }
+ if (aFormat & CUBEB_DEVICE_FMT_F32BE) {
+ format |= nsIAudioDeviceInfo::FMT_F32BE;
+ }
+ return format;
+}
+
+void GetDeviceCollection(nsTArray<RefPtr<AudioDeviceInfo>>& aDeviceInfos,
+ Side aSide)
+{
+ cubeb* context = GetCubebContext();
+ if (context) {
+ cubeb_device_collection collection = { nullptr, 0 };
+ if (cubeb_enumerate_devices(context,
+ aSide == Input ? CUBEB_DEVICE_TYPE_INPUT :
+ CUBEB_DEVICE_TYPE_OUTPUT,
+ &collection) == CUBEB_OK) {
+ for (unsigned int i = 0; i < collection.count; ++i) {
+ auto device = collection.device[i];
+ RefPtr<AudioDeviceInfo> info =
+ new AudioDeviceInfo(NS_ConvertASCIItoUTF16(device.friendly_name),
+ NS_ConvertASCIItoUTF16(device.group_id),
+ NS_ConvertASCIItoUTF16(device.vendor_name),
+ ConvertCubebType(device.type),
+ ConvertCubebState(device.state),
+ ConvertCubebPreferred(device.preferred),
+ ConvertCubebFormat(device.format),
+ ConvertCubebFormat(device.default_format),
+ device.max_channels,
+ device.default_rate,
+ device.max_rate,
+ device.min_rate,
+ device.latency_hi,
+ device.latency_lo);
+ aDeviceInfos.AppendElement(info);
+ }
+ }
+ cubeb_device_collection_destroy(context, &collection);
+ }
+}
+
} // namespace CubebUtils
} // namespace mozilla
diff --git a/dom/media/CubebUtils.h b/dom/media/CubebUtils.h
index 8ebd1af214..2e2e4ba3b5 100644
--- a/dom/media/CubebUtils.h
+++ b/dom/media/CubebUtils.h
@@ -30,6 +30,11 @@ uint32_t MaxNumberOfChannels();
// Get the sample rate the hardware/mixer runs at. Thread safe.
uint32_t PreferredSampleRate();
+enum Side {
+ Input,
+ Output
+};
+
void PrefChanged(const char* aPref, void* aClosure);
double GetVolumeScale();
bool GetFirstStream();
@@ -39,6 +44,8 @@ uint32_t GetCubebPlaybackLatencyInMilliseconds();
uint32_t GetCubebMSGLatencyInFrames(cubeb_stream_params * params);
bool CubebLatencyPrefSet();
void GetCurrentBackend(nsAString& aBackend);
+void GetDeviceCollection(nsTArray<RefPtr<AudioDeviceInfo>>& aDeviceInfos,
+ Side aSide);
} // namespace CubebUtils
} // namespace mozilla
diff --git a/dom/media/moz.build b/dom/media/moz.build
index 40d90b5998..4c22fdb64b 100644
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -65,6 +65,7 @@ if CONFIG['MOZ_WEBRTC']:
WEBRTC_SIGNALLING_TEST_MANIFESTS += ['tests/mochitest/steeplechase_long/steeplechase_long.ini']
XPIDL_SOURCES += [
+ 'nsIAudioDeviceInfo.idl',
'nsIDOMNavigatorUserMedia.idl',
'nsIMediaManager.idl',
]
@@ -163,6 +164,7 @@ IPDL_SOURCES += [
]
EXPORTS.mozilla.dom += [
+ 'AudioDeviceInfo.h',
'AudioStreamTrack.h',
'AudioTrack.h',
'AudioTrackList.h',
@@ -191,6 +193,7 @@ SOURCES += [
'AudioChannelFormat.cpp',
'AudioCompactor.cpp',
'AudioConverter.cpp',
+ 'AudioDeviceInfo.cpp',
'AudioSegment.cpp',
'AudioStream.cpp',
'AudioStreamTrack.cpp',
diff --git a/dom/media/nsIAudioDeviceInfo.idl b/dom/media/nsIAudioDeviceInfo.idl
new file mode 100644
index 0000000000..1a1b9f9f74
--- /dev/null
+++ b/dom/media/nsIAudioDeviceInfo.idl
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(feb979a8-f8cc-4522-9dff-6c055ca50762)]
+interface nsIAudioDeviceInfo : nsISupports
+{
+ readonly attribute DOMString name;
+
+ readonly attribute DOMString groupId;
+
+ readonly attribute DOMString vendor;
+
+ // type: Unknown/Input/Output
+ const unsigned short TYPE_UNKNOWN = 0;
+ const unsigned short TYPE_INPUT = 1;
+ const unsigned short TYPE_OUTPUT = 2;
+ readonly attribute unsigned short type;
+
+ // state: Disabled/Unplugged/Enabled
+ const unsigned short STATE_DISABLED = 0;
+ const unsigned short STATE_UNPLUGGED = 1;
+ const unsigned short STATE_ENABLED = 2;
+ readonly attribute unsigned short state;
+
+ // preferred: None/Multimedia/Voice/Notification/All
+ const unsigned short PREF_NONE = 0x00;
+ const unsigned short PREF_MULTIMEDIA = 0x01;
+ const unsigned short PREF_VOICE = 0x02;
+ const unsigned short PREF_NOTIFICATION = 0x04;
+ const unsigned short PREF_ALL = 0x0F;
+ readonly attribute unsigned short preferred;
+
+ // supported format, default format: S16LE/S16BE/F32LE/F32BE
+ const unsigned short FMT_S16LE = 0x0010;
+ const unsigned short FMT_S16BE = 0x0020;
+ const unsigned short FMT_F32LE = 0x1000;
+ const unsigned short FMT_F32BE = 0x2000;
+ readonly attribute unsigned short supportedFormat;
+ readonly attribute unsigned short defaultFormat;
+
+ // Max number of channels: [1, 255]
+ readonly attribute unsigned long maxChannels;
+
+ readonly attribute unsigned long defaultRate;
+ readonly attribute unsigned long maxRate;
+ readonly attribute unsigned long minRate;
+
+ readonly attribute unsigned long maxLatency;
+ readonly attribute unsigned long minLatency;
+};
diff --git a/toolkit/content/aboutSupport.js b/toolkit/content/aboutSupport.js
index f9a0abcb0e..86f1fa35b7 100644
--- a/toolkit/content/aboutSupport.js
+++ b/toolkit/content/aboutSupport.js
@@ -310,7 +310,6 @@ var snapshotFormatters = {
addRowFromKey("features", "webgl2DriverExtensions");
addRowFromKey("features", "webgl2Extensions");
addRowFromKey("features", "supportsHardwareH264", "hardwareH264");
- addRowFromKey("features", "currentAudioBackend", "audioBackend");
addRowFromKey("features", "direct2DEnabled", "#Direct2D");
if ("directWriteEnabled" in data) {
@@ -462,6 +461,111 @@ var snapshotFormatters = {
}
},
+ media: function media(data) {
+ let strings = stringBundle();
+
+ function insertBasicInfo(key, value) {
+ function createRow(key, value) {
+ let th = $.new("th", strings.GetStringFromName(key), "column");
+ let td = $.new("td", value);
+ td.style["white-space"] = "pre-wrap";
+ return $.new("tr", [th, td]);
+ }
+ $.append($("media-info-tbody"), [createRow(key, value)]);
+ }
+
+ function createDeviceInfoRow(device) {
+ let deviceInfo = Ci.nsIAudioDeviceInfo;
+
+ let states = {};
+ states[deviceInfo.STATE_DISABLED] = "Disabled";
+ states[deviceInfo.STATE_UNPLUGGED] = "Unplugged";
+ states[deviceInfo.STATE_ENABLED] = "Enabled";
+
+ let preferreds = {};
+ preferreds[deviceInfo.PREF_NONE] = "None";
+ preferreds[deviceInfo.PREF_MULTIMEDIA] = "Multimedia";
+ preferreds[deviceInfo.PREF_VOICE] = "Voice";
+ preferreds[deviceInfo.PREF_NOTIFICATION] = "Notification";
+ preferreds[deviceInfo.PREF_ALL] = "All";
+
+ let formats = {};
+ formats[deviceInfo.FMT_S16LE] = "S16LE";
+ formats[deviceInfo.FMT_S16BE] = "S16BE";
+ formats[deviceInfo.FMT_F32LE] = "F32LE";
+ formats[deviceInfo.FMT_F32BE] = "F32BE";
+
+ function toPreferredString(preferred) {
+ if (preferred == deviceInfo.PREF_NONE) {
+ return preferreds[deviceInfo.PREF_NONE];
+ } else if (preferred & deviceInfo.PREF_ALL) {
+ return preferreds[deviceInfo.PREF_ALL];
+ }
+ let str = "";
+ for (let pref of [deviceInfo.PREF_MULTIMEDIA,
+ deviceInfo.PREF_VOICE,
+ deviceInfo.PREF_NOTIFICATION]) {
+ if (preferred & pref) {
+ str += " " + preferreds[pref];
+ }
+ }
+ return str;
+ }
+
+ function toFromatString(dev) {
+ let str = "default: " + formats[dev.defaultFormat] + ", support:";
+ for (let fmt of [deviceInfo.FMT_S16LE,
+ deviceInfo.FMT_S16BE,
+ deviceInfo.FMT_F32LE,
+ deviceInfo.FMT_F32BE]) {
+ if (dev.supportedFormat & fmt) {
+ str += " " + formats[fmt];
+ }
+ }
+ return str;
+ }
+
+ function toRateString(dev) {
+ return "default: " + dev.defaultRate +
+ ", support: " + dev.minRate + " - " + dev.maxRate;
+ }
+
+ function toLatencyString(dev) {
+ return dev.minLatency + " - " + dev.maxLatency;
+ }
+
+ return $.new("tr", [$.new("td", device.name),
+ $.new("td", device.groupId),
+ $.new("td", device.vendor),
+ $.new("td", states[device.state]),
+ $.new("td", toPreferredString(device.preferred)),
+ $.new("td", toFromatString(device)),
+ $.new("td", device.maxChannels),
+ $.new("td", toRateString(device)),
+ $.new("td", toLatencyString(device))]);
+ }
+
+ function insertDeviceInfo(side, devices) {
+ let rows = [];
+ for (let dev of devices) {
+ rows.push(createDeviceInfoRow(dev));
+ }
+ $.append($("media-" + side + "-devices-tbody"), rows);
+ }
+
+ // Basic information
+ insertBasicInfo("audioBackend", data.currentAudioBackend);
+ insertBasicInfo("maxAudioChannels", data.currentMaxAudioChannels);
+ insertBasicInfo("sampleRate", data.currentPreferredSampleRate);
+
+ // Output devices information
+ insertDeviceInfo("output", data.audioOutputDevices);
+
+ // Input devices information
+ insertDeviceInfo("input", data.audioInputDevices);
+ },
+
+
javaScript: function javaScript(data) {
$("javascript-incremental-gc").textContent = data.incrementalGCEnabled;
},
diff --git a/toolkit/content/aboutSupport.xhtml b/toolkit/content/aboutSupport.xhtml
index 4ae9927399..7772f6497a 100644
--- a/toolkit/content/aboutSupport.xhtml
+++ b/toolkit/content/aboutSupport.xhtml
@@ -346,6 +346,91 @@
<!-- - - - - - - - - - - - - - - - - - - - - -->
<h2 class="major-section">
+ &aboutSupport.mediaTitle;
+ </h2>
+ <table>
+ <tbody id="media-info-tbody">
+ </tbody>
+
+ <tbody id="media-output-devices-tbody">
+ <tr>
+ <th colspan="10" class="title-column">
+ &aboutSupport.mediaOutputDevicesTitle;
+ </th>
+ </tr>
+ <tr>
+ <th>
+ &aboutSupport.mediaDeviceName;
+ </th>
+ <th>
+ &aboutSupport.mediaDeviceGroup;
+ </th>
+ <th>
+ &aboutSupport.mediaDeviceVendor;
+ </th>
+ <th>
+ &aboutSupport.mediaDeviceState;
+ </th>
+ <th>
+ &aboutSupport.mediaDevicePreferred;
+ </th>
+ <th>
+ &aboutSupport.mediaDeviceFormat;
+ </th>
+ <th>
+ &aboutSupport.mediaDeviceChannels;
+ </th>
+ <th>
+ &aboutSupport.mediaDeviceRate;
+ </th>
+ <th>
+ &aboutSupport.mediaDeviceLatency;
+ </th>
+ </tr>
+ </tbody>
+
+ <tbody id="media-input-devices-tbody">
+ <tr>
+ <th colspan="10" class="title-column">
+ &aboutSupport.mediaInputDevicesTitle;
+ </th>
+ </tr>
+ <tr>
+ <th>
+ &aboutSupport.mediaDeviceName;
+ </th>
+ <th>
+ &aboutSupport.mediaDeviceGroup;
+ </th>
+ <th>
+ &aboutSupport.mediaDeviceVendor;
+ </th>
+ <th>
+ &aboutSupport.mediaDeviceState;
+ </th>
+ <th>
+ &aboutSupport.mediaDevicePreferred;
+ </th>
+ <th>
+ &aboutSupport.mediaDeviceFormat;
+ </th>
+ <th>
+ &aboutSupport.mediaDeviceChannels;
+ </th>
+ <th>
+ &aboutSupport.mediaDeviceRate;
+ </th>
+ <th>
+ &aboutSupport.mediaDeviceLatency;
+ </th>
+ </tr>
+ </tbody>
+
+ </table>
+
+ <!-- - - - - - - - - - - - - - - - - - - - - -->
+
+ <h2 class="major-section">
&aboutSupport.modifiedKeyPrefsTitle;
</h2>
diff --git a/toolkit/locales/en-US/chrome/global/aboutSupport.dtd b/toolkit/locales/en-US/chrome/global/aboutSupport.dtd
index 02eb34664a..b4da6bc774 100644
--- a/toolkit/locales/en-US/chrome/global/aboutSupport.dtd
+++ b/toolkit/locales/en-US/chrome/global/aboutSupport.dtd
@@ -121,3 +121,16 @@ variant of aboutSupport.showDir.label. -->
<!ENTITY aboutSupport.graphicsDecisionLogTitle "Decision Log">
<!ENTITY aboutSupport.graphicsCrashGuardsTitle "Crash Guard Disabled Features">
<!ENTITY aboutSupport.graphicsWorkaroundsTitle "Workarounds">
+
+<!ENTITY aboutSupport.mediaTitle "Media">
+<!ENTITY aboutSupport.mediaOutputDevicesTitle "Output Devices">
+<!ENTITY aboutSupport.mediaInputDevicesTitle "Input Devices">
+<!ENTITY aboutSupport.mediaDeviceName "Name">
+<!ENTITY aboutSupport.mediaDeviceGroup "Group">
+<!ENTITY aboutSupport.mediaDeviceVendor "Vendor">
+<!ENTITY aboutSupport.mediaDeviceState "State">
+<!ENTITY aboutSupport.mediaDevicePreferred "Preferred">
+<!ENTITY aboutSupport.mediaDeviceFormat "Format">
+<!ENTITY aboutSupport.mediaDeviceChannels "Channels">
+<!ENTITY aboutSupport.mediaDeviceRate "Rate">
+<!ENTITY aboutSupport.mediaDeviceLatency "Latency">
diff --git a/toolkit/locales/en-US/chrome/global/aboutSupport.properties b/toolkit/locales/en-US/chrome/global/aboutSupport.properties
index 46e445f66d..751a3f096e 100644
--- a/toolkit/locales/en-US/chrome/global/aboutSupport.properties
+++ b/toolkit/locales/en-US/chrome/global/aboutSupport.properties
@@ -59,7 +59,6 @@ clearTypeParameters = ClearType Parameters
compositing = Compositing
hardwareH264 = Hardware H264 Decoding
-audioBackend = Audio Backend
mainThreadNoOMTC = main thread, no OMTC
yes = Yes
no = No
@@ -98,6 +97,11 @@ glcontextCrashGuard = OpenGL
resetOnNextRestart = Reset on Next Restart
gpuProcessKillButton = Terminate GPU Process
+audioBackend = Audio Backend
+maxAudioChannels = Max Channels
+channelLayout = Preferred Channel Layout
+sampleRate = Preferred Sample Rate
+
minLibVersions = Expected minimum version
loadedLibVersions = Version in use
diff --git a/toolkit/modules/Troubleshoot.jsm b/toolkit/modules/Troubleshoot.jsm
index 8ff6be30ba..d8f485d2c0 100644
--- a/toolkit/modules/Troubleshoot.jsm
+++ b/toolkit/modules/Troubleshoot.jsm
@@ -332,9 +332,6 @@ var dataProviders = {
data.numAcceleratedWindows++;
}
- let winUtils = Services.wm.getMostRecentWindow("").
- QueryInterface(Ci.nsIInterfaceRequestor).
- getInterface(Ci.nsIDOMWindowUtils)
data.supportsHardwareH264 = "Unknown";
try {
// After restart - data may not be available
@@ -345,7 +342,6 @@ var dataProviders = {
promises.push(promise);
} catch (e) {}
- data.currentAudioBackend = winUtils.currentAudioBackend;
if (!data.numAcceleratedWindows && gfxInfo) {
#ifdef XP_WIN
@@ -492,6 +488,48 @@ var dataProviders = {
completed();
},
+ media: function media(done) {
+ function convertDevices(devices) {
+ if (!devices) {
+ return undefined;
+ }
+ let infos = [];
+ for (let i = 0; i < devices.length; ++i) {
+ let device = devices.queryElementAt(i, Ci.nsIAudioDeviceInfo);
+ infos.push({
+ name: device.name,
+ groupId: device.groupId,
+ vendor: device.vendor,
+ type: device.type,
+ state: device.state,
+ preferred: device.preferred,
+ supportedFormat: device.supportedFormat,
+ defaultFormat: device.defaultFormat,
+ maxChannels: device.maxChannels,
+ defaultRate: device.defaultRate,
+ maxRate: device.maxRate,
+ minRate: device.minRate,
+ maxLatency: device.maxLatency,
+ minLatency: device.minLatency
+ });
+ }
+ return infos;
+ }
+
+ let data = {};
+ let winUtils = Services.wm.getMostRecentWindow("").
+ QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIDOMWindowUtils);
+ data.currentAudioBackend = winUtils.currentAudioBackend;
+ data.currentMaxAudioChannels = winUtils.currentMaxAudioChannels;
+ data.currentPreferredSampleRate = winUtils.currentPreferredSampleRate;
+ data.audioOutputDevices = convertDevices(winUtils.audioDevices(Ci.nsIDOMWindowUtils.AUDIO_OUTPUT).
+ QueryInterface(Ci.nsIArray));
+ data.audioInputDevices = convertDevices(winUtils.audioDevices(Ci.nsIDOMWindowUtils.AUDIO_INPUT).
+ QueryInterface(Ci.nsIArray));
+ done(data);
+ },
+
javaScript: function javaScript(done) {
let data = {};
let winEnumer = Services.ww.getWindowEnumerator();