Bug 1197045 - part3: Add audio devices information to about:support; r=felipe draft
authorChun-Min Chang <chun.m.chang@gmail.com>
Tue, 25 Jul 2017 10:46:39 +0800
changeset 614815 02c9752e8a9ff20dcff1155cacf38c11c186fa43
parent 610466 ede633f29146a7f83832278a6a77e5ccabb0e303
child 614816 7391c71063fdcaa4f1f59bd217924a978179010a
push id70140
push userbmo:cchang@mozilla.com
push dateTue, 25 Jul 2017 02:46:59 +0000
reviewersfelipe
bugs1197045
milestone56.0a1
Bug 1197045 - part3: Add audio devices information to about:support; r=felipe MozReview-Commit-ID: FoF52HG0Nou
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
@@ -436,17 +436,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;
@@ -585,16 +584,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
@@ -430,16 +430,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
@@ -134,8 +134,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
@@ -385,22 +385,16 @@ var dataProviders = {
     }
 
     // If we had no OMTC windows, report back Basic Layers.
     if (!data.windowLayerManagerType) {
       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) {
@@ -535,16 +529,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();