You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

API.js 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. import * as JitsiMeetConferenceEvents from '../../ConferenceEvents';
  2. import { parseJWTFromURLParams } from '../../react/features/jwt';
  3. import { getJitsiMeetTransport } from '../transport';
  4. import { API_ID } from './constants';
  5. declare var APP: Object;
  6. /**
  7. * List of the available commands.
  8. */
  9. let commands = {};
  10. /**
  11. * The state of screen sharing(started/stopped) before the screen sharing is
  12. * enabled and initialized.
  13. * NOTE: This flag help us to cache the state and use it if toggle-share-screen
  14. * was received before the initialization.
  15. */
  16. let initialScreenSharingState = false;
  17. /**
  18. * The transport instance used for communication with external apps.
  19. *
  20. * @type {Transport}
  21. */
  22. const transport = getJitsiMeetTransport();
  23. /**
  24. * The current audio availability.
  25. *
  26. * @type {boolean}
  27. */
  28. let audioAvailable = true;
  29. /**
  30. * The current video availability.
  31. *
  32. * @type {boolean}
  33. */
  34. let videoAvailable = true;
  35. /**
  36. * Initializes supported commands.
  37. *
  38. * @returns {void}
  39. */
  40. function initCommands() {
  41. commands = {
  42. 'display-name':
  43. APP.conference.changeLocalDisplayName.bind(APP.conference),
  44. 'toggle-audio': () => {
  45. APP.conference.toggleAudioMuted(false /* no UI */);
  46. },
  47. 'toggle-video': () => {
  48. APP.conference.toggleVideoMuted(false /* no UI */);
  49. },
  50. 'toggle-film-strip': APP.UI.toggleFilmstrip,
  51. 'toggle-chat': APP.UI.toggleChat,
  52. 'toggle-contact-list': APP.UI.toggleContactList,
  53. 'toggle-share-screen': toggleScreenSharing,
  54. 'video-hangup': () => APP.conference.hangup(),
  55. 'email': APP.conference.changeLocalEmail,
  56. 'avatar-url': APP.conference.changeLocalAvatarUrl
  57. };
  58. transport.on('event', ({ data, name }) => {
  59. if (name && commands[name]) {
  60. commands[name](...data);
  61. return true;
  62. }
  63. return false;
  64. });
  65. transport.on('request', ({ data, name }, callback) => {
  66. switch (name) {
  67. case 'is-audio-muted':
  68. callback(APP.conference.audioMuted);
  69. break;
  70. case 'is-video-muted':
  71. callback(APP.conference.videoMuted);
  72. break;
  73. case 'is-audio-available':
  74. callback(audioAvailable);
  75. break;
  76. case 'is-video-available':
  77. callback(videoAvailable);
  78. break;
  79. default:
  80. return false;
  81. }
  82. return true;
  83. });
  84. }
  85. /**
  86. * Listens for desktop/screen sharing enabled events and toggles the screen
  87. * sharing if needed.
  88. *
  89. * @param {boolean} enabled - Current screen sharing enabled status.
  90. * @returns {void}
  91. */
  92. function onDesktopSharingEnabledChanged(enabled = false) {
  93. if (enabled && initialScreenSharingState) {
  94. toggleScreenSharing();
  95. }
  96. }
  97. /**
  98. * Check whether the API should be enabled or not.
  99. *
  100. * @returns {boolean}
  101. */
  102. function shouldBeEnabled() {
  103. return (
  104. typeof API_ID === 'number'
  105. // XXX Enable the API when a JSON Web Token (JWT) is specified in
  106. // the location/URL because then it is very likely that the Jitsi
  107. // Meet (Web) app is being used by an external/wrapping (Web) app
  108. // and, consequently, the latter will need to communicate with the
  109. // former. (The described logic is merely a heuristic though.)
  110. || parseJWTFromURLParams());
  111. }
  112. /**
  113. * Executes on toggle-share-screen command.
  114. *
  115. * @returns {void}
  116. */
  117. function toggleScreenSharing() {
  118. if (APP.conference.isDesktopSharingEnabled) {
  119. APP.conference.toggleScreenSharing();
  120. } else {
  121. initialScreenSharingState = !initialScreenSharingState;
  122. }
  123. }
  124. /**
  125. * Implements API class that communicates with external API class and provides
  126. * interface to access Jitsi Meet features by external applications that embed
  127. * Jitsi Meet.
  128. */
  129. class API {
  130. /**
  131. * Initializes the API. Setups message event listeners that will receive
  132. * information from external applications that embed Jitsi Meet. It also
  133. * sends a message to the external application that API is initialized.
  134. *
  135. * @param {Object} options - Optional parameters.
  136. * @returns {void}
  137. */
  138. init() {
  139. if (!shouldBeEnabled()) {
  140. return;
  141. }
  142. /**
  143. * Current status (enabled/disabled) of API.
  144. *
  145. * @private
  146. * @type {boolean}
  147. */
  148. this._enabled = true;
  149. APP.conference.addListener(
  150. JitsiMeetConferenceEvents.DESKTOP_SHARING_ENABLED_CHANGED,
  151. onDesktopSharingEnabledChanged);
  152. initCommands();
  153. }
  154. /**
  155. * Sends event to the external application.
  156. *
  157. * @param {Object} event - The event to be sent.
  158. * @returns {void}
  159. */
  160. _sendEvent(event = {}) {
  161. if (this._enabled) {
  162. transport.sendEvent(event);
  163. }
  164. }
  165. /**
  166. * Notify external application (if API is enabled) that message was sent.
  167. *
  168. * @param {string} message - Message body.
  169. * @returns {void}
  170. */
  171. notifySendingChatMessage(message) {
  172. this._sendEvent({
  173. name: 'outgoing-message',
  174. message
  175. });
  176. }
  177. /**
  178. * Notify external application (if API is enabled) that message was
  179. * received.
  180. *
  181. * @param {Object} options - Object with the message properties.
  182. * @returns {void}
  183. */
  184. notifyReceivedChatMessage({ body, id, nick, ts } = {}) {
  185. if (APP.conference.isLocalId(id)) {
  186. return;
  187. }
  188. this._sendEvent({
  189. name: 'incoming-message',
  190. from: id,
  191. message: body,
  192. nick,
  193. stamp: ts
  194. });
  195. }
  196. /**
  197. * Notify external application (if API is enabled) that user joined the
  198. * conference.
  199. *
  200. * @param {string} id - User id.
  201. * @returns {void}
  202. */
  203. notifyUserJoined(id) {
  204. this._sendEvent({
  205. name: 'participant-joined',
  206. id
  207. });
  208. }
  209. /**
  210. * Notify external application (if API is enabled) that user left the
  211. * conference.
  212. *
  213. * @param {string} id - User id.
  214. * @returns {void}
  215. */
  216. notifyUserLeft(id) {
  217. this._sendEvent({
  218. name: 'participant-left',
  219. id
  220. });
  221. }
  222. /**
  223. * Notify external application (if API is enabled) that user changed their
  224. * nickname.
  225. *
  226. * @param {string} id - User id.
  227. * @param {string} displayname - User nickname.
  228. * @returns {void}
  229. */
  230. notifyDisplayNameChanged(id, displayname) {
  231. this._sendEvent({
  232. name: 'display-name-change',
  233. displayname,
  234. id
  235. });
  236. }
  237. /**
  238. * Notify external application (if API is enabled) that the conference has
  239. * been joined.
  240. *
  241. * @param {string} roomName - The room name.
  242. * @returns {void}
  243. */
  244. notifyConferenceJoined(roomName) {
  245. this._sendEvent({
  246. name: 'video-conference-joined',
  247. roomName
  248. });
  249. }
  250. /**
  251. * Notify external application (if API is enabled) that user changed their
  252. * nickname.
  253. *
  254. * @param {string} roomName - User id.
  255. * @returns {void}
  256. */
  257. notifyConferenceLeft(roomName) {
  258. this._sendEvent({
  259. name: 'video-conference-left',
  260. roomName
  261. });
  262. }
  263. /**
  264. * Notify external application (if API is enabled) that we are ready to be
  265. * closed.
  266. *
  267. * @returns {void}
  268. */
  269. notifyReadyToClose() {
  270. this._sendEvent({ name: 'video-ready-to-close' });
  271. }
  272. /**
  273. * Notify external application (if API is enabled) for audio muted status
  274. * changed.
  275. *
  276. * @param {boolean} muted - The new muted status.
  277. * @returns {void}
  278. */
  279. notifyAudioMutedStatusChanged(muted) {
  280. this._sendEvent({
  281. name: 'audio-mute-status-changed',
  282. muted
  283. });
  284. }
  285. /**
  286. * Notify external application (if API is enabled) for video muted status
  287. * changed.
  288. *
  289. * @param {boolean} muted - The new muted status.
  290. * @returns {void}
  291. */
  292. notifyVideoMutedStatusChanged(muted) {
  293. this._sendEvent({
  294. name: 'video-mute-status-changed',
  295. muted
  296. });
  297. }
  298. /**
  299. * Notify external application (if API is enabled) for audio availability
  300. * changed.
  301. *
  302. * @param {boolean} available - True if available and false otherwise.
  303. * @returns {void}
  304. */
  305. notifyAudioAvailabilityChanged(available) {
  306. audioAvailable = available;
  307. this._sendEvent({
  308. name: 'audio-availability-changed',
  309. available
  310. });
  311. }
  312. /**
  313. * Notify external application (if API is enabled) for video available
  314. * status changed.
  315. *
  316. * @param {boolean} available - True if available and false otherwise.
  317. * @returns {void}
  318. */
  319. notifyVideoAvailabilityChanged(available) {
  320. videoAvailable = available;
  321. this._sendEvent({
  322. name: 'video-availability-changed',
  323. available
  324. });
  325. }
  326. /**
  327. * Disposes the allocated resources.
  328. *
  329. * @returns {void}
  330. */
  331. dispose() {
  332. if (this._enabled) {
  333. this._enabled = false;
  334. APP.conference.removeListener(
  335. JitsiMeetConferenceEvents.DESKTOP_SHARING_ENABLED_CHANGED,
  336. onDesktopSharingEnabledChanged);
  337. }
  338. }
  339. }
  340. export default new API();