diff options
author | Jeremy Andrews <athenian200@outlook.com> | 2021-08-24 14:35:49 -0500 |
---|---|---|
committer | Jeremy Andrews <athenian200@outlook.com> | 2021-08-24 14:35:49 -0500 |
commit | 893fc903790e1ca5bba598113c49d94a165e333b (patch) | |
tree | 3d5c4f557b0ddf422d75b3616015cde10b390cd5 | |
parent | 41b1b3947c99d5f9478e0d3bd60a95b781c69431 (diff) | |
download | uxp-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.cpp | 48 | ||||
-rw-r--r-- | dom/interfaces/base/nsIDOMWindowUtils.idl | 23 | ||||
-rw-r--r-- | dom/media/AudioDeviceInfo.cpp | 167 | ||||
-rw-r--r-- | dom/media/AudioDeviceInfo.h | 53 | ||||
-rw-r--r-- | dom/media/CubebUtils.cpp | 93 | ||||
-rw-r--r-- | dom/media/CubebUtils.h | 7 | ||||
-rw-r--r-- | dom/media/moz.build | 3 | ||||
-rw-r--r-- | dom/media/nsIAudioDeviceInfo.idl | 54 | ||||
-rw-r--r-- | toolkit/content/aboutSupport.js | 106 | ||||
-rw-r--r-- | toolkit/content/aboutSupport.xhtml | 85 | ||||
-rw-r--r-- | toolkit/locales/en-US/chrome/global/aboutSupport.dtd | 13 | ||||
-rw-r--r-- | toolkit/locales/en-US/chrome/global/aboutSupport.properties | 6 | ||||
-rw-r--r-- | toolkit/modules/Troubleshoot.jsm | 46 |
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(); |