Bug 1197045 - part3: Add audio devices information to about:support; r=Felipe
☠☠ backed out by 40795195e9b6 ☠ ☠
authorChun-Min Chang <chun.m.chang@gmail.com>
Fri, 21 Jul 2017 17:58:59 +0800
changeset 419259 fd48cc71efefb5c4eee80a8a6fcb6b540dac8567
parent 419258 cf756c62b0a61b02b1b599fda6c680240e7b6756
child 419260 3af0f387a8f2cbaefcd744a925df6be7cab3b8af
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersFelipe
bugs1197045
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1197045 - part3: Add audio devices information to about:support; r=Felipe MozReview-Commit-ID: Lo3WgXC5ikN
toolkit/content/aboutSupport.js
toolkit/content/aboutSupport.xhtml
toolkit/locales/en-US/chrome/global/aboutSupport.dtd
toolkit/locales/en-US/chrome/global/aboutSupport.properties
toolkit/modules/Troubleshoot.jsm
--- a/toolkit/content/aboutSupport.js
+++ b/toolkit/content/aboutSupport.js
@@ -444,17 +444,16 @@ var snapshotFormatters = {
     addRowFromKey("features", "webgl1DriverExtensions");
     addRowFromKey("features", "webgl1Extensions");
     addRowFromKey("features", "webgl2WSIInfo");
     addRowFromKey("features", "webgl2Renderer");
     addRowFromKey("features", "webgl2Version");
     addRowFromKey("features", "webgl2DriverExtensions");
     addRowFromKey("features", "webgl2Extensions");
     addRowFromKey("features", "supportsHardwareH264", "hardwareH264");
-    addRowFromKey("features", "currentAudioBackend", "audioBackend");
     addRowFromKey("features", "direct2DEnabled", "#Direct2D");
 
     if ("directWriteEnabled" in data) {
       let message = data.directWriteEnabled;
       if ("directWriteVersion" in data)
         message += " (" + data.directWriteVersion + ")";
       addRow("features", "#DirectWrite", message);
       delete data.directWriteEnabled;
@@ -593,16 +592,121 @@ var snapshotFormatters = {
       let value = data[key];
       if (Array.isArray(value)) {
         value = localizedMsg(value);
       }
       addRow("diagnostics", key, value);
     }
   },
 
+  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("channelLayout", data.currentPreferredChannelLayout);
+    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;
   },
 
   accessibility: function accessibility(data) {
     $("a11y-activated").textContent = data.isActive;
     $("a11y-force-disabled").textContent = data.forceDisabled || 0;
     let a11yHandlerUsed = $("a11y-handler-used");
--- a/toolkit/content/aboutSupport.xhtml
+++ b/toolkit/content/aboutSupport.xhtml
@@ -439,16 +439,101 @@
             </th>
           </tr>
         </tbody>
       </table>
 
       <!-- - - - - - - - - - - - - - - - - - - - - -->
 
       <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>
 
       <table class="prefs-table">
         <thead class="no-copy">
           <th class="name">
             &aboutSupport.modifiedPrefsName;
           </th>
--- a/toolkit/locales/en-US/chrome/global/aboutSupport.dtd
+++ b/toolkit/locales/en-US/chrome/global/aboutSupport.dtd
@@ -136,8 +136,21 @@ variant of aboutSupport.showDir.label. -
 <!ENTITY aboutSupport.graphicsFeaturesTitle "Features">
 <!ENTITY aboutSupport.graphicsDiagnosticsTitle "Diagnostics">
 <!ENTITY aboutSupport.graphicsFailureLogTitle "Failure Log">
 <!ENTITY aboutSupport.graphicsGPU1Title "GPU #1">
 <!ENTITY aboutSupport.graphicsGPU2Title "GPU #2">
 <!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">
--- a/toolkit/locales/en-US/chrome/global/aboutSupport.properties
+++ b/toolkit/locales/en-US/chrome/global/aboutSupport.properties
@@ -52,17 +52,16 @@ blockedMismatchedVersion = Blocked for y
 
 # LOCALIZATION NOTE In the following strings, "Direct2D", "DirectWrite" and "ClearType"
 # are proper nouns and should not be translated. Feel free to leave english strings if
 # there are no good translations, these are only used in about:support
 clearTypeParameters = ClearType Parameters
 
 compositing = Compositing
 hardwareH264 = Hardware H264 Decoding
-audioBackend = Audio Backend
 mainThreadNoOMTC = main thread, no OMTC
 yes = Yes
 no = No
 # LOCALIZATION NOTE The following strings indicate if an API key has been found.
 # In some development versions, it's expected for some API keys that they are
 # not found.
 found = Found
 missing = Missing
@@ -97,16 +96,21 @@ unknownFailure = Blocklisted; failure co
 d3d11layersCrashGuard = D3D11 Compositor
 d3d11videoCrashGuard = D3D11 Video Decoder
 d3d9videoCrashGuard = D3D9 Video Decoder
 glcontextCrashGuard = OpenGL
 resetOnNextRestart = Reset on Next Restart
 gpuProcessKillButton = Terminate GPU Process
 gpuDeviceResetButton = Trigger Device Reset
 
+audioBackend = Audio Backend
+maxAudioChannels = Max Channels
+channelLayout = Preferred Channel Layout
+sampleRate = Preferred Sample Rate
+
 minLibVersions = Expected minimum version
 loadedLibVersions = Version in use
 
 hasSeccompBPF = Seccomp-BPF (System Call Filtering)
 hasSeccompTSync = Seccomp Thread Synchronization
 hasUserNamespaces = User Namespaces
 hasPrivilegedUserNamespaces = User Namespaces for privileged processes
 canSandboxContent = Content Process Sandboxing
@@ -144,9 +148,9 @@ keyboardEnabled = keyboard enabled
 wheelWarning = async wheel input disabled due to unsupported pref: %S
 touchWarning = async touch input disabled due to unsupported pref: %S
 
 # LOCALIZATION NOTE Strings explaining why a feature is or is not available.
 disabledByBuild = disabled by build
 enabledByDefault = enabled by default
 disabledByDefault = disabled by default
 enabledByUser = enabled by user
-disabledByUser = disabled by user
\ No newline at end of file
+disabledByUser = disabled by user
--- a/toolkit/modules/Troubleshoot.jsm
+++ b/toolkit/modules/Troubleshoot.jsm
@@ -397,18 +397,16 @@ var dataProviders = {
       data.windowLayerManagerType = "Basic";
       data.windowLayerManagerRemote = false;
     }
 
     let winUtils = Services.wm.getMostRecentWindow("").
                    QueryInterface(Ci.nsIInterfaceRequestor).
                    getInterface(Ci.nsIDOMWindowUtils)
 
-    data.currentAudioBackend = winUtils.currentAudioBackend;
-
     if (!data.numAcceleratedWindows && gfxInfo) {
       let win = AppConstants.platform == "win";
       let feature = win ? gfxInfo.FEATURE_DIRECT3D_9_LAYERS :
                           gfxInfo.FEATURE_OPENGL_LAYERS;
       data.numAcceleratedWindowsMessage = statusMsgForFeature(feature);
     }
 
     if (!gfxInfo) {
@@ -543,16 +541,59 @@ var dataProviders = {
     }
 
     data.featureLog = gfxInfo.getFeatureLog();
     data.crashGuards = gfxInfo.getActiveCrashGuards();
 
     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.currentPreferredChannelLayout = winUtils.currentPreferredChannelLayout;
+    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();
     if (winEnumer.hasMoreElements())
       data.incrementalGCEnabled = winEnumer.getNext().
                                   QueryInterface(Ci.nsIInterfaceRequestor).
                                   getInterface(Ci.nsIDOMWindowUtils).
                                   isIncrementalGCEnabled();