audio.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /**
  2. * GNU MediaGoblin -- federated, autonomous media hosting
  3. * Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. var audioPlayer = new Object();
  19. (function (audioPlayer) {
  20. audioPlayer.init = function (audioElement) {
  21. audioPlayer.audioElement = audioElement;
  22. console.log(audioElement);
  23. attachEvents();
  24. $(audioElement).hide();
  25. };
  26. function attachEvents () {
  27. audioPlayer.audioElement.addEventListener(
  28. 'durationchange', audioPlayer.durationChange, true);
  29. audioPlayer.audioElement.addEventListener(
  30. 'timeupdate', audioPlayer.timeUpdate, true);
  31. audioPlayer.audioElement.addEventListener(
  32. 'progress', audioPlayer.onProgress, true);
  33. audioPlayer.audioElement.addEventListener(
  34. 'ended', audioPlayer.onEnded, true);
  35. $(document).ready( function () {
  36. $('.audio-spectrogram').delegate(
  37. '.seekbar', 'click', audioPlayer.onSeek);
  38. $('.audio-spectrogram').delegate(
  39. '.audio-control-play-pause', 'click', audioPlayer.playPause);
  40. $('.audio-spectrogram').delegate(
  41. '.audio-volume', 'change', audioPlayer.onVolumeChange);
  42. $('.audio-media').delegate(
  43. '.audio-spectrogram', 'attachedControls',
  44. audioPlayer.onControlsAttached);
  45. });
  46. }
  47. audioPlayer.onVolumeChange = function(e) {
  48. console.log('volume change', e);
  49. audioPlayer.audioElement.volume = e.target.value;
  50. }
  51. audioPlayer.onControlsAttached = function(e) {
  52. console.log('Controls attached', e);
  53. $('.audio-spectrogram .audio-volume').val(
  54. Math.round(audioPlayer.audioElement.volume, 2));
  55. }
  56. audioPlayer.onProgress = function(e) {
  57. /**
  58. * Handler for file download progress
  59. */
  60. console.log(e);
  61. var buffered = audioPlayer.audioElement.buffered;
  62. ranges = new Array();
  63. var indicators = $('.audio-spectrogram .buffered-indicators div');
  64. for (var i = 0; i < buffered.length; i++) {
  65. if (!(i in indicators)) {
  66. $('<div style="display: none;"></div>')
  67. .appendTo($('.audio-spectrogram .buffered-indicators'))
  68. .fadeIn(500);
  69. indicators = $('.audio-spectrogram .buffered-indicators div');
  70. }
  71. var posStart = ((buffered.start(i) / audioPlayer.audioElement.duration)
  72. * audioPlayer.imageElement.width());
  73. var posStop = ((buffered.end(i) / audioPlayer.audioElement.duration)
  74. * audioPlayer.imageElement.width());
  75. console.log('indicators', indicators);
  76. var indicator = $(indicators[i]);
  77. indicator.css('left', posStart);
  78. indicator.css('width', posStop - posStart);
  79. }
  80. /*
  81. * Clean up unused indicators
  82. */
  83. if (indicators.length > buffered.length) {
  84. for (var i = buffered.length; i < indicators.length; i++) {
  85. $(indicators[i]).fadeOut(500, function () {
  86. this.remove();
  87. });
  88. }
  89. }
  90. };
  91. audioPlayer.onSeek = function (e) {
  92. /**
  93. * Callback handler for seek event, which is a .click() event on the
  94. * .seekbar element
  95. */
  96. console.log('onSeek', e);
  97. var im = audioPlayer.imageElement;
  98. var pos = (e.offsetX || e.originalEvent.layerX) / im.width();
  99. audioPlayer.audioElement.currentTime = pos * audioPlayer.audioElement.duration;
  100. audioPlayer.audioElement.play();
  101. audioPlayer.setState(audioPlayer.PLAYING);
  102. };
  103. audioPlayer.onEnded = function (e) {
  104. audioPlayer.setState(audioPlayer.PAUSED);
  105. }
  106. audioPlayer.playPause = function (e) {
  107. console.log('playPause', e);
  108. if (audioPlayer.audioElement.paused) {
  109. audioPlayer.audioElement.play();
  110. audioPlayer.setState(audioPlayer.PLAYING);
  111. } else {
  112. audioPlayer.audioElement.pause();
  113. audioPlayer.setState(audioPlayer.PAUSED);
  114. }
  115. };
  116. audioPlayer.NULL = null;
  117. audioPlayer.PLAYING = 2;
  118. audioPlayer.PAUSED = 4;
  119. audioPlayer.state = audioPlayer.NULL;
  120. audioPlayer.setState = function (state) {
  121. if (state == audioPlayer.state) {
  122. return;
  123. } else {
  124. audioPlayer.state = state;
  125. }
  126. switch (state) {
  127. case audioPlayer.PLAYING:
  128. $('.audio-spectrogram .audio-control-play-pause')
  129. .removeClass('paused').addClass('playing')
  130. .text('▮▮');
  131. break;
  132. case audioPlayer.PAUSED:
  133. $('.audio-spectrogram .audio-control-play-pause')
  134. .removeClass('playing').addClass('paused')
  135. .text('▶');
  136. break;
  137. }
  138. };
  139. audioPlayer.durationChange = function () {
  140. // ???
  141. };
  142. audioPlayer.timeUpdate = function () {
  143. /**
  144. * Callback handler for the timeupdate event, responsible for
  145. * updating the playhead
  146. */
  147. var currentTime = audioPlayer.audioElement.currentTime;
  148. var playhead = audioPlayer.imageElement.parent().find('.playhead');
  149. playhead.css('width', (currentTime / audioPlayer.audioElement.duration)
  150. * audioPlayer.imageElement.width());
  151. var time = formatTime(currentTime);
  152. var duration = formatTime(audioPlayer.audioElement.duration);
  153. audioPlayer.imageElement.parent()
  154. .find('.audio-currentTime')
  155. .text(time + '/' + duration);
  156. };
  157. function formatTime(seconds) {
  158. /**
  159. * Format a time duration in (hh:)?mm:ss manner
  160. */
  161. var h = Math.floor(seconds / (60 * 60));
  162. var m = Math.floor((seconds - h * 60 * 60) / 60);
  163. var s = Math.round(seconds - h * 60 * 60 - m * 60);
  164. return '' + (h ? (h < 10 ? '0' + h : h) + ':' : '') + (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
  165. }
  166. audioPlayer.formatTime = formatTime;
  167. audioPlayer.attachToImage = function (imageElement) {
  168. /**
  169. * Attach the player to an image element
  170. */
  171. console.log(imageElement);
  172. var im = $(imageElement);
  173. audioPlayer.imageElement = im;
  174. $('<div class="playhead"></div>').appendTo(im.parent());
  175. $('<div class="buffered-indicators"></div>').appendTo(im.parent());
  176. $('<div class="seekbar"></div>').appendTo(im.parent());
  177. $('<div class="audio-control-play-pause paused">▶</div>').appendTo(im.parent());
  178. $('<div class="audio-currentTime">00:00</div>').appendTo(im.parent());
  179. $('<input type="range" class="audio-volume"'
  180. +'value="1" min="0" max="1" step="0.001" />').appendTo(im.parent());
  181. $('.audio-spectrogram').trigger('attachedControls');
  182. };
  183. })(audioPlayer);
  184. $(document).ready(function () {
  185. if (!$('.audio-media').length) {
  186. return;
  187. }
  188. console.log('Initializing audio player');
  189. audioElements = $('.audio-media .audio-player');
  190. audioPlayer.init(audioElements[0]);
  191. audioPlayer.attachToImage($('.audio-spectrogram img')[0]);
  192. });