blob: e2160847f16bf949bce622cbfb1c9fd557ef08df [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
/* global cordova, Windows, Media, MediaError, LocalFileSystem, halfSpeedBtn */
// increased timeout for actual playback to give device chance to download and play mp3 file
// some emulators can be REALLY slow at this, so two minutes
var ACTUAL_PLAYBACK_TEST_TIMEOUT = 2 * 60 * 1000;
var WEB_MP3_FILE = 'https://cordova.apache.org/downloads/BlueZedEx.mp3';
var WEB_MP3_STREAM = 'https://cordova.apache.org/downloads/BlueZedEx.mp3';
var isWindows = cordova.platformId === 'windows8' || cordova.platformId === 'windows';
var isBrowser = cordova.platformId === 'browser';
// Detect whether audio hardware is available and enabled. For iOS playing audio is
// not supported on emulators w/out sound device connected to host PC but (which is
// the case for Sauce Labs emulators - see CB-11430)
var isAudioSupported = isWindows
? !!Windows.Media.Devices.MediaDevice.getDefaultAudioRenderId(Windows.Media.Devices.AudioDeviceRole.default)
: cordova.platformId === 'ios'
? !window.SAUCELABS_ENV
: true;
var isKitKat = cordova.platformId === 'android' && /Android\s4\.4/.test(window.navigator.userAgent);
exports.defineAutoTests = function () {
var failed = function (done, msg, context) {
if (context && context.done) return;
context.done = true;
var info = typeof msg === 'undefined' ? 'Unexpected error callback' : msg;
expect(true).toFailWithMessage(info);
done();
};
var succeed = function (done, msg, context) {
if (context && context.done) return;
context.done = true;
var info = typeof msg === 'undefined' ? 'Unexpected success callback' : msg;
expect(true).toFailWithMessage(info);
done();
};
describe('Media', function () {
beforeEach(function () {
// Custom Matcher
jasmine.Expectation.addMatchers({
toFailWithMessage: function () {
return {
compare: function (_, message) {
var pass = false;
return {
pass: pass,
message: message
};
}
};
}
});
});
it('media.spec.1 should exist', function () {
expect(Media).toBeDefined();
expect(typeof Media).toBe('function');
});
it('media.spec.2 should have the following properties', function () {
var media1 = new Media('dummy');
expect(media1.id).toBeDefined();
expect(media1.src).toBeDefined();
expect(media1._duration).toBeDefined();
expect(media1._position).toBeDefined();
media1.release();
});
it('media.spec.3 should define constants for Media status', function () {
expect(Media).toBeDefined();
expect(Media.MEDIA_NONE).toBe(0);
expect(Media.MEDIA_STARTING).toBe(1);
expect(Media.MEDIA_RUNNING).toBe(2);
expect(Media.MEDIA_PAUSED).toBe(3);
expect(Media.MEDIA_STOPPED).toBe(4);
});
it('media.spec.4 should define constants for Media errors', function () {
expect(MediaError).toBeDefined();
expect(MediaError.MEDIA_ERR_NONE_ACTIVE).toBe(0);
expect(MediaError.MEDIA_ERR_ABORTED).toBe(1);
expect(MediaError.MEDIA_ERR_NETWORK).toBe(2);
expect(MediaError.MEDIA_ERR_DECODE).toBe(3);
expect(MediaError.MEDIA_ERR_NONE_SUPPORTED).toBe(4);
});
it('media.spec.5 should contain a play function', function () {
var media1 = new Media('dummy');
expect(media1.play).toBeDefined();
expect(typeof media1.play).toBe('function');
media1.release();
});
it('media.spec.6 should contain a stop function', function () {
var media1 = new Media('dummy');
expect(media1.stop).toBeDefined();
expect(typeof media1.stop).toBe('function');
media1.release();
});
it('media.spec.7 should contain a seekTo function', function () {
var media1 = new Media('dummy');
expect(media1.seekTo).toBeDefined();
expect(typeof media1.seekTo).toBe('function');
media1.release();
});
it('media.spec.8 should contain a pause function', function () {
var media1 = new Media('dummy');
expect(media1.pause).toBeDefined();
expect(typeof media1.pause).toBe('function');
media1.release();
});
it('media.spec.9 should contain a getDuration function', function () {
var media1 = new Media('dummy');
expect(media1.getDuration).toBeDefined();
expect(typeof media1.getDuration).toBe('function');
media1.release();
});
it('media.spec.10 should contain a getCurrentPosition function', function () {
var media1 = new Media('dummy');
expect(media1.getCurrentPosition).toBeDefined();
expect(typeof media1.getCurrentPosition).toBe('function');
media1.release();
});
it('media.spec.11 should contain a startRecord function', function () {
var media1 = new Media('dummy');
expect(media1.startRecord).toBeDefined();
expect(typeof media1.startRecord).toBe('function');
media1.release();
});
it('media.spec.12 should contain a stopRecord function', function () {
var media1 = new Media('dummy');
expect(media1.stopRecord).toBeDefined();
expect(typeof media1.stopRecord).toBe('function');
media1.release();
});
it('media.spec.13 should contain a release function', function () {
var media1 = new Media('dummy');
expect(media1.release).toBeDefined();
expect(typeof media1.release).toBe('function');
media1.release();
});
it('media.spec.14 should contain a setVolume function', function () {
var media1 = new Media('dummy');
expect(media1.setVolume).toBeDefined();
expect(typeof media1.setVolume).toBe('function');
media1.release();
});
it('media.spec.15 should contain a getCurrentAmplitude function', function () {
var media1 = new Media('dummy');
expect(media1.getCurrentAmplitude).toBeDefined();
expect(typeof media1.getCurrentAmplitude).toBe('function');
media1.release();
});
it('media.spec.16 should contain a pauseRecord function', function () {
var media1 = new Media('dummy');
expect(media1.pauseRecord).toBeDefined();
expect(typeof media1.pauseRecord).toBe('function');
media1.release();
});
it('media.spec.17 should contain a resumeRecord function', function () {
var media1 = new Media('dummy');
expect(media1.resumeRecord).toBeDefined();
expect(typeof media1.resumeRecord).toBe('function');
media1.release();
});
it('media.spec.18 should return MediaError for bad filename', function (done) {
// bb10 dialog pops up, preventing tests from running
if (cordova.platformId === 'blackberry10') {
pending();
}
var context = this;
var fileName = 'invalid.file.name';
var badMedia = new Media(
fileName,
succeed.bind(
null,
done,
' badMedia = new Media , Unexpected succees callback, it should not create Media object with invalid file name'
),
function (result) {
if (context.done) return;
context.done = true;
expect(result).toBeDefined();
expect(result.code).toBe(MediaError.MEDIA_ERR_ABORTED);
if (badMedia) {
badMedia.release();
}
done();
}
);
badMedia.play();
});
describe('actual playback', function () {
var checkInterval, media;
afterEach(function () {
clearInterval(checkInterval);
if (media) {
media.stop();
media.release();
media = null;
}
});
it(
'media.spec.19 position should be set properly',
function (done) {
// no audio hardware available
if (!isAudioSupported || isBrowser || isKitKat) {
pending();
}
// context variable used as an extra security statement to ensure that the callback is processed only once,
// in case the statusChange callback is reached more than one time with the same status code.
// Some information about this kind of behaviour can be found at JIRA: CB-7099.
var context = this;
var mediaFile = WEB_MP3_FILE;
var successCallback = function () {};
var statusChange = function (statusCode) {
if (!context.done && statusCode === Media.MEDIA_RUNNING) {
checkInterval = setInterval(function () {
if (context.done) return;
media.getCurrentPosition(function successCallback (position) {
if (position > 0.0) {
context.done = true;
expect(true).toBe(true);
done();
}
}, failed.bind(null, done, 'media1.getCurrentPosition - Error getting media current position', context));
}, 1000);
}
};
media = new Media(
mediaFile,
successCallback,
failed.bind(null, done, 'media1 = new Media - Error creating Media object. Media file: ' + mediaFile, context),
statusChange
);
media.play();
},
ACTUAL_PLAYBACK_TEST_TIMEOUT
);
it(
'media.spec.20 duration should be set properly',
function (done) {
if (!isAudioSupported || cordova.platformId === 'blackberry10' || isBrowser || isKitKat) {
pending();
}
// context variable used as an extra security statement to ensure that the callback is processed only once,
// in case the statusChange callback is reached more than one time with the same status code.
// Some information about this kind of behaviour can be found at JIRA: CB-7099.
var context = this;
var mediaFile = WEB_MP3_FILE;
var successCallback = function () {};
var statusChange = function (statusCode) {
if (!context.done && statusCode === Media.MEDIA_RUNNING) {
checkInterval = setInterval(function () {
if (context.done) return;
media.getCurrentPosition(function (position) {
if (position > 0.0) {
context.done = true;
expect(media.getDuration()).toBeGreaterThan(0.0);
done();
}
}, failed.bind(null, done, 'media1.getCurrentPosition - Error getting media current position', context));
}, 1000);
}
};
media = new Media(
mediaFile,
successCallback,
failed.bind(null, done, 'media1 = new Media - Error creating Media object. Media file: ' + mediaFile, context),
statusChange
);
media.play();
},
ACTUAL_PLAYBACK_TEST_TIMEOUT
);
it(
'media.spec.21 should be able to resume playback after pause',
function (done) {
if (!isAudioSupported || cordova.platformId === 'blackberry10' || isKitKat) {
pending();
}
// context variable used as an extra security statement to ensure that the callback is processed only once,
// in case the statusChange callback is reached more than one time with the same status code.
// Some information about this kind of behaviour can be found at JIRA: CB-7099.
var context = this;
var resumed = false;
var mediaFile = WEB_MP3_FILE;
var successCallback = function () {};
var statusChange = function (statusCode) {
if (context.done) return;
if (statusCode === Media.MEDIA_RUNNING) {
if (!resumed) {
media.seekTo(20000);
media.pause();
return;
}
media.getCurrentPosition(function (position) {
expect(position).toBeGreaterThan(19);
expect(position).toBeLessThan(21);
context.done = true;
done();
}, failed.bind(null, done, 'media1.getCurrentPosition - Error getting media current position', context));
}
if (statusCode === Media.MEDIA_PAUSED) {
resumed = true;
media.play();
}
};
media = new Media(
mediaFile,
successCallback,
failed.bind(null, done, 'media1 = new Media - Error creating Media object. Media file: ' + mediaFile, context),
statusChange
);
// CB-10535: Play after a few secs, to give allow enough buffering of media file before seeking
setTimeout(function () {
media.play();
}, 4000);
},
ACTUAL_PLAYBACK_TEST_TIMEOUT
);
it(
'media.spec.22 should be able to seek through file',
function (done) {
if (!isAudioSupported || cordova.platformId === 'blackberry10' || isKitKat) {
pending();
}
// context variable used as an extra security statement to ensure that the callback is processed only once,
// in case the statusChange callback is reached more than one time with the same status code.
// Some information about this kind of behaviour can be found at JIRA: CB-7099.
var context = this;
var mediaFile = WEB_MP3_FILE;
var successCallback = function () {};
var statusChange = function (statusCode) {
if (!context.done && statusCode === Media.MEDIA_RUNNING) {
checkInterval = setInterval(function () {
if (context.done) return;
media.seekTo(5000);
media.getCurrentPosition(function (position) {
expect(position).toBeCloseTo(5, 0);
context.done = true;
done();
}, failed.bind(null, done, 'media1.getCurrentPosition - Error getting media current position', context));
}, 1000);
}
};
media = new Media(
mediaFile,
successCallback,
failed.bind(null, done, 'media1 = new Media - Error creating Media object. Media file: ' + mediaFile, context),
statusChange
);
// CB-10535: Play after a few secs, to give allow enough buffering of media file before seeking
setTimeout(function () {
media.play();
}, 4000);
},
ACTUAL_PLAYBACK_TEST_TIMEOUT
);
});
it('media.spec.23 should contain a setRate function', function () {
var media1 = new Media('dummy');
expect(media1.setRate).toBeDefined();
expect(typeof media1.setRate).toBe('function');
media1.release();
});
it(
'media.spec.24 playback rate should be set properly using setRate',
function (done) {
if (cordova.platformId !== 'ios') {
expect(true).toFailWithMessage('Platform does not supported this feature');
pending();
}
// no audio hardware available
if (!isAudioSupported) {
pending();
}
var mediaFile = WEB_MP3_FILE;
var successCallback;
var context = this;
var flag = true;
var statusChange = function (statusCode) {
console.log('status code: ' + statusCode);
if (statusCode === Media.MEDIA_RUNNING && flag) {
// flag variable used to ensure an extra security statement to ensure that the callback is processed only once,
// in case for some reason the statusChange callback is reached more than one time with the same status code.
// Some information about this kind of behavior it can be found at JIRA: CB-7099
flag = false;
setTimeout(function () {
media1.getCurrentPosition(
function (position) {
// in four seconds expect position to be between 4 & 10. Here, the values are chosen to give
// a large enough buffer range for the position to fall in and are not based on any calculation.
expect(position).not.toBeLessThan(4);
expect(position).toBeLessThan(10);
media1.stop();
media1.release();
context.done = true;
done();
},
failed.bind(null, done, 'media1.getCurrentPosition - Error getting media current position'),
context
);
}, 4000);
}
};
var media1 = new Media(
mediaFile,
successCallback,
failed.bind(null, done, 'media1 = new Media - Error creating Media object. Media file: ' + mediaFile, context),
statusChange
);
// make audio playback two times faster
media1.setRate(2);
media1.play();
},
ACTUAL_PLAYBACK_TEST_TIMEOUT
);
it(
'media.spec.25 should be able to play an audio stream',
function (done) {
// no audio hardware available, OR
// O_o Safari can't play the stream, so we're skipping this test on all browsers o_O
if (!isAudioSupported || isBrowser || isKitKat) {
pending();
}
// The link below points to an infinite mp3 stream
var mediaFile = WEB_MP3_STREAM;
var successCallback;
var context = this;
var flag = true;
var statusChange = function (statusCode) {
console.log('status code: ' + statusCode);
if (statusCode === Media.MEDIA_RUNNING && flag) {
// flag variable used to ensure an extra security statement to ensure that the callback is processed only once,
// in case for some reason the statusChange callback is reached more than one time with the same status code.
// Some information about this kind of behavior it can be found at JIRA: CB-7099
flag = false;
expect(true).toBe(true);
media1.stop();
media1.release();
context.done = true;
done();
}
};
var media1 = new Media(
mediaFile,
successCallback,
failed.bind(null, done, 'media1 = new Media - Error creating Media object. Media file: ' + mediaFile, context),
statusChange
);
media1.play();
},
ACTUAL_PLAYBACK_TEST_TIMEOUT
);
it('media.spec.26 should not crash or throw when setting the volume right after creating the media', function (done) {
// bb10 dialog pops up, preventing tests from running
if (cordova.platformId === 'blackberry10') {
pending();
}
var mediaFile = WEB_MP3_FILE;
var media = null;
expect(function () {
media = new Media(mediaFile);
media.setVolume('0.5');
}).not.toThrow();
// if there is no exception or crash in 3 seconds, the spec is completed
setTimeout(function () {
if (media) {
media.release();
done();
}
}, 3000);
});
it('media.spec.27 should call success or error when trying to stop a media that is in starting state', function (done) {
// bb10 dialog pops up, preventing tests from running
if (!isAudioSupported || cordova.platformId === 'blackberry10') {
pending();
}
var mediaFile = WEB_MP3_FILE;
var media = null;
var context = this;
var beenStarting = false;
var safeDone = function () {
if (!context.done) {
media.release();
context.done = true;
done();
}
};
var errorCallback = jasmine.createSpy('errorCallback').and.callFake(function (e) {
expect(true).toBe(true);
safeDone();
});
var successCallback = function () {
expect(true).toBe(true);
safeDone();
};
var statusChange = function (s) {
if (s === Media.MEDIA_STARTING && !context.done) {
beenStarting = true;
media.stop();
} else if (s === Media.MEDIA_RUNNING) {
// Some plugin implementations may skip "Starting" state
// so we'll also try to call stop in "Running" state,
// but in this case we should check that the "Starting" state wasn't really reached,
// otherwise it would mean that the previous media.stop() call has been ignored
expect(beenStarting).toBe(false);
media.stop();
}
};
media = new Media(mediaFile, successCallback, errorCallback, statusChange);
media.play();
});
});
};
//* *****************************************************************************************
//* **************************************Manual Tests***************************************
//* *****************************************************************************************
exports.defineManualTests = function (contentEl, createActionButton) {
// -------------------------------------------------------------------------
// Audio player
// -------------------------------------------------------------------------
var media1 = null;
var media1Timer = null;
var audioSrc = null;
var defaultaudio = WEB_MP3_FILE;
// Play audio function
function playAudio (url) {
console.log('playAudio()');
console.log(' -- media=' + media1);
var src = defaultaudio;
if (url) {
src = url;
}
// Stop playing if src is different from currently playing source
if (src !== audioSrc) {
if (media1 !== null) {
stopAudio();
media1 = null;
}
}
if (media1 === null) {
// TEST STREAMING AUDIO PLAYBACK
// var src = "http://nunzioweb.com/misc/Bon_Jovi-Crush_Mystery_Train.mp3"; // works
// var src = "http://nunzioweb.com/misc/Bon_Jovi-Crush_Mystery_Train.m3u"; // doesn't work
// var src = "http://www.wav-sounds.com/cartoon/bugsbunny1.wav"; // works
// var src = "http://www.angelfire.com/fl5/html-tutorial/a/couldyou.mid"; // doesn't work
// var src = "MusicSearch/mp3/train.mp3"; // works
// var src = "bryce.mp3"; // works
// var src = "/android_asset/www/bryce.mp3"; // works
media1 = new Media(
src,
function () {
console.log('playAudio():Audio Success');
},
function (err) {
console.log('playAudio():Audio Error: ' + err.code);
setAudioStatus('Error: ' + err.code);
},
function (status) {
console.log('playAudio():Audio Status: ' + status);
setAudioStatus(Media.MEDIA_MSG[status]);
// If stopped, then stop getting current position
if (Media.MEDIA_STOPPED === status) {
clearInterval(media1Timer);
media1Timer = null;
setAudioPosition('0 sec');
}
}
);
}
audioSrc = src;
document.getElementById('durationValue').innerHTML = '';
// Play audio
media1.play();
if (media1Timer === null && media1.getCurrentPosition) {
media1Timer = setInterval(function () {
media1.getCurrentPosition(
function (position) {
if (position >= 0.0) {
setAudioPosition(position + ' sec');
}
},
function (e) {
console.log('Error getting pos=' + e);
setAudioPosition('Error: ' + e);
}
);
}, 1000);
}
// Get duration
var counter = 0;
var timerDur = setInterval(function () {
counter = counter + 100;
if (counter > 2000) {
clearInterval(timerDur);
}
var dur = media1.getDuration();
if (dur > 0) {
clearInterval(timerDur);
document.getElementById('durationValue').innerHTML = dur + ' sec';
}
}, 100);
}
// Pause audio playback
function pauseAudio () {
console.log('pauseAudio()');
if (media1) {
media1.pause();
}
}
// Stop audio
function stopAudio () {
console.log('stopAudio()');
if (media1) {
media1.stop();
}
clearInterval(media1Timer);
media1Timer = null;
}
// Release audio
function releaseAudio () {
console.log('releaseAudio()');
if (media1) {
media1.stop(); // imlied stop of playback, resets timer
media1.release();
}
}
// Set audio status
function setAudioStatus (status) {
document.getElementById('statusValue').innerHTML = status;
}
// Set audio position
function setAudioPosition (position) {
document.getElementById('positionValue').innerHTML = position;
}
// Seek audio
function seekAudio (mode) {
var time = document.getElementById('seekInput').value;
if (time === '') {
time = 5000;
} else {
time = time * 1000; // we expect the input to be in seconds
}
if (media1 === null) {
console.log('seekTo requested while media1 is null');
if (audioSrc === null) {
audioSrc = defaultaudio;
}
media1 = new Media(
audioSrc,
function () {
console.log('seekToAudio():Audio Success');
},
function (err) {
console.log('seekAudio():Audio Error: ' + err.code);
setAudioStatus('Error: ' + err.code);
},
function (status) {
console.log('seekAudio():Audio Status: ' + status);
setAudioStatus(Media.MEDIA_MSG[status]);
// If stopped, then stop getting current position
if (Media.MEDIA_STOPPED === status) {
clearInterval(media1Timer);
media1Timer = null;
setAudioPosition('0 sec');
}
}
);
}
media1.getCurrentPosition(
function (position) {
var deltat = time;
if (mode === 'by') {
deltat = time + position * 1000;
}
media1.seekTo(
deltat,
function () {
console.log('seekAudioTo():Audio Success');
// force an update on the position display
updatePosition();
},
function (err) {
console.log('seekAudioTo():Audio Error: ' + err.code);
}
);
},
function (e) {
console.log('Error getting pos=' + e);
setAudioPosition('Error: ' + e);
}
);
}
// set audio volume
function setVolume () {
console.log('setVolume()');
var volume = document.getElementById('volumeInput').value;
if (media1 !== null) {
media1.setVolume(volume);
}
}
// for forced updates of position after a successful seek
function updatePosition () {
media1.getCurrentPosition(
function (position) {
if (position >= 0.0) {
setAudioPosition(position + ' sec');
}
},
function (e) {
console.log('Error getting pos=' + e);
setAudioPosition('Error: ' + e);
}
);
}
// -------------------------------------------------------------------------
// Audio recorder
// -------------------------------------------------------------------------
var mediaRec = null;
var recTime = 0;
var recordSrc = 'myRecording.mp3';
// Record audio
function recordAudio () {
console.log('recordAudio(), recording to ' + recordSrc);
console.log(' -- media=' + mediaRec);
releaseAudio();
if (!mediaRec) {
mediaRec = new Media(
recordSrc,
function () {
console.log('recordAudio():Audio Success');
},
function (err) {
console.log('recordAudio():Audio Error: ' + err.code);
setAudioStatus('Error: ' + err.code);
},
function (status) {
console.log('recordAudio():Audio Status: ' + status);
setAudioStatus(Media.MEDIA_MSG[status]);
}
);
}
// Record audio
mediaRec.startRecord();
// Stop recording after 10 sec
recTime = 0;
var recInterval = setInterval(function () {
recTime = recTime + 1;
setAudioPosition(recTime + ' sec');
if (recTime >= 10) {
clearInterval(recInterval);
if (mediaRec.stopAudioRecord) {
mediaRec.stopAudioRecord();
} else {
mediaRec.stopRecord();
}
console.log('recordAudio(): stop');
}
}, 1000);
}
// Play back recorded audio
function playRecording () {
playAudio(recordSrc);
}
// Function to get a filename for iOS recording
// Ensures that file doesn't exist to test CB-11380
function getRecordSrc () {
var noop = function () {};
recordSrc = 'cdvfile://localhost/temporary/iOSRecording.wav';
window.resolveLocalFileSystemURL(
recordSrc,
function (file) {
file.remove(function () {
console.log('Successfully removed ' + recordSrc);
}, noop);
},
noop
);
}
// Function to create a file for BB recording
function getRecordSrcBB () {
var fsFail = function (error) {
console.log('error creating file for BB recording', error);
};
var gotFile = function (file) {
recordSrc = file.fullPath;
};
var gotFS = function (fileSystem) {
fileSystem.root.getFile(
'BBRecording.amr',
{
create: true
},
gotFile,
fsFail
);
};
window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, gotFS, fsFail);
}
// Function to create a file for Windows recording
function getRecordSrcWin () {
var fsFail = function (error) {
console.log('error creating file for Win recording', error);
};
var gotFile = function (file) {
recordSrc = file.name;
};
var gotFS = function (fileSystem) {
fileSystem.root.getFile(
'WinRecording.m4a',
{
create: true
},
gotFile,
fsFail
);
};
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fsFail);
}
// Generate Dynamic Table
function generateTable (tableId, rows, cells, elements) {
var table = document.createElement('table');
for (var r = 0; r < rows; r++) {
var row = table.insertRow(r);
for (var c = 0; c < cells; c++) {
var cell = row.insertCell(c);
cell.setAttribute('align', 'center');
for (var e in elements) {
if (elements[e].position.row === r && elements[e].position.cell === c) {
var htmlElement = document.createElement(elements[e].tag);
var content;
if (elements[e].content !== '') {
content = document.createTextNode(elements[e].content);
htmlElement.appendChild(content);
}
if (elements[e].type) {
htmlElement.type = elements[e].type;
}
htmlElement.setAttribute('id', elements[e].id);
cell.appendChild(htmlElement);
}
}
}
}
table.setAttribute('align', 'center');
table.setAttribute('id', tableId);
return table;
}
// Audio && Record Elements
var elementsResultsAudio = [
{
id: 'statusTag',
content: 'Status:',
tag: 'div',
position: {
row: 0,
cell: 0
}
},
{
id: 'statusValue',
content: '',
tag: 'div',
position: {
row: 0,
cell: 2
}
},
{
id: 'durationTag',
content: 'Duration:',
tag: 'div',
position: {
row: 1,
cell: 0
}
},
{
id: 'durationValue',
content: '',
tag: 'div',
position: {
row: 1,
cell: 2
}
},
{
id: 'positionTag',
content: 'Position:',
tag: 'div',
position: {
row: 2,
cell: 0
}
},
{
id: 'positionValue',
content: '',
tag: 'div',
position: {
row: 2,
cell: 2
}
}
];
var elementsAudio = [
{
id: 'playBtn',
content: '',
tag: 'div',
position: {
row: 0,
cell: 0
}
},
{
id: 'pauseBtn',
content: '',
tag: 'div',
position: {
row: 0,
cell: 1
}
},
{
id: 'stopBtn',
content: '',
tag: 'div',
position: {
row: 1,
cell: 0
}
},
{
id: 'releaseBtn',
content: '',
tag: 'div',
position: {
row: 1,
cell: 1
}
},
{
id: 'seekByBtn',
content: '',
tag: 'div',
position: {
row: 2,
cell: 0
}
},
{
id: 'seekToBtn',
content: '',
tag: 'div',
position: {
row: 2,
cell: 1
}
},
{
id: 'seekInput',
content: '',
tag: 'input',
type: 'number',
position: {
row: 2,
cell: 2
}
},
{
id: 'halfSpeedBtn',
content: '',
tag: 'div',
position: {
row: 0,
cell: 2
}
},
{
id: 'setVolumeBtn',
content: '',
tag: 'div',
position: {
row: 3,
cell: 0
}
},
{
id: 'volumeInput',
tag: 'input',
type: 'text',
position: {
row: 3,
cell: 1
}
}
];
var elementsRecord = [
{
id: 'recordbtn',
content: '',
tag: 'div',
position: {
row: 1,
cell: 0
}
},
{
id: 'recordplayBtn',
content: '',
tag: 'div',
position: {
row: 1,
cell: 1
}
},
{
id: 'recordpauseBtn',
content: '',
tag: 'div',
position: {
row: 2,
cell: 0
}
},
{
id: 'recordstopBtn',
content: '',
tag: 'div',
position: {
row: 2,
cell: 1
}
}
];
// Title audio results
var div = document.createElement('h2');
div.appendChild(document.createTextNode('Audio'));
div.setAttribute('align', 'center');
contentEl.appendChild(div);
// Generate and add results table
contentEl.appendChild(generateTable('info', 3, 3, elementsResultsAudio));
// Title audio actions
div = document.createElement('h2');
div.appendChild(document.createTextNode('Actions'));
div.setAttribute('align', 'center');
contentEl.appendChild(div);
// Generate and add buttons table
contentEl.appendChild(generateTable('audioActions', 4, 3, elementsAudio));
createActionButton(
'Play',
function () {
playAudio();
},
'playBtn'
);
createActionButton(
'Pause',
function () {
pauseAudio();
},
'pauseBtn'
);
createActionButton(
'HalfSpeed',
function () {
if (halfSpeedBtn.firstChild.firstChild.innerText === 'HalfSpeed') {
halfSpeedBtn.firstChild.firstChild.innerText = 'FullSpeed';
media1.setRate(0.5);
} else if (halfSpeedBtn.firstChild.firstChild.innerText === 'FullSpeed') {
halfSpeedBtn.firstChild.firstChild.innerText = 'DoubleSpeed';
media1.setRate(1.0);
} else {
halfSpeedBtn.firstChild.firstChild.innerText = 'HalfSpeed';
media1.setRate(2.0);
}
},
'halfSpeedBtn'
);
createActionButton(
'Stop',
function () {
stopAudio();
},
'stopBtn'
);
createActionButton(
'Release',
function () {
releaseAudio();
},
'releaseBtn'
);
createActionButton(
'Seek By',
function () {
seekAudio('by');
},
'seekByBtn'
);
createActionButton(
'Seek To',
function () {
seekAudio('to');
},
'seekToBtn'
);
createActionButton(
'Set volume',
function () {
setVolume();
},
'setVolumeBtn'
);
// get Special path to record if iOS || Blackberry
if (cordova.platformId === 'ios') {
getRecordSrc();
} else if (cordova.platformId === 'blackberry') {
getRecordSrcBB();
} else if (cordova.platformId === 'windows' || cordova.platformId === 'windows8') {
getRecordSrcWin();
}
// testing process and details
function addItemToList (_list, _text) {
var item = document.createElement('li');
item.appendChild(document.createTextNode(_text));
_list.appendChild(item);
}
div = document.createElement('h4');
div.appendChild(document.createTextNode('Recommended Test Procedure'));
contentEl.appendChild(div);
var list = document.createElement('ol');
addItemToList(
list,
'Press play - Will start playing audio. Status: Running, Duration: 61.333 sec, Position: Current position of audio track'
);
addItemToList(
list,
'Press pause - Will pause the audio. Status: Paused, Duration: 61.333 sec, Position: Position where track was paused'
);
addItemToList(list, 'Press play - Will begin playing where track left off from the pause');
addItemToList(list, 'Press stop - Will stop the audio. Status: Stopped, Duration: 61.333 sec, Position: 0 sec');
addItemToList(list, 'Press play - Will begin playing the audio track from the beginning');
addItemToList(list, 'Press release - Will stop the audio. Status: Stopped, Duration: 61.333 sec, Position: 0 sec');
addItemToList(list, 'Press play - Will begin playing the audio track from the beginning');
addItemToList(list, 'Type 10 in the text box beside Seek To button');
addItemToList(list, 'Press seek by - Will jump 10 seconds ahead in the audio track. Position: should jump by 10 sec');
addItemToList(list, 'Press stop if track is not already stopped');
addItemToList(list, 'Type 30 in the text box beside Seek To button');
addItemToList(list, 'Press play then seek to - Should jump to Position 30 sec');
addItemToList(list, 'Press stop');
addItemToList(list, 'Type 5 in the text box beside Seek To button');
addItemToList(list, 'Press play, let play past 10 seconds then press seek to - should jump back to position 5 sec');
div = document.createElement('div');
div.setAttribute(
'style',
'background:#B0C4DE;border:1px solid #FFA07A;margin:15px 6px 0px;min-width:295px;max-width:97%;padding:4px 0px 2px 10px;min-height:160px;max-height:200px;overflow:auto'
);
div.appendChild(list);
contentEl.appendChild(div);
// Title Record Audio
div = document.createElement('h2');
div.appendChild(document.createTextNode('Record Audio'));
div.setAttribute('align', 'center');
contentEl.appendChild(div);
// Generate and add Record buttons table
contentEl.appendChild(generateTable('recordContent', 3, 3, elementsRecord));
createActionButton(
'Record Audio \n 10 sec',
function () {
recordAudio();
},
'recordbtn'
);
createActionButton(
'Play',
function () {
playRecording();
},
'recordplayBtn'
);
createActionButton(
'Pause',
function () {
pauseAudio();
},
'recordpauseBtn'
);
createActionButton(
'Stop',
function () {
stopAudio();
},
'recordstopBtn'
);
// testing process and details
div = document.createElement('h4');
div.appendChild(document.createTextNode('Recommended Test Procedure'));
contentEl.appendChild(div);
list = document.createElement('ol');
addItemToList(
list,
'Press Record Audio 10 sec - Will start recording audio for 10 seconds. Status: Running, Position: number of seconds recorded (will stop at 10)'
);
addItemToList(list, 'Status will change to Stopped when finished recording');
addItemToList(
list,
'Press play - Will begin playing the recording. Status: Running, Duration: # of seconds of recording, Position: Current position of recording'
);
addItemToList(
list,
'Press stop - Will stop playing the recording. Status: Stopped, Duration: # of seconds of recording, Position: 0 sec'
);
addItemToList(list, 'Press play - Will begin playing the recording from the beginning');
addItemToList(
list,
'Press pause - Will pause the playback of the recording. Status: Paused, Duration: # of seconds of recording, Position: Position where recording was paused'
);
addItemToList(list, 'Press play - Will begin playing the recording from where it was paused');
div = document.createElement('div');
div.setAttribute(
'style',
'background:#B0C4DE;border:1px solid #FFA07A;margin:15px 6px 0px;min-width:295px;max-width:97%;padding:4px 0px 2px 10px;min-height:160px;max-height:200px;overflow:auto'
);
div.appendChild(list);
contentEl.appendChild(div);
};