Show:

File: app/components/exp-video-config/component.js

  1. import Em from 'ember';
  2. import layout from './template';
  3.  
  4. import ExpFrameBaseComponent from '../exp-frame-base/component';
  5. import VideoRecord from '../../mixins/video-record';
  6. import { LOOKIT_PREFERRED_DEVICES } from '../../services/video-recorder';
  7. import { observer } from '@ember/object';
  8.  
  9. let {
  10. $
  11. } = Em;
  12.  
  13. /**
  14. * @module exp-player
  15. * @submodule frames
  16. */
  17.  
  18. /**
  19. Video configuration frame guiding user through making sure permissions are set
  20. appropriately and microphone is working, with troubleshooting text. Almost all content is
  21. hard-coded, to provide a general-purpose technical setup frame.
  22.  
  23. ```json
  24. "frames": {
  25. "video-config": {
  26. "kind": "exp-video-config",
  27. "troubleshootingIntro": "If you're having any trouble getting your webcam set up,
  28. please feel free to call the XYZ lab at (123) 456-7890 and we'd be glad to
  29. help you out!"
  30. }
  31. }
  32. ```
  33.  
  34. @class Exp-video-config
  35. @extends Exp-frame-base
  36. @extends Video-record
  37. */
  38.  
  39. export default ExpFrameBaseComponent.extend(VideoRecord, {
  40. layout,
  41. showWarning: false,
  42. showWebcamPermWarning: false,
  43. checkedWebcamPermissions: false,
  44. micChecked: Em.computed.alias('recorder.micChecked'),
  45. hasCamAccess: Em.computed.alias('recorder.hasCamAccess'),
  46.  
  47. populateDropdowns() {
  48. const micSelect = $('select#audioSource')[0];
  49. const camSelect = $('select#videoSource')[0];
  50. const selectors = [micSelect, camSelect];
  51.  
  52. // Adapted from the example at https://github.com/webrtc/samples/blob/gh-pages/src/content/devices/input-output/js/main.js
  53. navigator.mediaDevices.enumerateDevices().then(function(deviceInfos) {
  54. selectors.forEach(select => {
  55. while (select.firstChild) {
  56. select.removeChild(select.firstChild);
  57. }
  58. const blankOption = document.createElement('option');
  59. blankOption.text = 'select...';
  60. blankOption.value = 123;
  61. select.appendChild(blankOption);
  62. });
  63. for (let i = 0; i !== deviceInfos.length; ++i) {
  64. const deviceInfo = deviceInfos[i];
  65. const option = document.createElement('option');
  66. option.value = deviceInfo.deviceId;
  67. if (deviceInfo.kind === 'audioinput') {
  68. option.text = deviceInfo.label || `Microphone ${micSelect.length + 1}`;
  69. if (option.value == LOOKIT_PREFERRED_DEVICES.mic) {
  70. option.selected = true;
  71. }
  72. micSelect.appendChild(option);
  73. } else if (deviceInfo.kind === 'videoinput') {
  74. option.text = deviceInfo.label || `Camera ${camSelect.length + 1}`;
  75. if (option.value == LOOKIT_PREFERRED_DEVICES.cam) {
  76. option.selected = true;
  77. }
  78. camSelect.appendChild(option);
  79. }
  80. }
  81. });
  82. },
  83.  
  84. reloadRecorder() {
  85. this.destroyRecorder();
  86. this.setupRecorder(this.$(this.get('recorderElement')));
  87. },
  88.  
  89. actions: {
  90.  
  91. checkAudioThenNext() {
  92. if (!this.get('checkedWebcamPermissions') || !this.get('micChecked') || !this.get('hasCamAccess')) {
  93. this.set('showWarning', true);
  94. } else {
  95. this.send('next');
  96. }
  97. },
  98.  
  99. reloadRecorderButton() {
  100. this.set('showWarning', false);
  101. this.populateDropdowns();
  102. this.reloadRecorder();
  103. },
  104.  
  105. reloadRecorderButtonAndRecordCheck() {
  106. this.send('reloadRecorderButton');
  107. this.set('checkedWebcamPermissions', true);
  108. },
  109.  
  110. processSelectedMic() {
  111. var selectedMicId = $('select#audioSource')[0].value;
  112. if (selectedMicId) {
  113. LOOKIT_PREFERRED_DEVICES.mic = selectedMicId;
  114. this.reloadRecorder();
  115. }
  116. },
  117.  
  118. processSelectedCam() {
  119. var selectedCamId = $('select#videoSource')[0].value;
  120. if (selectedCamId) {
  121. LOOKIT_PREFERRED_DEVICES.cam = selectedCamId;
  122. this.reloadRecorder();
  123. }
  124. }
  125. },
  126.  
  127. /**
  128. * @property {Boolean} startRecordingAutomatically
  129. * @private
  130. */
  131.  
  132. /**
  133. * @property {Boolean} showWaitForRecordingMessage
  134. * @private
  135. */
  136.  
  137. /**
  138. * @property {Boolean} waitForRecordingMessage
  139. * @private
  140. */
  141.  
  142. /**
  143. * @property {Boolean} waitForRecordingMessageColor
  144. * @private
  145. */
  146.  
  147. /**
  148. * @property {Boolean} showWaitForUploadMessage
  149. * @private
  150. */
  151.  
  152. /**
  153. * @property {Boolean} waitForUploadMessage
  154. * @private
  155. */
  156.  
  157. /**
  158. * @property {String} waitForUploadMessageColor
  159. * @private
  160. */
  161.  
  162. /**
  163. * @property {String} waitForWebcamImage
  164. * @private
  165. */
  166.  
  167. /**
  168. * @property {String} waitForWebcamVideo
  169. * @private
  170. */
  171.  
  172. frameSchemaProperties: {
  173. /**
  174. Text to show as the introduction to the troubleshooting tips section
  175. @property {String} troubleshootingIntro
  176. @default ""
  177. */
  178. troubleshootingIntro: {
  179. type: 'string',
  180. description: 'Text to show as introduction to troubleshooting tips section',
  181. default: ''
  182. }
  183. },
  184.  
  185. type: 'exp-videoconfig',
  186. meta: {
  187. data: {
  188. type: 'object',
  189. properties: {}
  190. }
  191. },
  192.  
  193. updateOptions: observer('hasCamAccess', function() {
  194. if (this.get('hasCamAccess')) {
  195. this.populateDropdowns();
  196. }
  197. }),
  198.  
  199. didInsertElement() {
  200. this._super(...arguments);
  201. this.populateDropdowns();
  202. }
  203. });
  204.  
  205.