diff --git a/libraries/wavesurfer/.babelrc b/libraries/wavesurfer/.babelrc new file mode 100644 index 000000000..94b38c1c4 --- /dev/null +++ b/libraries/wavesurfer/.babelrc @@ -0,0 +1,14 @@ +{ + "presets": [ + ["es2015", "stage-0"] + ], + "plugins": [ + "transform-class-properties", + "add-module-exports" + ], + "env": { + "test": { + "plugins": [ "istanbul" ] + } + } +} diff --git a/libraries/wavesurfer/.editorconfig b/libraries/wavesurfer/.editorconfig new file mode 100644 index 000000000..48a18f15f --- /dev/null +++ b/libraries/wavesurfer/.editorconfig @@ -0,0 +1,11 @@ +# http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/libraries/wavesurfer/.esdoc.json b/libraries/wavesurfer/.esdoc.json new file mode 100644 index 000000000..ea7243b8c --- /dev/null +++ b/libraries/wavesurfer/.esdoc.json @@ -0,0 +1,20 @@ +{ + "source": "./src", + "destination": "./doc", + "title": "wavesurfer.js documentation", + "styles": ["example/css/doc.css"], + "lint": true, + "builtinExternal": true, + "experimentalProposal": { + "classProperties": true, + "objectRestSpread": true, + "exportExtensions": true + }, + "test": { + "type": "mocha", + "source": "spec" + }, + "manual": { + "changelog": ["CHANGES.md"] + } +} diff --git a/libraries/wavesurfer/.eslintrc.js b/libraries/wavesurfer/.eslintrc.js new file mode 100644 index 000000000..76594892d --- /dev/null +++ b/libraries/wavesurfer/.eslintrc.js @@ -0,0 +1,279 @@ +module.exports = { + "env": { + "browser": true, + "commonjs": true, + "es6": true + }, + "extends": "eslint:recommended", + "parser": "babel-eslint", + "parserOptions": { + "ecmaVersion": 7, + "sourceType": "module", + "ecmaFeatures": { + "classes": true + }, + }, + "rules": { + "accessor-pairs": "error", + "array-bracket-spacing": "error", + "array-callback-return": "error", + "arrow-body-style": "error", + "arrow-parens": "off", + "arrow-spacing": [ + "error", + { + "after": true, + "before": true + } + ], + "block-scoped-var": "off", + "block-spacing": [ + "error", + "always" + ], + "brace-style": [ + "error", + "1tbs", + { + "allowSingleLine": true + } + ], + "callback-return": "off", + "camelcase": "error", + "class-methods-use-this": "off", + "comma-dangle": "error", + "comma-spacing": [ + "error", + { + "after": true, + "before": false + } + ], + "comma-style": [ + "error", + "last" + ], + "complexity": "error", + "computed-property-spacing": [ + "error", + "never" + ], + "consistent-return": "off", + "consistent-this": "off", + "curly": "error", + "default-case": "off", + "dot-location": "off", + "dot-notation": "error", + "eol-last": "error", + "eqeqeq": "off", + "func-call-spacing": "error", + "func-name-matching": "error", + "func-names": [ + "error", + "never" + ], + "func-style": "off", + "generator-star-spacing": "error", + "global-require": "error", + "guard-for-in": "off", + "handle-callback-err": "error", + "id-blacklist": "error", + "id-length": "off", + "id-match": "error", + "indent": [2, 4, { "SwitchCase": 1 }], + "init-declarations": "off", + "jsx-quotes": "error", + "key-spacing": "off", + "keyword-spacing": [ + "error", + { + "after": true, + "before": true + } + ], + "line-comment-position": "off", + "linebreak-style": [ + "error", + "unix" + ], + "lines-around-comment": "off", + "lines-around-directive": "error", + "max-depth": "error", + "max-len": "off", + "max-lines": "off", + "max-nested-callbacks": "error", + "max-params": "off", + "max-statements": "off", + "max-statements-per-line": "off", + "multiline-ternary": "off", + "new-cap": "error", + "new-parens": "off", + "newline-after-var": "off", + "newline-before-return": "off", + "newline-per-chained-call": "off", + "no-redeclare": "error", + "no-unused-vars": "off", + "no-console": "off", + "no-alert": "error", + "no-array-constructor": "error", + "no-bitwise": "off", + "no-caller": "error", + "no-catch-shadow": "error", + "no-confusing-arrow": [ + "error", + { + "allowParens": true + } + ], + "no-continue": "error", + "no-div-regex": "error", + "no-duplicate-imports": "error", + "no-else-return": "error", + "no-empty-function": "off", + "no-eq-null": "off", + "no-eval": "error", + "no-extend-native": "error", + "no-extra-bind": "error", + "no-extra-label": "error", + "no-extra-parens": "off", + "no-floating-decimal": "error", + "no-implicit-coercion": "off", + "no-implicit-globals": "error", + "no-implied-eval": "error", + "no-inline-comments": "off", + "no-inner-declarations": [ + "error", + "functions" + ], + "no-invalid-this": "off", + "no-iterator": "error", + "no-label-var": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-lonely-if": "error", + "no-loop-func": "error", + "no-magic-numbers": "off", + "no-mixed-operators": "off", + "no-mixed-requires": "error", + "no-multi-spaces": "error", + "no-multi-str": "error", + "no-multiple-empty-lines": "off", + "no-native-reassign": "error", + "no-negated-condition": "off", + "no-negated-in-lhs": "error", + "no-nested-ternary": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-object": "error", + "no-new-require": "error", + "no-new-wrappers": "error", + "no-octal-escape": "error", + "no-param-reassign": "off", + "no-path-concat": "error", + "no-plusplus": "off", + "no-process-env": "error", + "no-process-exit": "error", + "no-proto": "error", + "no-prototype-builtins": "error", + "no-restricted-globals": "error", + "no-restricted-imports": "error", + "no-restricted-modules": "error", + "no-restricted-properties": "error", + "no-restricted-syntax": "error", + "no-return-assign": "error", + "no-script-url": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-shadow": "off", + "no-shadow-restricted-names": "error", + "no-spaced-func": "error", + "no-sync": "error", + "no-tabs": "off", + "no-template-curly-in-string": "error", + "no-ternary": "off", + "no-throw-literal": "off", + "no-trailing-spaces": "error", + "no-undef-init": "error", + "no-undefined": "off", + "no-underscore-dangle": "off", + "no-unmodified-loop-condition": "error", + "no-unneeded-ternary": "error", + "no-use-before-define": "error", + "no-useless-call": "error", + "no-useless-computed-key": "error", + "no-useless-concat": "error", + "no-useless-constructor": "off", + "no-useless-escape": "error", + "no-useless-rename": "error", + "no-useless-return": "error", + "no-var": "error", + "no-void": "error", + "no-warning-comments": "off", + "no-whitespace-before-property": "error", + "no-with": "error", + "object-curly-newline": "off", + "object-curly-spacing": "off", + "object-property-newline": "off", + "object-shorthand": [ + "error", + "methods", + { + avoidQuotes: true + } + ], + "one-var": [ + "error", + { + var: "never", + let: "never", + const: "never" + } + ], + "one-var-declaration-per-line": "error", + "operator-assignment": "off", + "operator-linebreak": "off", + "padded-blocks": "off", + "prefer-arrow-callback": "error", + "prefer-const": "error", + "prefer-numeric-literals": "error", + "prefer-reflect": "off", + "prefer-rest-params": "error", + "prefer-spread": "error", + "prefer-template": "off", + "quote-props": "off", + "quotes": [ + "error", + "single" + ], + "radix": "off", + "require-jsdoc": "error", + "rest-spread-spacing": "error", + "semi": "error", + "semi-spacing": "error", + "sort-imports": "off", + "sort-keys": "off", + "sort-vars": "off", + "space-before-blocks": "off", + "space-before-function-paren": "off", + "space-in-parens": [ + "error", + "never" + ], + "space-infix-ops": "off", + "space-unary-ops": "off", + "spaced-comment": "off", + "strict": "error", + "symbol-description": "error", + "template-curly-spacing": "error", + "unicode-bom": [ + "error", + "never" + ], + "valid-jsdoc": "off", + "vars-on-top": "off", + "wrap-iife": "error", + "wrap-regex": "error", + "yield-star-spacing": "error", + "yoda": "off" + } +}; diff --git a/libraries/wavesurfer/.github/ISSUE_TEMPLATE.md b/libraries/wavesurfer/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..4634e3bac --- /dev/null +++ b/libraries/wavesurfer/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,26 @@ +# Hey, thank you for testing and contributing to wavesurfer.js! + +## Please make sure you can check all of these points below before opening an issue: + +(You don't have to post this section) + +- [ ] I have checked [the FAQ](https://wavesurfer-js.org/faq/) and it doesn't solve my problem. +- [ ] I have checked [the documentation](https://wavesurfer-js.org/docs/) and it doesn't solve my problem +- [ ] I have searched for [already open issues](https://github.com/katspaugh/wavesurfer.js/issues) which desribe my problem. +- [ ] The issue I'm having is related to and caused by wavesurfer.js, not by other software (which maybe packages and uses wavesurfer incorrectly) – In that case you should open the issue on the respective project pages. + +## Please make sure you provide the following information (if applicable): + +### Wavesurfer.js version(s): + + +### Browser version(s): + + +### Code needed to reproduce the issue: + +(Please reduce your code as much as possible and only post the minimum code needed to reproduce the issue. [A Code pen](http://codepen.io/) is an excellent way to share such code) + + +### Use behaviour needed to reproduce the issue: + diff --git a/libraries/wavesurfer/.github/PULL_REQUEST_TEMPLATE.md b/libraries/wavesurfer/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..f9002b067 --- /dev/null +++ b/libraries/wavesurfer/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,21 @@ +# Hey, thank you for contributing to wavesurfer.js! + +To review/merge open PRs it is very helpful to know as much as possible about the changes which are being introduced. Reviewing PRs is very time consuming, please be patient, it can take some time to do properly. + +**Title:** Please make sure the name of your PR is as descriptive as possible (Describe the feature that is introduced or the bug that is being fixed). + +## Please make sure you provide the information below: + +### Short description of changes: + + +### Breaking in the external API: + + +### Breaking changes in the internal API: + + +### Todos/Notes: + + +### Related Issues and other PRs: diff --git a/libraries/wavesurfer/.gitignore b/libraries/wavesurfer/.gitignore new file mode 100644 index 000000000..fa55af572 --- /dev/null +++ b/libraries/wavesurfer/.gitignore @@ -0,0 +1,13 @@ +dist/wavesurfer.dev.js +dist/plugin/*.js +!/dist/plugin/*.min.js +dist/**/*.map +/node_modules +/bower_components +/npm-debug.log +/.grunt +/coverage +/_SpecRunner.html +.DS_Store +.idea +.project diff --git a/libraries/wavesurfer/.jscsrc b/libraries/wavesurfer/.jscsrc new file mode 100644 index 000000000..0ca4de394 --- /dev/null +++ b/libraries/wavesurfer/.jscsrc @@ -0,0 +1,7 @@ +{ + "disallowTrailingWhitespace": true, + "disallowMixedSpacesAndTabs": true, + "requirePaddingNewLinesAfterUseStrict": true, + "requireSpaceAfterComma": true, + "requireSpaceBetweenArguments": true +} \ No newline at end of file diff --git a/libraries/wavesurfer/.npmignore b/libraries/wavesurfer/.npmignore new file mode 100644 index 000000000..0f62610c4 --- /dev/null +++ b/libraries/wavesurfer/.npmignore @@ -0,0 +1,4 @@ +# exclude everything except dist and src +**/* +!dist/** +!src/** diff --git a/libraries/wavesurfer/.travis.yml b/libraries/wavesurfer/.travis.yml new file mode 100644 index 000000000..fdce43390 --- /dev/null +++ b/libraries/wavesurfer/.travis.yml @@ -0,0 +1,17 @@ +sudo: required +dist: trusty +language: node_js +node_js: + - "6.9.4" +before_install: + - export CHROME_BIN=chromium-browser + - export DISPLAY=:99.0 + - sh -e /etc/init.d/xvfb start +install: + - npm prune + - npm install + - npm update +script: + - npm run test + - npm run build + - npm run doc diff --git a/libraries/wavesurfer/CHANGES.md b/libraries/wavesurfer/CHANGES.md new file mode 100644 index 000000000..aad51d344 --- /dev/null +++ b/libraries/wavesurfer/CHANGES.md @@ -0,0 +1,26 @@ +wavesurfer.js changelog +======================= + +1.2.4 (11.11.2016) +------------------ +- Fix a problem of Web Audio not playing in Safari on initial load (#749) + +1.2.3 (09.11.2016) +------------------ + +- Add a 'waveform-ready' event, triggered when waveform is drawn with MediaElement backend (#736) +- Add a 'preload' parameter to load function to choose the preload HTML5 audio attribute value if MediaElement backend is choosen (#854) + +1.2.2 (31.10.2016) +------------------ + +- Determistic way to mute and unmute a track (#841) +- Replace jasmine with karma / jasmine test suite (#849) +- Regions plugin: fix a bug when clicking on scroll-bar in Firefox (#851) + +1.2.1 (01.10.2016) +------------------ + +- Added changelog (#824) +- Correct AMD module name for plugins (#831) +- Fix to remove small gaps between regions (#834) diff --git a/libraries/wavesurfer/CNAME b/libraries/wavesurfer/CNAME new file mode 100644 index 000000000..c2b93c991 --- /dev/null +++ b/libraries/wavesurfer/CNAME @@ -0,0 +1 @@ +wavesurfer-js.org diff --git a/libraries/wavesurfer/LICENSE b/libraries/wavesurfer/LICENSE new file mode 100644 index 000000000..6749f6eab --- /dev/null +++ b/libraries/wavesurfer/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2012-2017, katspaugh and contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/libraries/wavesurfer/README.md b/libraries/wavesurfer/README.md new file mode 100644 index 000000000..b75d06879 --- /dev/null +++ b/libraries/wavesurfer/README.md @@ -0,0 +1,193 @@ +# [wavesurfer.js](https://wavesurfer-js.org) + +# Read below how to update to version 2! + +[![npm version](https://img.shields.io/npm/v/wavesurfer.js.svg?style=flat)](https://www.npmjs.com/package/wavesurfer.js) +![npm](https://img.shields.io/npm/dm/wavesurfer.js.svg) [![Join the chat at https://gitter.im/katspaugh/wavesurfer.js](https://badges.gitter.im/katspaugh/wavesurfer.js.svg)](https://gitter.im/katspaugh/wavesurfer.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +Interactive navigable audio visualization using Web Audio and Canvas. + +[![Screenshot](https://raw.githubusercontent.com/katspaugh/wavesurfer.js/gh-pages/example/screenshot.png "Screenshot")](https://wavesurfer-js.org) + +See a [tutorial](https://wavesurfer-js.org/docs) and [examples](https://wavesurfer-js.org/examples) on [wavesurfer-js.org](https://wavesurfer-js.org). + +## Browser support +wavesurfer.js works only in [modern browsers supporting Web Audio](http://caniuse.com/audio-api). + +It will fallback to Audio Element in other browsers (without graphics). You can also try [wavesurfer.swf](https://github.com/laurentvd/wavesurfer.swf) which is a Flash-based fallback. + +## FAQ +### Can the audio start playing before the waveform is drawn? +Yes, if you use the `backend: 'MediaElement'` option. See here: https://wavesurfer-js.org/example/audio-element/. The audio will start playing as you press play. A thin line will be displayed until the whole audio file is downloaded and decoded to draw the waveform. + +### Can drawing be done as file loads? +No. Web Audio needs the whole file to decode it in the browser. You can however load pre-decoded waveform data to draw the waveform immediately. See here: https://wavesurfer-js.org/example/audio-element/ (the "Pre-recoded Peaks" section). + +## API in examples + +Choose a container: +```html +
+``` +Create an instance, passing the container selector and [options](https://wavesurfer-js.org/docs/options.html): + +```javascript +var wavesurfer = WaveSurfer.create({ + container: '#waveform', + waveColor: 'violet', + progressColor: 'purple' +}); +``` + +Subscribe to some [events](https://wavesurfer-js.org/docs/events.html): + +```javascript +wavesurfer.on('ready', function () { + wavesurfer.play(); +}); +``` + +Load an audio file from a URL: + +```javascript +wavesurfer.load('example/media/demo.wav'); +``` + +## Documentation + +See the documentation on all available [methods](https://wavesurfer-js.org/docs/methods.html), [options](https://wavesurfer-js.org/docs/options.html) and [events](https://wavesurfer-js.org/docs/events.html) on the [homepage](https://wavesurfer-js.org/docs/). + +**Note on version 2**: The wavesurfer.js core library and the plugins were refactored to be modular so it can be used with a module bundler. (You can still use wavesurfer without, e.g. with ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/wavesurfer/example/angular-material/main.css b/libraries/wavesurfer/example/angular-material/main.css new file mode 100644 index 000000000..77d94afc7 --- /dev/null +++ b/libraries/wavesurfer/example/angular-material/main.css @@ -0,0 +1,35 @@ +.text-center { + text-align: center !important; +} + +.text-left { + text-align: left !important;; +} + +.text-right { + text-align: right !important;; +} + +.text-justify { + text-align: justify !important;; +} + +md-icon[md-font-icon] { + font-size: 24px; +} + +md-toolbar.md-toolbar-sm .md-toolbar-tools { + max-height: 32px; + padding: 6px; + font-size: 16px; +} + +md-toolbar.md-toolbar-sm { + min-height: 24px; +} +.md-player-controls .md-button { + min-width: 44px; +} + + + diff --git a/libraries/wavesurfer/example/angular-material/main.js b/libraries/wavesurfer/example/angular-material/main.js new file mode 100644 index 000000000..ff5f488d5 --- /dev/null +++ b/libraries/wavesurfer/example/angular-material/main.js @@ -0,0 +1,21 @@ +/** + * Created by intelWorx on 19/11/2015. + */ +(function () { + 'use strict'; + angular.module('mdWavesurferApp', ['mdWavesurfer']) + .config(function ($mdIconProvider) { + //$mdIconProvider.fontSet('zmdi', 'fontawesome'); + }) + .controller('MainController', ['$scope', + function ($scope) { + $scope.urls = ["../media/demo.wav", "../panner/media.wav", "../elan/transcripts/001z.mp3"]; + $scope.longList = []; + for (var i = 0; i < 100; i++) { + $scope.longList.push({ + title: 'Long List test: ' + i, + url: $scope.urls[Math.floor(3 * Math.random())] + }); + } + }]) +})(); diff --git a/libraries/wavesurfer/example/angular-material/md-player-audio.partial.html b/libraries/wavesurfer/example/angular-material/md-player-audio.partial.html new file mode 100644 index 000000000..e73c3c992 --- /dev/null +++ b/libraries/wavesurfer/example/angular-material/md-player-audio.partial.html @@ -0,0 +1,30 @@ + +
+ +
+

Audio Player

+
+
+ + + +

+ {{$index+1}}. {{track.title}} +

+ +
+ {{track.duration | mdWavesurferTimeFormat}} +
+ +
+
+
+ + +
\ No newline at end of file diff --git a/libraries/wavesurfer/example/angular-material/md-player.partial.html b/libraries/wavesurfer/example/angular-material/md-player.partial.html new file mode 100644 index 000000000..9d9cfb0e4 --- /dev/null +++ b/libraries/wavesurfer/example/angular-material/md-player.partial.html @@ -0,0 +1,70 @@ +
+ +
+
+ {{control.currentTime | mdWavesurferTimeFormat}} +
+
+ {{control.title}} +
+
+ {{control.surfer.getDuration() | mdWavesurferTimeFormat}} +
+
+
+ + +
+
+ + +
+
+ + + {{btn.title}} + + + +
+ +
+ + + Rewind + + + + + + + {{control.surfer.isPlaying() ? 'Pause' : 'Play'}} + + + + + + + + Skip forward + + + +
+
+ + + Toggle mute + + + + +
+
+
+
\ No newline at end of file diff --git a/libraries/wavesurfer/example/angular-material/wavesurfer.directive.js b/libraries/wavesurfer/example/angular-material/wavesurfer.directive.js new file mode 100644 index 000000000..98eb68441 --- /dev/null +++ b/libraries/wavesurfer/example/angular-material/wavesurfer.directive.js @@ -0,0 +1,415 @@ +/** + * Created by intelWorx on 19/11/2015. + */ +(function () { + 'use strict'; + + /** + * Main module, your application should depend on this + * @module {mdWavesurfer} + */ + var app = angular.module('mdWavesurfer', ['ngMaterial']); + + /** + * @ngdoc service + * @name $mdWavesurferUtils + * + * @description + * + * Utility service for this directive, exposes method: + * - getLength(url), which returns a promise for the length of the audio specified by URL + * + * ```js + * app.directive('myFancyDirective', function(mdWavesurferUtils) { + * return { + * restrict: 'e', + * link: function(scope, el, attrs) { + * mdWavesurferUtils(attrs.url) + * .then(function(l){ + * scope.length = l; + * }, function(){ + * someErrorhandler() + * }) + * ; + * } + * }; + * }); + * ``` + */ + app.factory('mdWavesurferUtils', ['$q', '$document', '$timeout', + function ($q, $document, $timeout) { + return { + getLength: function (object) { + var deferred = $q.defer(); + var estimateLength = function (url) { + var audio = $document[0].createElement('audio'); + audio.src = url; + audio.addEventListener('loadeddata', function listener() { + deferred.resolve(this.duration); + audio.removeEventListener('loadeddata', listener); + audio.src = 'data:audio/mpeg,0';//destroy loading. + }); + + audio.addEventListener('error', function (e) { + deferred.resolve(e.target.error); + }); + }; + + if (typeof object === 'string') { + //this is a URL + estimateLength(object); + } else { + $timeout(function () { + deferred.reject(new DOMError("NotSupportedError", "Specified argument is not supported")); + }); + } + + return deferred.promise; + } + }; + } + ]); + + /** + * @ngdoc filter + * @name mdWavesurferTimeFormat + * + * Simple filter to convert value in seconds to MM:SS format + * + * @param Number duration in seconds + */ + app.filter('mdWavesurferTimeFormat', function () { + return function (input) { + if (!input) { + return "00:00"; + } + + var minutes = Math.floor(input / 60); + var seconds = Math.ceil(input) % 60; + + return (minutes < 10 ? '0' : '') + + minutes + + ":" + + (seconds < 10 ? '0' : '') + seconds; + }; + }); + + + app.controller('mdWavesurferAudioController', ['$attrs', '$element', + function (attributes, $element) { + var audio = this; + + audio.tracks = []; + audio.selectedIndex = audio.selectedIndex || 0; + audio.currentTrack = null; + + //adds to an audio track + audio.addTrack = function (trackScope) { + if (audio.tracks.indexOf(trackScope) < 0) { + audio.tracks.push(trackScope); + } + + if (!audio.currentTrack) { + audio.currentTrack = audio.tracks[audio.selectedIndex]; + } + }; + + //remove audio track + audio.removeTrack = function (trackScope) { + var idx = audio.tracks.indexOf(trackScope); + if (idx >= 0) { + audio.tracks.splice(idx, 1); + } + }; + + audio.playerProperties = {} + var nKey; + for (var attr in attributes) { + if (attr.match(/^player/)) { + nKey = attr.replace(/^player([A-Z])/, function (m, $1) { + return $1.toLowerCase(); + }); + audio.playerProperties[nKey] = attributes[attr]; + } + } + + var getPlayer = function(){ + return $element.find('md-wavesurfer-player').controller('mdWavesurferPlayer'); + }; + var setAutoPlay = function (forcePlay) { + var controller = getPlayer(); + if (controller && (forcePlay || controller.surfer.isPlaying())) { + controller.autoPlay = true; + } + }; + audio.setTrack = function (idx, forcePlay) { + if (audio.tracks.length > idx) { + if (audio.selectedIndex === idx) { + var ctrl = getPlayer(); + ctrl.surfer.playPause(); + } else { + setAutoPlay(forcePlay); + audio.currentTrack = audio.tracks[idx]; + audio.selectedIndex = idx; + } + } + }; + + audio.extraButtons = [{ + icon: 'zmdi zmdi-skip-previous', + title: 'Previous', + action: function ($event) { + if (audio.selectedIndex > 0) { + audio.setTrack(audio.selectedIndex - 1); + } + }, + class: '' + }, { + icon: 'zmdi zmdi-skip-next', + title: 'Next', + action: function ($event) { + if (audio.selectedIndex < audio.tracks.length - 1) { + audio.setTrack(audio.selectedIndex + 1); + } + }, + class: '' + }]; + + + } + ]); + + /** + * @ngdoc directive + * @name md-wavesurfer-audio + * + * Directive for playing a set of audio files. This directive is analogous to `