Earcon.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /* *
  2. *
  3. * (c) 2009-2019 Øystein Moseng
  4. *
  5. * Earcons for the sonification module in Highcharts.
  6. *
  7. * License: www.highcharts.com/license
  8. *
  9. * */
  10. 'use strict';
  11. import H from '../../parts/Globals.js';
  12. /**
  13. * Define an Instrument and the options for playing it.
  14. *
  15. * @requires module:modules/sonification
  16. *
  17. * @interface Highcharts.EarconInstrument
  18. *//**
  19. * An instrument instance or the name of the instrument in the
  20. * Highcharts.sonification.instruments map.
  21. * @name Highcharts.EarconInstrument#instrument
  22. * @type {Highcharts.Instrument|String}
  23. *//**
  24. * The options to pass to Instrument.play.
  25. * @name Highcharts.EarconInstrument#playOptions
  26. * @type {object}
  27. */
  28. /**
  29. * Options for an Earcon.
  30. *
  31. * @requires module:modules/sonification
  32. *
  33. * @interface Highcharts.EarconOptionsObject
  34. *//**
  35. * The instruments and their options defining this earcon.
  36. * @name Highcharts.EarconOptionsObject#instruments
  37. * @type {Array<Highcharts.EarconInstrument>}
  38. *//**
  39. * The unique ID of the Earcon. Generated if not supplied.
  40. * @name Highcharts.EarconOptionsObject#id
  41. * @type {string|undefined}
  42. *//**
  43. * Global panning of all instruments. Overrides all panning on individual
  44. * instruments. Can be a number between -1 and 1.
  45. * @name Highcharts.EarconOptionsObject#pan
  46. * @type {number|undefined}
  47. *//**
  48. * Master volume for all instruments. Volume settings on individual instruments
  49. * can still be used for relative volume between the instruments. This setting
  50. * does not affect volumes set by functions in individual instruments. Can be a
  51. * number between 0 and 1. Defaults to 1.
  52. * @name Highcharts.EarconOptionsObject#volume
  53. * @type {number|undefined}
  54. *//**
  55. * Callback function to call when earcon has finished playing.
  56. * @name Highcharts.EarconOptionsObject#onEnd
  57. * @type {Function|undefined}
  58. */
  59. /**
  60. * The Earcon class. Earcon objects represent a certain sound consisting of
  61. * one or more instruments playing a predefined sound.
  62. *
  63. * @sample highcharts/sonification/earcon/
  64. * Using earcons directly
  65. *
  66. * @requires module:modules/sonification
  67. *
  68. * @class
  69. * @name Highcharts.Earcon
  70. *
  71. * @param {Highcharts.EarconOptionsObject} options
  72. * Options for the Earcon instance.
  73. */
  74. function Earcon(options) {
  75. this.init(options || {});
  76. }
  77. Earcon.prototype.init = function (options) {
  78. this.options = options;
  79. if (!this.options.id) {
  80. this.options.id = this.id = H.uniqueKey();
  81. }
  82. this.instrumentsPlaying = {};
  83. };
  84. /**
  85. * Play the earcon, optionally overriding init options.
  86. *
  87. * @sample highcharts/sonification/earcon/
  88. * Using earcons directly
  89. *
  90. * @function Highcharts.Earcon#sonify
  91. *
  92. * @param {Highcharts.EarconOptionsObject} options
  93. * Override existing options.
  94. */
  95. Earcon.prototype.sonify = function (options) {
  96. var playOptions = H.merge(this.options, options);
  97. // Find master volume/pan settings
  98. var masterVolume = H.pick(playOptions.volume, 1),
  99. masterPan = playOptions.pan,
  100. earcon = this,
  101. playOnEnd = options && options.onEnd,
  102. masterOnEnd = earcon.options.onEnd;
  103. // Go through the instruments and play them
  104. playOptions.instruments.forEach(function (opts) {
  105. var instrument = typeof opts.instrument === 'string' ?
  106. H.sonification.instruments[opts.instrument] : opts.instrument,
  107. instrumentOpts = H.merge(opts.playOptions),
  108. instrOnEnd,
  109. instrumentCopy,
  110. copyId;
  111. if (instrument && instrument.play) {
  112. if (opts.playOptions) {
  113. // Handle master pan/volume
  114. if (typeof opts.playOptions.volume !== 'function') {
  115. instrumentOpts.volume = H.pick(masterVolume, 1) *
  116. H.pick(opts.playOptions.volume, 1);
  117. }
  118. instrumentOpts.pan = H.pick(masterPan, instrumentOpts.pan);
  119. // Handle onEnd
  120. instrOnEnd = instrumentOpts.onEnd;
  121. instrumentOpts.onEnd = function () {
  122. delete earcon.instrumentsPlaying[copyId];
  123. if (instrOnEnd) {
  124. instrOnEnd.apply(this, arguments);
  125. }
  126. if (!Object.keys(earcon.instrumentsPlaying).length) {
  127. if (playOnEnd) {
  128. playOnEnd.apply(this, arguments);
  129. }
  130. if (masterOnEnd) {
  131. masterOnEnd.apply(this, arguments);
  132. }
  133. }
  134. };
  135. // Play the instrument. Use a copy so we can play multiple at
  136. // the same time.
  137. instrumentCopy = instrument.copy();
  138. copyId = instrumentCopy.id;
  139. earcon.instrumentsPlaying[copyId] = instrumentCopy;
  140. instrumentCopy.play(instrumentOpts);
  141. }
  142. } else {
  143. H.error(30);
  144. }
  145. });
  146. };
  147. /**
  148. * Cancel any current sonification of the Earcon. Calls onEnd functions.
  149. *
  150. * @function Highcharts.Earcon#cancelSonify
  151. *
  152. * @param {boolean} [fadeOut=false]
  153. * Whether or not to fade out as we stop. If false, the earcon is
  154. * cancelled synchronously.
  155. */
  156. Earcon.prototype.cancelSonify = function (fadeOut) {
  157. var playing = this.instrumentsPlaying,
  158. instrIds = playing && Object.keys(playing);
  159. if (instrIds && instrIds.length) {
  160. instrIds.forEach(function (instr) {
  161. playing[instr].stop(!fadeOut, null, 'cancelled');
  162. });
  163. this.instrumentsPlaying = {};
  164. }
  165. };
  166. export default Earcon;