Vmeda.Online/src/core/emulator/providers/capture-helper.ts

223 lines
8.1 KiB
TypeScript
Raw Normal View History

// (C) Copyright 2015 Martin Dougiamas
//
// Licensed 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.
import { Injectable } from '@angular/core';
import { ModalController, Modal } from 'ionic-angular';
import { CoreMimetypeUtilsProvider } from '../../../providers/utils/mimetype';
import { CoreUtilsProvider } from '../../../providers/utils/utils';
/**
* Helper service with some features to capture media (image, audio, video).
*/
@Injectable()
export class CoreEmulatorCaptureHelperProvider {
protected possibleAudioMimeTypes = {
'audio/webm': 'weba',
'audio/ogg': 'ogg'
};
protected possibleVideoMimeTypes = {
'video/webm;codecs=vp9': 'webm',
'video/webm;codecs=vp8': 'webm',
'video/ogg': 'ogv'
};
protected win: any;
videoMimeType: string;
audioMimeType: string;
constructor(private utils: CoreUtilsProvider, private mimeUtils: CoreMimetypeUtilsProvider,
private modalCtrl: ModalController) {
// Convert the window to "any" type because some of the variables used (like MediaRecorder) aren't in the window spec.
this.win = <any>window;
}
/**
* Capture media (image, audio, video).
*
* @param {String} type Type of media: image, audio, video.
* @param {Function} successCallback Function called when media taken.
* @param {Function} errorCallback Function called when error or cancel.
* @param {Object} [options] Optional options.
* @return {Void}
*/
captureMedia(type: string, options: any) : Promise<any> {
options = options || {};
try {
// Build the params to send to the modal.
let deferred = this.utils.promiseDefer(),
params: any = {
type: type
},
mimeAndExt,
modal: Modal;
// Initialize some data based on the type of media to capture.
if (type == 'video') {
mimeAndExt = this.getMimeTypeAndExtension(type, options.mimetypes);
params.mimetype = mimeAndExt.mimetype;
params.extension = mimeAndExt.extension;
} else if (type == 'audio') {
mimeAndExt = this.getMimeTypeAndExtension(type, options.mimetypes);
params.mimetype = mimeAndExt.mimetype;
params.extension = mimeAndExt.extension;
} else if (type == 'image') {
if (typeof options.sourceType != 'undefined' && options.sourceType != 1) {
return Promise.reject('This source type is not supported in desktop.');
}
if (options.cameraDirection == 1) {
params.facingMode = 'user';
}
if (options.encodingType == 1) {
params.mimetype = 'image/png';
params.extension = 'png';
} else {
params.mimetype = 'image/jpeg';
params.extension = 'jpeg';
}
if (options.quality >= 0 && options.quality <= 100) {
params.quality = options.quality / 100;
}
if (options.destinationType == 0) {
params.returnDataUrl = true;
}
}
if (options.duration) {
params.maxTime = options.duration * 1000;
}
modal = this.modalCtrl.create('CoreEmulatorCaptureMediaPage', params);
modal.present();
modal.onDidDismiss((data: any, role: string) => {
if (role == 'success') {
deferred.resolve(data);
} else {
deferred.reject(data);
}
});
return deferred.promise;
} catch(ex) {
return Promise.reject(ex.toString());
}
}
/**
* Get the mimetype and extension to capture media.
*
* @param {string} type Type of media: image, audio, video.
* @param {string[]} [mimetypes] List of supported mimetypes. If undefined, all mimetypes supported.
* @return {{extension: string, mimetype: string}} An object with mimetype and extension to use.
*/
protected getMimeTypeAndExtension(type: string, mimetypes) : {extension: string, mimetype: string} {
var result: any = {};
if (mimetypes && mimetypes.length) {
// Search for a supported mimetype.
for (let i = 0; i < mimetypes.length; i++) {
let mimetype = mimetypes[i],
matches = mimetype.match(new RegExp('^' + type + '/'));
if (matches && matches.length && this.win.MediaRecorder.isTypeSupported(mimetype)) {
result.mimetype = mimetype;
break;
}
}
}
if (result.mimetype) {
// Found a supported mimetype in the mimetypes array, get the extension.
result.extension = this.mimeUtils.getExtension(result.mimetype);
} else if (type == 'video') {
// No mimetype found, use default extension.
result.mimetype = this.videoMimeType;
result.extension = this.possibleVideoMimeTypes[result.mimetype];
} else if (type == 'audio') {
// No mimetype found, use default extension.
result.mimetype = this.audioMimeType;
result.extension = this.possibleAudioMimeTypes[result.mimetype];
}
return result;
}
/**
* Init the getUserMedia function, using a deprecated function as fallback if the new one doesn't exist.
*
* @return {boolean} Whether the function is supported.
*/
protected initGetUserMedia() : boolean {
let nav = <any>navigator;
// Check if there is a function to get user media.
if (typeof nav.mediaDevices == 'undefined') {
nav.mediaDevices = {};
}
if (!nav.mediaDevices.getUserMedia) {
// New function doesn't exist, check if the deprecated function is supported.
nav.getUserMedia = nav.getUserMedia || nav.webkitGetUserMedia || nav.mozGetUserMedia || nav.msGetUserMedia;
if (nav.getUserMedia) {
// Deprecated function exists, support the new function using the deprecated one.
navigator.mediaDevices.getUserMedia = (constraints) => {
let deferred = this.utils.promiseDefer();
nav.getUserMedia(constraints, deferred.resolve, deferred.reject);
return deferred.promise;
};
} else {
return false;
}
}
return true;
}
/**
* Initialize the mimetypes to use when capturing.
*/
protected initMimeTypes() : void {
// Determine video and audio mimetype to use.
for (let mimeType in this.possibleVideoMimeTypes) {
if (this.win.MediaRecorder.isTypeSupported(mimeType)) {
this.videoMimeType = mimeType;
break;
}
}
for (let mimeType in this.possibleAudioMimeTypes) {
if (this.win.MediaRecorder.isTypeSupported(mimeType)) {
this.audioMimeType = mimeType;
break;
}
}
}
/**
* Load the Mocks that need it.
*
* @return {Promise<void>} Promise resolved when loaded.
*/
load() : Promise<void> {
if (typeof this.win.MediaRecorder != 'undefined' && this.initGetUserMedia()) {
this.initMimeTypes();
}
return Promise.resolve();
}
}