1 # Copyright 2017 The Chromium OS Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import logging 6 7 DEFAULT_TIMEOUT = 30 8 TELEMETRY_API = 'hrTelemetryApi' 9 10 11 class CfmMeetingsAPI(object): 12 """Utility class for interacting with CfMs.""" 13 14 def __init__(self, webview_context): 15 self._webview_context = webview_context 16 17 def _execute_telemetry_command(self, command): 18 self._webview_context.ExecuteJavaScript( 19 'window.%s.%s' % (TELEMETRY_API, command)) 20 21 def _evaluate_telemetry_command(self, command): 22 return self._webview_context.EvaluateJavaScript( 23 'window.%s.%s' % (TELEMETRY_API, command)) 24 25 # UI commands/functions 26 def wait_for_meetings_landing_page(self): 27 """Waits for the landing page screen.""" 28 self._webview_context.WaitForJavaScriptCondition( 29 'window.hasOwnProperty("%s") ' 30 '&& !window.%s.isInMeeting()' % (TELEMETRY_API, TELEMETRY_API), 31 timeout=DEFAULT_TIMEOUT) 32 logging.info('Reached meetings landing page.') 33 34 def wait_for_meetings_in_call_page(self): 35 """Waits for the in-call page to launch.""" 36 self._webview_context.WaitForJavaScriptCondition( 37 'window.hasOwnProperty("%s") ' 38 '&& window.%s.isInMeeting()' % (TELEMETRY_API, TELEMETRY_API), 39 timeout=DEFAULT_TIMEOUT) 40 logging.info('Reached meetings in-call page.') 41 42 def wait_for_telemetry_commands(self): 43 """Wait for hotrod app to load and telemetry commands to be available. 44 """ 45 raise NotImplementedError 46 47 def wait_for_oobe_start_page(self): 48 """Wait for oobe start screen to launch.""" 49 raise NotImplementedError 50 51 def skip_oobe_screen(self): 52 """Skip Chromebox for Meetings oobe screen.""" 53 raise NotImplementedError 54 55 def is_oobe_start_page(self): 56 """Check if device is on CFM oobe start screen.""" 57 raise NotImplementedError 58 59 # Hangouts commands/functions 60 def start_meeting_session(self): 61 """Start a meeting.""" 62 if self.is_in_meeting_session(): 63 self.end_meeting_session() 64 65 self._execute_telemetry_command('startMeeting()') 66 self.wait_for_meetings_in_call_page() 67 logging.info('Started meeting session.') 68 69 def join_meeting_session(self, meeting_name): 70 """Joins a meeting. 71 72 @param meeting_name: Name of the meeting session. 73 """ 74 if self.is_in_meeting_session(): 75 self.end_meeting_session() 76 77 self._execute_telemetry_command('joinMeeting("%s")' % meeting_name) 78 self.wait_for_meetings_in_call_page() 79 logging.info('Started meeting session: %s', meeting_name) 80 81 def end_meeting_session(self): 82 """End current meeting session.""" 83 self._execute_telemetry_command('endCall()') 84 self.wait_for_meetings_landing_page() 85 logging.info('Ended meeting session.') 86 87 def is_in_meeting_session(self): 88 """Check if device is in meeting session.""" 89 if self._evaluate_telemetry_command('isInMeeting()'): 90 logging.info('Is in meeting session.') 91 return True 92 logging.info('Is not in meeting session.') 93 return False 94 95 def start_new_hangout_session(self, hangout_name): 96 """Start a new hangout session. 97 98 @param hangout_name: Name of the hangout session. 99 """ 100 raise NotImplementedError 101 102 def end_hangout_session(self): 103 """End current hangout session.""" 104 raise NotImplementedError 105 106 def is_in_hangout_session(self): 107 """Check if device is in hangout session.""" 108 raise NotImplementedError 109 110 def is_ready_to_start_hangout_session(self): 111 """Check if device is ready to start a new hangout session.""" 112 raise NotImplementedError 113 114 def get_participant_count(self): 115 """Returns the total number of participants in a meeting.""" 116 return self._evaluate_telemetry_command('getParticipantCount()') 117 118 # Diagnostics commands/functions 119 def is_diagnostic_run_in_progress(self): 120 """Check if hotrod diagnostics is running.""" 121 raise NotImplementedError 122 123 def wait_for_diagnostic_run_to_complete(self): 124 """Wait for hotrod diagnostics to complete.""" 125 raise NotImplementedError 126 127 def run_diagnostics(self): 128 """Run hotrod diagnostics.""" 129 raise NotImplementedError 130 131 def get_last_diagnostics_results(self): 132 """Get latest hotrod diagnostics results.""" 133 raise NotImplementedError 134 135 # Mic audio commands/functions 136 def is_mic_muted(self): 137 """Check if mic is muted.""" 138 if self._evaluate_telemetry_command('isMicMuted()'): 139 logging.info('Mic is muted.') 140 return True 141 logging.info('Mic is not muted.') 142 return False 143 144 def mute_mic(self): 145 """Local mic mute from toolbar.""" 146 self._execute_telemetry_command('setMicMuted(true)') 147 logging.info('Locally muted mic.') 148 149 def unmute_mic(self): 150 """Local mic unmute from toolbar.""" 151 self._execute_telemetry_command('setMicMuted(false)') 152 logging.info('Locally unmuted mic.') 153 154 def get_mic_devices(self): 155 """Get all mic devices detected by hotrod.""" 156 return self._evaluate_telemetry_command('getAudioInDevices()') 157 158 def get_preferred_mic(self): 159 """Get preferred microphone for hotrod.""" 160 return self._evaluate_telemetry_command('getPreferredAudioInDevice()') 161 162 def set_preferred_mic(self, mic_name): 163 """Set preferred mic for hotrod. 164 165 @param mic_name: String with mic name. 166 """ 167 self._execute_telemetry_command('setPreferredAudioInDevice(%s)' 168 % mic_name) 169 logging.info('Setting preferred mic to %s.', mic_name) 170 171 def remote_mute_mic(self): 172 """Remote mic mute request from cPanel.""" 173 raise NotImplementedError 174 175 def remote_unmute_mic(self): 176 """Remote mic unmute request from cPanel.""" 177 raise NotImplementedError 178 179 # Speaker commands/functions 180 def get_speaker_devices(self): 181 """Get all speaker devices detected by hotrod.""" 182 return self._evaluate_telemetry_command('getAudioOutDevices()') 183 184 def get_preferred_speaker(self): 185 """Get speaker preferred for hotrod.""" 186 return self._evaluate_telemetry_command('getPreferredAudioOutDevice()') 187 188 def set_preferred_speaker(self, speaker_name): 189 """Set preferred speaker for hotrod. 190 191 @param speaker_name: String with speaker name. 192 """ 193 self._execute_telemetry_command('setPreferredAudioOutDevice(%s)' 194 % speaker_name) 195 logging.info('Set preferred speaker to %s.', speaker_name) 196 197 def set_speaker_volume(self, volume_level): 198 """Set speaker volume. 199 200 @param volume_level: Number value ranging from 0-100 to set volume to. 201 """ 202 self._execute_telemetry_command('setAudioOutVolume(%d)' % volume_level) 203 logging.info('Set speaker volume to %d', volume_level) 204 205 def get_speaker_volume(self): 206 """Get current speaker volume.""" 207 return self._evaluate_telemetry_command('getAudioOutVolume()') 208 209 def play_test_sound(self): 210 """Play test sound.""" 211 raise NotImplementedError 212 213 # Camera commands/functions 214 def get_camera_devices(self): 215 """Get all camera devices detected by hotrod. 216 217 @return List of camera devices. 218 """ 219 return self._evaluate_telemetry_command('getVideoInDevices()') 220 221 def get_preferred_camera(self): 222 """Get camera preferred for hotrod.""" 223 return self._evaluate_telemetry_command('getPreferredVideoInDevice()') 224 225 def set_preferred_camera(self, camera_name): 226 """Set preferred camera for hotrod. 227 228 @param camera_name: String with camera name. 229 """ 230 self._execute_telemetry_command('setPreferredVideoInDevice(%s)' 231 % camera_name) 232 logging.info('Set preferred camera to %s.', camera_name) 233 234 def is_camera_muted(self): 235 """Check if camera is muted (turned off).""" 236 if self._evaluate_telemetry_command('isCameraMuted()'): 237 logging.info('Camera is muted.') 238 return True 239 logging.info('Camera is not muted.') 240 return False 241 242 def mute_camera(self): 243 """Mute (turn off) camera.""" 244 self._execute_telemetry_command('setCameraMuted(true)') 245 logging.info('Camera muted.') 246 247 def unmute_camera(self): 248 """Unmute (turn on) camera.""" 249 self._execute_telemetry_command('setCameraMuted(false)') 250 logging.info('Camera unmuted.') 251 252 def move_camera(self, camera_motion): 253 """Move camera(PTZ functions). 254 255 @param camera_motion: String of the desired camera motion. 256 """ 257 ptz_motions = ['panLeft','panRight','panStop', 258 'tiltUp','tiltDown','tiltStop', 259 'zoomIn','zoomOut','resetPosition'] 260 261 if camera_motion in ptz_motions: 262 self._execute_telemetry_command('ptz.%s()' % camera_motion) 263 else: 264 raise ValueError('Unsupported PTZ camera action: "%s"' 265 % camera_motion) 266