summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNorman Kerr 柯念北2013-10-16 21:20:48 (GMT)
committerNorman Kerr 柯念北2013-10-16 21:20:48 (GMT)
commit23925bf1d5b816f52f17f050c50a49867690c19c (patch)
tree12a66fd453f6443a0fe2f5c8decba3663d8266d0
parent320e725eb5984db4e134ed77b31523de360d323f (diff)
Complete overhaul of media recorder. See commit notes for changes.7.x-1.0-alpha2
Removes unneeded theme function for audio player, and instead relies on file entity to display audio preview. Integrates completely with file module by relying on file_managed element. Adds better support for mobile devices through display of file managed element. Removes dependency on modernizr and transliteration. Adds requirement for file entity and media 2.x. Adds ajax refresh for changing recorder tabs. Adds working media browser tab. … plus many more minor fixes.
-rwxr-xr-xcss/media-recorder.css (renamed from css/media_recorder.css)24
-rw-r--r--includes/media_recorder.admin.inc (renamed from media_recorder.admin.inc)0
-rw-r--r--includes/media_recorder.drush.inc (renamed from media_recorder.drush.inc)13
-rwxr-xr-xjs/jquery.mediaRecorder.js251
-rwxr-xr-xjs/media-recorder-youtube.js39
-rw-r--r--js/media-recorder.browser.js34
-rwxr-xr-xjs/media-recorder.js20
-rwxr-xr-xjs/media_recorder.js44
-rwxr-xr-xjs/media_recorder_youtube.js68
-rwxr-xr-xmedia_recorder.info7
-rwxr-xr-xmedia_recorder.install2
-rwxr-xr-xmedia_recorder.media.inc17
-rwxr-xr-xmedia_recorder.module667
-rw-r--r--theme/media-recorder.tpl.php19
14 files changed, 512 insertions, 693 deletions
diff --git a/css/media_recorder.css b/css/media-recorder.css
index 71a87fb..005d3a5 100755
--- a/css/media_recorder.css
+++ b/css/media-recorder.css
@@ -208,3 +208,27 @@
background: #33cc33;
vertical-align: middle;
}
+
+div.media-recorder-toggle .form-item {
+ margin: 0;
+ padding: 0;
+ display: inline-block;
+}
+
+div.media-recorder-toggle input {
+ display: none;
+}
+
+div.media-recorder-toggle input:checked + label.option {
+ background: #323232;
+}
+
+div.media-recorder-toggle label.option {
+ background: #555555;
+ border: #ccc;
+ border-radius: 3px 3px 0px 0px;
+ color: #ffffff;
+ margin: 0 5px 0 0;
+ padding: 5px 10px;
+ cursor: pointer;
+}
diff --git a/media_recorder.admin.inc b/includes/media_recorder.admin.inc
index 47217a4..47217a4 100644
--- a/media_recorder.admin.inc
+++ b/includes/media_recorder.admin.inc
diff --git a/media_recorder.drush.inc b/includes/media_recorder.drush.inc
index ab57865..895971b 100644
--- a/media_recorder.drush.inc
+++ b/includes/media_recorder.drush.inc
@@ -72,17 +72,16 @@ function drush_media_recorder_download_libraries() {
// Wami doesn't have a tarball, so we download individually.
elseif (empty($download_url) && $name == 'wami') {
- drush_mkdir($library_path);
- drush_op('chdir', $library_path);
- drush_shell_exec('wget %s', 'https://wami-recorder.googlecode.com/hg/example/client/Wami.swf');
- drush_shell_exec('wget %s', 'https://wami-recorder.googlecode.com/hg/example/client/recorder.js');
+ drush_mkdir($name);
+ drush_op('chdir', $name);
+ drush_download_file('https://wami-recorder.googlecode.com/hg/example/client/Wami.swf');
+ drush_download_file('https://wami-recorder.googlecode.com/hg/example/client/recorder.js');
+ drush_op('chdir', '..');
+ drush_copy_dir($name, $library_path);
drush_log(dt('The @name library has been downloaded to @path', array('@name' => $name, '@path' => $library_path)), 'success');
}
// Return to base path.
drush_op('chdir', $base_path);
}
-
- // Make sure Modernizr is installed.
- drush_op('_modernizr_drush_download_dev');
}
diff --git a/js/jquery.mediaRecorder.js b/js/jquery.mediaRecorder.js
index a7a2b98..ecd179d 100755
--- a/js/jquery.mediaRecorder.js
+++ b/js/jquery.mediaRecorder.js
@@ -16,10 +16,6 @@
'timeLimit': 300000
};
- // Audio analyzer variables.
- var analyserNode = null;
- var analyserContext = null;
-
// Normalize features.
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext;
@@ -29,27 +25,9 @@
var browser = $.browser;
var getUserMediaCheck = typeof(navigator.getUserMedia) === 'function';
var webAudioCheck = typeof(window.AudioContext) === 'function';
- var wamiCheck = typeof(window.Wami) === 'object';
- var canvasCheck = Modernizr.canvas;
- var wavCheck = Modernizr.audio.wav;
- var touchCheck = Modernizr.touch;
-
- // Only enable for Chrome Canary at this point, due to Chrome showing
- // AudioContext as enabled, even though it's disabled.
- if (browser.webkit === true && browser.version >= 537.36) {
- getUserMediaCheck = true;
- } else {
- getUserMediaCheck = false;
- }
-
- // Feature Debugging.
- //console.log(browser);
- //console.log('getUserMedia: ' + getUserMediaCheck);
- //console.log('Web Audio: ' + webAudioCheck);
- //console.log('Wami: ' + wamiCheck);
- //console.log('Canvas: ' + canvasCheck);
- //console.log('WAV: ' + wavCheck);
- //console.log('Touch: ' + touchCheck);
+ var flashVersion = swfobject.getFlashPlayerVersion();
+ var canvas = document.createElement('canvas');
+ var canvasCheck = !!(canvas.getContext && canvas.getContext('2d'));
// ********************************************************************
// * jQuery Plugin Functions.
@@ -63,16 +41,40 @@
// Check for existing recorder.
if (typeof this.element.recorder != 'undefined') {
return this.element.mediaRecorder;
- } else {
- // Attach recorder to DOM node for reference
+ }
+ // Otherwise attach recorder to DOM node for reference
+ else {
this.element.mediaRecorder = this;
}
+ // Run webRTC recorder.
if (getUserMediaCheck && webAudioCheck) {
+ // Hide specific file related elements.
+ $(this.element).parent().children('span.file, span.file-size, input.media-recorder-upload, input.media-recorder-upload-button').hide();
+ // Set audio player width to recorder width.
+ $(this.element).parent().children('div.file-audio').width(options.width);
+ // Initialize webRTC recorder.
this.init();
- } else {
+ }
+ // Run flash recorder.
+ else if (flashVersion.major >= 10) {
+ // Hide all file input related elements.
+ $(this.element).parent().children('span.file, span.file-size, input.media-recorder-upload, input.media-recorder-upload-button').hide();
+ // Set audio player width to recorder width.
+ $(this.element).parent().children('div.file-audio').width(options.width);
+ // Initialize flash recorder.
this.flashInit();
}
+ // Display flash warning if not newer version.
+ else if (flashVersion.major < 10 && flashVersion.major > 0) {
+ $(this.element).prepend($('<div class="messages error"><span class="message-text"><a target="_blank" href="https://get.adobe.com/flashplayer">Flash 10</a> or higher must be installed in order to record.</span></div>'));
+ }
+ // Show file element.
+ else {
+ // Hide all media recorder related elements.
+ $(this.element).parent().children('.media-recorder-toggle').hide();
+ $(this.element).hide();
+ }
return this;
}
@@ -99,7 +101,7 @@
// Generate general recorder markup.
var element = $(this.element);
var options = this.options;
- element.recorder = $('<div class="media-recorder" style="width: 300px; height:100px;"></div>');
+ element.recorder = $('<div class="media-recorder"></div>').width(options.width).height(options.height);
element.recorder.controls = $('<div class="controls"></div>');
element.recorder.canvas = $('<canvas class="media-recorder-analyser"></canvas>');
element.recorder.status = $('<div class="media-recorder-status">00:00 / ' + millisecondsToTime(options.timeLimit) + '</div>');
@@ -125,7 +127,7 @@
max: 1,
value: 0.8,
slide: function(event, ui) {
- inputPoint.gain.value = ui.value;
+ gainNode.gain.value = ui.value;
}
});
@@ -207,9 +209,6 @@
clearInterval(element.recorder.statusInterval);
element.recorder.HTML5Recorder.stop();
element.recorder.HTML5Recorder.exportWAV(function(blob) {
- var url = URL.createObjectURL(blob);
- var audio = $(element).find('.media-recorder-audio audio');
- $(audio).attr('src', url);
$(element).find('.media-recorder-status').html('<div class="progressbar"></div>');
sendBlob(element, options, blob);
});
@@ -226,13 +225,6 @@
var element = $(this.element);
var options = this.options;
- // Check flash version.
- var flashVersion = swfobject.getFlashPlayerVersion();
- if (flashVersion.major < 10) {
- element.prepend($('<div class="messages error"><span class="message-text"><a target="_blank" href="https://get.adobe.com/flashplayer">Flash 10</a> or higher must be installed in order to record.</span></div>'));
- return;
- }
-
// Build recorder.
element.recorder = $('<div class="media-recorder" style="width: 300px; height:100px;"></div>');
element.recorder.controls = $('<div class="controls"></div>');
@@ -268,21 +260,8 @@
// Initiate Wami.
Wami.setup({
id: 'wami-' + $(element).attr('id'),
- swfUrl: options.swfURL
+ swfUrl: options.swfurl
});
-
- // Test that html5 audio tags can play wav files (not possible in IE9-).
- if (!wavCheck && browser.msie) {
- var audio = element.find('.media-recorder-audio');
- var url = '';
- if (audio.children('audio').length) {
- url = audio.children('audio').attr('src');
- } else if (audio.children('embed').length) {
- url = audio.children('embed').attr('src');
- }
- audio.css('position', 'static');
- audio.detach().insertBefore(element);
- }
},
// ********************************************************************
@@ -290,7 +269,7 @@
// ********************************************************************
flashRecord: function(element, options) {
Wami.startRecording(
- options.recordingPath + '/' + options.drupalFileName,
+ options.recordingPath + '/' + options.fileName,
Wami.nameCallback(function() {
mediaRecorder.prototype.flashRecordStart(element, options);
}),
@@ -351,16 +330,9 @@
flashRecordFinish: function(element, options) {
// Clear all progress intervals.
clearInterval(element.recorder.progressInterval);
- // Update audio player.
- updateAudio(element, options);
// Set audio and file input values.
- var elementName = fieldFormatter(element, options, 'filepath');
- $('input[name="' + elementName + '"]').val(options.drupalFilePath + '/' + options.drupalFileName);
- $(element).find('.media-recorder-status').html('00:00 / 05:00');
- $(element).find('.media-recorder-record').removeClass('record-on').addClass('record-off')
- .unbind('click').click(function() {
- mediaRecorder.prototype.flashRecord(element, options);
- });
+ $(element).parent().children('input.media-recorder-filepath').val(options.filePath + '/' + options.fileName);
+ $(element).parent().children('input.media-recorder-refresh').trigger('mousedown');
},
// ********************************************************************
@@ -390,22 +362,81 @@
// ********************************************************************
function startUserMedia(element, options, stream) {
if (webAudioCheck) {
+
+ // Audio analyzer variables.
+ var analyserNode = null;
+ var analyserContext = null;
+ var canvas = $("canvas.media-recorder-analyser");
+ var canvasWidth = canvas[0].width;
+ var canvasHeight = canvas[0].height;
+
+ // Create an audio context.
element.recorder.audioContext = new AudioContext();
- inputPoint = element.recorder.audioContext.createGainNode();
- realAudioInput = element.recorder.audioContext.createMediaStreamSource(stream);
- audioInput = realAudioInput;
- audioInput.connect(inputPoint);
- inputPoint.gain.value = 0.8;
+
+ // Create a source node.
+ mediaStreamSourceNode = element.recorder.audioContext.createMediaStreamSource(stream);
+
+ // Create a default gain node.
+ gainNode = element.recorder.audioContext.createGain();
+ gainNode.gain.value = 0.8;
+
+ // Send media stream through gain node.
+ mediaStreamSourceNode.connect(gainNode);
+
+ // Create analyser node.
analyserNode = element.recorder.audioContext.createAnalyser();
analyserNode.fftSize = 2048;
- inputPoint.connect(analyserNode);
- element.recorder.HTML5Recorder = new Recorder(inputPoint, {workerPath:Drupal.settings.basePath + 'sites/all/libraries/Recorderjs/recorderWorker.js'});
- zeroGain = element.recorder.audioContext.createGainNode();
- zeroGain.gain.value = 0.0;
- inputPoint.connect(zeroGain);
- zeroGain.connect(element.recorder.audioContext.destination);
+
+ // Send gain node data to analyser node.
+ gainNode.connect(analyserNode);
+
+ // Create a recorder using the gain node.
+ element.recorder.HTML5Recorder = new Recorder(gainNode, {workerPath:Drupal.settings.basePath + 'sites/all/libraries/Recorderjs/recorderWorker.js'});
+
+ // Create a muted gain node.
+ zeroGainNode = element.recorder.audioContext.createGain();
+ zeroGainNode.gain.value = 0.0;
+
+ // Send gain node data through zero gain node.
+ gainNode.connect(zeroGainNode);
+
+ // Send zero gain data to audio context destination.
+ zeroGainNode.connect(element.recorder.audioContext.destination);
+
+ // Update audio canvas.
updateAudioCanvas(element, options);
}
+
+ // ********************************************************************
+ // * Update Audio Canvas.
+ // ********************************************************************
+ function updateAudioCanvas() {
+ if (!analyserContext) {
+ analyserContext = canvas[0].getContext('2d');
+ }
+ var spacing = 1;
+ var barWidth = 1;
+ var numBars = Math.round(canvasWidth / spacing);
+ var freqByteData = new Uint8Array(analyserNode.frequencyBinCount);
+ analyserNode.getByteFrequencyData(freqByteData);
+ analyserContext.clearRect(0, 0, canvasWidth, canvasHeight);
+ analyserContext.fillStyle = '#F6D565';
+ analyserContext.lineCap = 'round';
+ var multiplier = analyserNode.frequencyBinCount / numBars;
+ // Draw rectangle for each frequency bin.
+ for (var i = 0; i < numBars; ++i) {
+ var magnitude = 0;
+ var offset = Math.floor(i * multiplier);
+ for (var j = 0; j < multiplier; j++) {
+ magnitude += freqByteData[offset + j];
+ }
+ magnitude = magnitude / multiplier;
+ var magnitude2 = freqByteData[i * multiplier];
+ analyserContext.fillStyle = "hsl( " + Math.round((i * 360) / numBars) + ", 100%, 50%)";
+ analyserContext.fillRect(i * spacing, canvasHeight, barWidth, -magnitude);
+ }
+ rafID = window.requestAnimationFrame(updateAudioCanvas);
+ }
}
// ********************************************************************
@@ -421,7 +452,7 @@
req.addEventListener("load", transferComplete, false);
req.addEventListener("error", transferFailed, false);
req.addEventListener("abort", transferCanceled, false);
- req.open("POST", options.recordingPath + '/' + options.drupalFileName, true);
+ req.open("POST", options.recordingPath + '/' + options.fileName, true);
req.send(formData);
function updateProgress(evt) {
@@ -430,7 +461,8 @@
$(element).find('.progressbar').progressbar({
value: percentComplete
});
- } else {
+ }
+ else {
$(element).find('.progressbar').progressbar({
value: 100
});
@@ -439,11 +471,9 @@
function transferComplete(evt) {
var file = JSON.parse(req.response);
- var fidInput = fieldFormatter(element, options, 'fid');
- var filepathInput = fieldFormatter(element, options, 'filepath');
- $('input[name="' + fidInput + '"]').val(file.fid);
- $('input[name="' + filepathInput + '"]').val(options.drupalFilePath + '/' + options.drupalFileName);
- $(element).find('.media-recorder-status').html('00:00 / 05:00');
+ $(element).parent().children('input.media-recorder-filepath').val(options.filePath + '/' + options.fileName);
+ $(element).parent().children('input.media-recorder-fid').val(file.fid);
+ $(element).parent().children('input.media-recorder-refresh').trigger('mousedown');
}
function transferFailed(evt) {
@@ -456,63 +486,8 @@
}
// ********************************************************************
- // * Update Audio Canvas.
+ // * Convert milliseconds to time.
// ********************************************************************
- function updateAudioCanvas(element, options) {
- if (!analyserContext) {
- canvasWidth = element.recorder.canvas[0].width;
- canvasHeight = element.recorder.canvas[0].height;
- analyserContext = element.recorder.canvas[0].getContext('2d');
- }
- var SPACING = 1;
- var BAR_WIDTH = 1;
- var numBars = Math.round(canvasWidth / SPACING);
- var freqByteData = new Uint8Array(analyserNode.frequencyBinCount);
- analyserNode.getByteFrequencyData(freqByteData);
- analyserContext.clearRect(0, 0, canvasWidth, canvasHeight);
- analyserContext.fillStyle = '#F6D565';
- analyserContext.lineCap = 'round';
- var multiplier = analyserNode.frequencyBinCount / numBars;
- // Draw rectangle for each frequency bin.
- for (var i = 0; i < numBars; ++i) {
- var magnitude = 0;
- var offset = Math.floor(i * multiplier);
- for (var j = 0; j < multiplier; j++) {
- magnitude += freqByteData[offset + j];
- }
- magnitude = magnitude / multiplier;
- var magnitude2 = freqByteData[i * multiplier];
- analyserContext.fillStyle = "hsl( " + Math.round((i * 360) / numBars) + ", 100%, 50%)";
- analyserContext.fillRect(i * SPACING, canvasHeight, BAR_WIDTH, -magnitude);
- }
- rafID = window.webkitRequestAnimationFrame(updateAudioCanvas);
- }
-
- // ********************************************************************
- // * Update Audio Element.
- // ********************************************************************
- function updateAudio(element, options) {
- // Adds time to audio url to disable caching.
- var time = new Date().getTime();
- var url = options.drupalURL + '/' + options.drupalFileName;
- // Using hack to support IE9 and below browsers.
- if (wavCheck) {
- $(element).find('.media-recorder-audio audio').attr('src', url + '?' + time);
- } else {
- var embed = '<embed width="300" height="30" autostart="false" src="' + url + '?' + time + '" />';
- $(element).parent().find('.media-recorder-audio').html(embed);
- }
- }
-
- // ********************************************************************
- // * Format Input Field Helper.
- // ********************************************************************
- function fieldFormatter(element, options, name) {
- var language = options.drupalLanguage ? '[' + options.drupalLanguage + ']' : '';
- var delta = (options.drupalDelta !== null) ? '[' + options.drupalDelta + ']' : '';
- return options.drupalFieldName + language + delta + '[' + name + ']';
- }
-
function millisecondsToTime(milliSeconds) {
// Format Current Time
var milliSecondsDate = new Date(milliSeconds);
diff --git a/js/media-recorder-youtube.js b/js/media-recorder-youtube.js
new file mode 100755
index 0000000..5610ddd
--- /dev/null
+++ b/js/media-recorder-youtube.js
@@ -0,0 +1,39 @@
+/**
+ * @file
+ * Adds an interface between the Youtube upload widget and the Drupal media recorder module.
+ */
+
+(function($) {
+ Drupal.behaviors.mediaRecorderYoutube = {
+ attach: function(context, settings) {
+
+ var widget;
+ var element = $('#youtube-upload-widget');
+ var input = element.parent().children('input.media-recorder-youtube');
+
+ // Hide specific file related elements.
+ element.parent().children('span.file, span.file-size, input.media-recorder-upload, input.media-recorder-upload-button').hide();
+
+ // Attaches upload widget to upload div.
+ function onYouTubeIframeAPIReady() {
+ widget = new YT.UploadWidget('youtube-upload', {
+ width: 500,
+ events: {
+ 'onUploadSuccess': onUploadSuccess,
+ }
+ });
+ }
+
+ // Callback fired when video is successfully uploaded.
+ function onUploadSuccess(event) {
+ // Set input value.
+ input.val(event.data.videoId);
+ // Refresh the media recorder form.
+ element.parent().children('input.media-recorder-refresh').trigger('mousedown');
+ }
+
+ // Create widget.
+ onYouTubeIframeAPIReady();
+ }
+ };
+})(jQuery);
diff --git a/js/media-recorder.browser.js b/js/media-recorder.browser.js
new file mode 100644
index 0000000..66abeac
--- /dev/null
+++ b/js/media-recorder.browser.js
@@ -0,0 +1,34 @@
+/**
+ * @file
+ * Media browser JS integration for the Media Recorder module.
+ */
+
+(function($) {
+ Drupal.behaviors.mediaRecorderBrowser = {
+ attach: function (context, settings) {
+
+ // Bind click handler to media recorder submit input.
+ $('#media-tab-media_recorder input[type="submit"]').bind('click', function (event) {
+
+ // Prevent regular form submit.
+ event.preventDefault();
+
+ // Get the fid value.
+ var fid = $('#media-tab-media_recorder .media-recorder-fid').val();
+
+ // Build file object.
+ var file = {};
+ file.fid = fid;
+ file.preview = $('#media-tab-media_recorder .media-recorder-preview .content').html();
+
+ // Add to selected media.
+ var files = new Array();
+ files.push(file);
+ Drupal.media.browser.selectMedia(files);
+
+ // Submit media browser form.
+ Drupal.media.browser.submit();
+ });
+ }
+ }
+})(jQuery);
diff --git a/js/media-recorder.js b/js/media-recorder.js
new file mode 100755
index 0000000..1e12e15
--- /dev/null
+++ b/js/media-recorder.js
@@ -0,0 +1,20 @@
+/**
+ * @file
+ * Adds an interface between the media recorder jQuery plugin and the drupal media module.
+ */
+
+(function($) {
+ Drupal.behaviors.mediaRecorder = {
+ attach: function(context, settings) {
+ $('.media-recorder-wrapper').mediaRecorder({
+ 'recordingPath': Drupal.settings.mediaRecorder.recordingPath,
+ 'filePath': Drupal.settings.mediaRecorder.filePath,
+ 'fileName': Drupal.settings.mediaRecorder.fileName,
+ 'timeLimit': Drupal.settings.mediaRecorder.timeLimit,
+ 'width': Drupal.settings.mediaRecorder.width,
+ 'height': Drupal.settings.mediaRecorder.height,
+ 'swfurl': Drupal.settings.basePath + 'sites/all/libraries/wami/Wami.swf',
+ });
+ }
+ };
+})(jQuery);
diff --git a/js/media_recorder.js b/js/media_recorder.js
deleted file mode 100755
index 760c6f2..0000000
--- a/js/media_recorder.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * @file
- * Adds an interface between the media recorder jQuery plugin and the drupal media module.
- */
-
-(function($) {
- // Add setup to drupal behaviors.
- Drupal.behaviors.mediaRecorder = {
- attach: function(context, settings) {
-
- // Iterate over each media recorder field widget.
- $('.media-recorder-wrapper').each(function(){
-
- // Validation.
- if ($(this).hasClass('media-recorder-processed')) {
- return;
- }
-
- // Hide original field.
- $(this).parent().children('.form-managed-file input').hide();
- $(this).parent().children('.description').hide();
-
- var mediaRecorderWrapper = $(this);
-
- // Add processed class.
- $(this).addClass('media-recorder-processed');
-
- // Instantiate media recorder.
- $(this).mediaRecorder({
- 'timeLimit': Drupal.settings.mediaRecorder.timeLimit,
- 'recordingPath': Drupal.settings.mediaRecorder.recordingPath,
- 'swfURL': Drupal.settings.basePath + 'sites/all/libraries/wami/Wami.swf',
- 'drupalURL': Drupal.settings.mediaRecorder.url,
- 'drupalFilePath': Drupal.settings.mediaRecorder.filePath,
- 'drupalFileName': Drupal.settings.mediaRecorder.fileName,
- 'drupalFieldName': Drupal.settings.mediaRecorder.fieldName,
- 'drupalLanguage': Drupal.settings.mediaRecorder.language,
- 'drupalDelta': Drupal.settings.mediaRecorder.delta,
- });
- });
-
- }
- };
-})(jQuery);
diff --git a/js/media_recorder_youtube.js b/js/media_recorder_youtube.js
deleted file mode 100755
index db64139..0000000
--- a/js/media_recorder_youtube.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * @file
- * Adds an interface between the Youtube upload widget and the Drupal media recorder module.
- */
-
-(function($) {
- // Add setup to drupal behaviors.
- Drupal.behaviors.mediaRecorderYoutube = {
- attach: function(context, settings) {
-
- var widget;
- var player;
- var youtubeInput = fieldFormatter('youtube');
- var currentId = $('input[name="' + youtubeInput + '"]').val();
-
- // Format input field helper.
- function fieldFormatter(name) {
- var fieldName = Drupal.settings.mediaRecorder.fieldName;
- var language = '[' + Drupal.settings.mediaRecorder.language + ']';
- var delta = '[' + Drupal.settings.mediaRecorder.delta + ']';
- return fieldName + language + delta + '[' + name + ']';
- }
-
- // Attaches upload widget to upload div.
- function onYouTubeIframeAPIReady() {
- widget = new YT.UploadWidget('youtube-upload', {
- width: 500,
- events: {
- 'onUploadSuccess': onUploadSuccess,
- 'onProcessingComplete': onProcessingComplete
- }
- });
- }
-
- // Callback fired when video is successfully uploaded.
- function onUploadSuccess(event) {
- $('input[name="' + youtubeInput + '"]').val(event.data.videoId);
- $('#youtube-upload-wrapper').hide();
- $('#youtube-player-wrapper').prepend('<div class="messages warning">Video is currently processing and will not display properly until processing is finished. However, you may save this content at any time without loss of video.</div>');
- player = new YT.Player('youtube-player', {
- height: 390,
- width: 640,
- videoId: event.data.videoId,
- events: {}
- });
- }
-
- // Callback fired when video is finished processing.
- function onProcessingComplete(event) {
- $('#youtube-player-wrapper .messages').removeClass('warning').addClass('status').html('Video is finished processing.');
- }
-
- // Check if there is already a youtube video id.
- if (currentId) {
- // Display video as a video.
- player = new YT.Player('youtube-player', {
- height: 390,
- width: 640,
- videoId: currentId,
- events: {}
- });
- } else {
- // Create widget.
- onYouTubeIframeAPIReady();
- }
- }
- };
-})(jQuery);
diff --git a/media_recorder.info b/media_recorder.info
index cdabb8d..f4a1821 100755
--- a/media_recorder.info
+++ b/media_recorder.info
@@ -4,13 +4,10 @@ package = "Media"
core = 7.x
dependencies[] = ctools
-dependencies[] = file_entity
-dependencies[] = media
+dependencies[] = file_entity (>=2)
+dependencies[] = media (>=2)
dependencies[] = libraries (>=2)
-dependencies[] = modernizr
-dependencies[] = transliteration
files[] = includes/MediaRecorderBrowser.inc
-files[] = media_recorder.drush.inc
configure = admin/config/media/mediarecorder
diff --git a/media_recorder.install b/media_recorder.install
index 0f9df90..132c3aa 100755
--- a/media_recorder.install
+++ b/media_recorder.install
@@ -11,7 +11,7 @@
*/
function media_recorder_enable() {
// Check that all libraries exist.
- $required_libraries = array('modernizr', 'swfobject', 'wami', 'Recorderjs');
+ $required_libraries = array('swfobject', 'wami', 'Recorderjs');
foreach ($required_libraries as $name) {
$library = libraries_detect($name);
if (!$library['installed']) {
diff --git a/media_recorder.media.inc b/media_recorder.media.inc
deleted file mode 100755
index 7f124ee..0000000
--- a/media_recorder.media.inc
+++ /dev/null
@@ -1,17 +0,0 @@
-<?php
-
-/**
- * @file
- * Media module integration for the Media internet module.
- */
-
-/**
- * Implements hook_media_browser_plugin_info().
- */
-function media_recorder_media_browser_plugin_info() {
- $info['media_recorder'] = array(
- 'title' => t('Voice Recorder'),
- 'class' => 'MediaBrowserRecorder',
- );
- return $info;
-}
diff --git a/media_recorder.module b/media_recorder.module
index e41816c..ce87b88 100755
--- a/media_recorder.module
+++ b/media_recorder.module
@@ -53,7 +53,11 @@ function media_recorder_libraries_info() {
'pattern' => '@v([0-9a-zA-Z\.-]+)@',
),
'files' => array(
- 'js' => array('swfobject.js'),
+ 'js' => array('swfobject.js' => array(
+ 'type' => 'file',
+ 'scope' => 'header',
+ 'group' => JS_LIBRARY,
+ )),
),
);
$libraries['wami'] = array(
@@ -87,6 +91,7 @@ function media_recorder_libraries_info() {
*/
function media_recorder_menu() {
$items = array();
+
$items['file/add/record'] = array(
'title' => 'Record',
'description' => 'Add recordings to your media library.',
@@ -110,8 +115,9 @@ function media_recorder_menu() {
'page callback' => 'drupal_get_form',
'page arguments' => array('media_recorder_admin_form'),
'access arguments' => array('administer files'),
- 'file' => 'media_recorder.admin.inc',
+ 'file' => 'includes/media_recorder.admin.inc',
);
+
return $items;
}
@@ -126,80 +132,6 @@ function media_recorder_help($path, $arg) {
}
/**
- * Implements hook_theme().
- */
-function media_recorder_theme() {
- return array(
- 'media_recorder' => array(
- 'template' => 'theme/media-recorder',
- 'variables' => array(
- 'cssid' => 'media-recorder',
- 'width' => 300,
- 'height' => 100,
- 'timelimit' => 300000,
- 'audio' => NULL,
- ),
- ),
- );
-}
-
-/**
- * Preprocess function for a player.
- */
-function template_preprocess_media_recorder(&$variables) {
- $variables['cssid'] = is_string($variables['cssid']) ? $variables['cssid'] : 'media-recorder';
- $variables['width'] = is_numeric($variables['width']) ? $variables['width'] : 300;
- $variables['height'] = is_numeric($variables['height']) ? $variables['height'] : 100;
- $variables['timelimit'] = is_numeric($variables['timelimit']) ? gmdate('i:s', $variables['timelimit']) : '05:00';
- $fid = (isset($variables['audio']) && is_numeric($variables['audio'])) ? $variables['audio'] : '';
- $file = !empty($fid) ? file_load($fid) : NULL;
- // Render audio file.
- if (is_object($file)) {
- $url = file_create_url($file->uri);
- // Mediaelement available.
- if (module_exists('mediaelement')) {
- $settings = array(
- 'controls' => 1,
- 'width' => '100%',
- 'height' => 30,
- 'download_link' => 0,
- 'download_text' => t('Download'),
- );
- $js_settings = array();
- $js_settings['opts'] = array();
- $js_settings['controls'] = (bool) $settings['controls'];
- $js_settings['opts']['audioWidth'] = '100%';
- $js_settings['opts']['audioHeight'] = 30;
- $class = 'mediaelement_audio' . $variables['id'];
- $audio = array(
- '#theme' => 'mediaelement_audio',
- '#attributes' => array(
- 'src' => $url,
- 'class' => $class,
- ),
- '#settings' => $settings,
- '#attached' => array(
- 'library' => array(array('mediaelement', 'mediaelement')),
- 'js' => array(
- drupal_get_path('module', 'mediaelement') . '/mediaelement.js' => array(),
- 0 => array('type' => 'setting', 'data' => array('mediaelement' => array('.' . $class => $js_settings))),
- ),
- ),
- );
- $variables['audio'] = drupal_render($audio);
- }
- // Mediaelement not available.
- else {
- $variables['audio'] = '<audio id="media-recorder-audio" controls src="' . $url . '" type="audio/wav" width="300" height="30"></audio>';
- }
- }
- // No file present.
- else {
- $variables['audio'] = '<audio id="media-recorder-audio" controls width="300" height="30"></audio>';
- }
-}
-
-/**
* Menu callback for recording a media file.
*/
function media_recorder_record() {
@@ -215,13 +147,17 @@ function media_recorder_record() {
}
// Process file.
if (!empty($filename) && !empty($url)) {
- $upload_directory = 'public://media_recorder';
- file_prepare_directory($upload_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
- $uri = $upload_directory . '/' . $filename;
+
+ // Get file data.
+ $uri = 'temporary://' . $filename;
$data = file_get_contents($url);
+
+ // Save file as temporary file.
$file = file_save_data($data, $uri, FILE_EXISTS_REPLACE);
$file->status = 0;
file_save($file);
+
+ // Return file information.
echo drupal_json_output($file);
}
else {
@@ -230,6 +166,18 @@ function media_recorder_record() {
}
/**
+ * Implements hook_media_browser_plugin_info().
+ */
+function media_recorder_media_browser_plugin_info() {
+ $info['media_recorder'] = array(
+ 'title' => t('Recorder'),
+ 'class' => 'MediaRecorderBrowser',
+ );
+
+ return $info;
+}
+
+/**
* Provides a form for adding media items using the Wami Recorder.
*/
function media_recorder_add($form, &$form_state) {
@@ -239,36 +187,59 @@ function media_recorder_add($form, &$form_state) {
$langcode = LANGUAGE_NONE;
$items = array();
$delta = 0;
- $field = array();
+ $field = array(
+ 'field_name' => $field_name,
+ 'cardinality' => 1,
+ 'settings' => array(
+ 'uri_scheme' => 'public',
+ 'display_default' => 0,
+ ),
+ 'cardinality' => 1,
+ );
$instance = array(
'settings' => array(
'file_directory' => variable_get('media_recorder_upload_directory', ''),
'file_extensions' => 'wav mp3 m4a mov m4v mp4 mpeg mpg avi ogg oga ogv',
),
+ 'widget' => array(
+ 'settings' => array(
+ 'progress_indicator' => 'throbber',
+ ),
+ ),
);
$element['#field_name'] = $field_name;
$element['#language'] = $langcode;
$element['#delta'] = $delta;
+ $element['#id'] = 'edit-field-media-recorder-und-0';
$element['#field_parents'] = array();
$element['#columns'] = array('fid', 'display', 'description');
$element['#title'] = t('Media Recorder');
+ $element['#description'] = '';
$element['#required'] = TRUE;
+ $element['#upload_location'] = 'public://' . variable_get('media_recorder_upload_directory', '');
+ $element['#upload_validators']['file_validate_extensions'][] = 'wav';
// Add title field.
- $form['media_recorder']['#title'] = t('Title');
+ $form['#title'] = t('Title');
// Add title field.
- $form['media_recorder']['title']['#type'] = 'textfield';
- $form['media_recorder']['title']['#title'] = t('Title');
- $form['media_recorder']['title']['#required'] = TRUE;
+ $form['title']['#type'] = 'textfield';
+ $form['title']['#title'] = t('Title');
+ $form['title']['#required'] = TRUE;
// Add media recorder element.
- $form['media_recorder']['field_media_recorder']['#type'] = 'container';
- $form['media_recorder']['field_media_recorder']['#tree'] = TRUE;
- $form['media_recorder']['field_media_recorder'][$langcode] = media_recorder_field_widget_form($form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
+ $form[$field_name]['#type'] = 'container';
+ $form[$field_name]['#tree'] = TRUE;
+ $form[$field_name][$langcode] = media_recorder_field_widget_form($form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
+
+ // Remove file field widget process, since this is not an actual field widget.
+ $key = array_search('file_field_widget_process', $form[$field_name][$langcode][0]['#process']);
+ unset($form[$field_name][$langcode][0]['#process'][$key]);
+
+ // Add media browser javascript and CSS.
+ drupal_add_js(drupal_get_path('module', 'media_recorder') . '/js/media-recorder.browser.js');
// Add a submit button.
- $form['actions'] = array('#type' => 'actions');
$form['actions']['submit']['#type'] = 'submit';
$form['actions']['submit']['#value'] = t('Save Recording');
@@ -276,6 +247,25 @@ function media_recorder_add($form, &$form_state) {
}
/**
+ * Submit handler for media_recorder_add form.
+ * @see media_recorder_add().
+ */
+function media_recorder_add_submit($form, &$form_state) {
+ $fid = $form_state['values']['field_media_recorder'][LANGUAGE_NONE][0]['fid'];
+ if ($fid != 0) {
+ $file = file_load($fid);
+ if (!$file->status) {
+ $file->status = FILE_STATUS_PERMANENT;
+ $file = file_save($file);
+ }
+ drupal_set_message(t('The file <em>!filename</em> was successfully loaded.', array('!filename' => l(check_plain($file->filename), file_create_url($file->uri)))), 'status');
+ }
+ else {
+ drupal_set_message(t('An unrecoverable error occurred. Try reloading the page and submitting again.'), 'error');
+ }
+}
+
+/**
* Implements hook_field_widget_info().
*/
function media_recorder_field_widget_info() {
@@ -296,309 +286,216 @@ function media_recorder_field_widget_info() {
}
/**
+ * Implements hook_field_widget_settings_form().
+ */
+function media_recorder_field_widget_settings_form($field, $instance) {
+
+ // Get default file widget settings form.
+ $form = file_field_widget_settings_form($field, $instance);
+
+ return $form;
+}
+
+/**
* Implements hook_field_widget_form().
*/
function media_recorder_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
- // Set recorder variables.
- $field_name = $element['#field_name'];
- $filename = uniqid() . '.wav';
- $recordpath = url('media_recorder/record');
- $filepath = 'public://media_recorder';
- $url = file_create_url($filepath);
- $fid = 0;
-
- $element['#type'] = 'fieldset';
+ // Get default file widget form.
+ $elements = file_field_widget_form($form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
- // Determine the current file id.
- if (isset($form_state['values']['fid']) && !empty($form_state['values']['fid'])) {
- $fid = $form_state['values']['fid'];
- }
- elseif (isset($element['#entity']->{$field_name}[$langcode][$delta]['fid']) && !empty($element['#entity']->{$field_name}[$langcode][$delta]['fid'])) {
- $fid = $element['#entity']->{$field_name}[$langcode][$delta]['fid'];
+ // Alter process callbacks.
+ $element_info = element_info('managed_file');
+ foreach (element_children($elements) as $delta) {
+ $elements[$delta]['#process'][] = 'media_recorder_field_widget_form_process';
}
- // Build file field and set values.
- $element[$delta]['fid']['#type'] = 'hidden';
- $element[$delta]['fid']['#value'] = $fid;
- $element[$delta]['display']['#type'] = 'hidden';
- $element[$delta]['display']['#value'] = TRUE;
+ return $elements;
+}
- // Add upload location and validators.
- $element['#upload_location'] = $instance['settings']['file_directory'];
- if (isset($instance['settings']['file_extensions'])) {
- $validators['file_validate_extensions'] = array($instance['settings']['file_extensions']);
- }
- if (isset($instance['settings']['max_filesize'])) {
- $validators['file_validate_size'] = array($instance['settings']['max_filesize']);
- }
- $element['#upload_validators'] = array($validators);
+/**
+ * An element #process callback.
+ * @see media_recorder_field_widget_form().
+ */
+function media_recorder_field_widget_form_process($element, &$form_state, $form) {
- // If browscap is installed, check if ismobiledevice.
- if (module_exists('browscap')) {
- $browser = browscap_get_browser();
- }
+ // Get field info.
+ $field_name = $element['#field_name'];
+ $langcode = $element['#language'];
+ $delta = $element['#delta'];
+
+ // Get fid and set media-recorder specific class.
+ $fid = isset($element['#value']['fid']) ? $element['#value']['fid'] : (isset($form_state['values'][$field_name][$langcode][$delta]['fid']) ? $form_state['values'][$field_name][$langcode][$delta]['fid'] : 0);
+ $element['fid']['#attributes']['class'][] = 'media-recorder-fid';
- // If this is a mobile device, only show a file field.
- if (isset($browser)) {
- if ($browser['ismobiledevice'] == 'true' || $browser['ismobiledevice'] == TRUE) {
- $element[$delta]['file'] = array(
- '#type' => 'file',
- '#required' => $element['#required'],
- '#title' => t('File'),
- '#title_display' => 'invisible',
- );
- $element['#element_validate'][] = 'media_recorder_field_widget_form_file_validate';
- return $element;
+ $element['upload']['#attributes']['class'][] = 'media-recorder-upload';
+ $element['upload_button']['#attributes']['class'][] = 'media-recorder-upload-button';
+ $element['remove_button']['#attributes']['class'][] = 'media-recorder-remove-button';
+ $element['remove_button']['#weight'] = 100;
+
+ // Add file preview to render array.
+ if ($fid) {
+ $file = file_load($fid);
+ $element['preview'] = array(
+ 'file' => file_view($file),
+ '#weight' => 100,
+ '#prefix' => '<div class="media-recorder-preview">',
+ '#suffix' => '</div>',
+ );
+ if ($file->filemime == 'video/youtube') {
+ // Remove file element upload validators.
+ unset($element['#upload_validators']);
+ $form_state['values'][$field_name][$langcode][$delta]['toggle'] = 'youtube';
}
}
- // Set current toggle state and options.
- $toggle = isset($form_state['values']['op']) ? $form_state['values']['op'] : 'Recorder';
+ // Append a description.
+ $element['#description'] .= '<br />Before recording please fill in content title, which is used to generate the recording filename.';
- // Add toggle buttons if youtube is a provider.
+ // Add toggle buttons.
+ $toggle = isset($form_state['values'][$field_name][$langcode][$delta]['toggle']) ? $form_state['values'][$field_name][$langcode][$delta]['toggle'] : 'record';
if (module_exists('media_youtube')) {
- // Toggle record.
- $element[$delta]['toggle']['#prefix'] = '<div class="media-recorder-toggle">';
- $element[$delta]['toggle']['#suffix'] = '</div>';
-
- $element[$delta]['toggle']['record']['#type'] = 'button';
- $element[$delta]['toggle']['record']['#value'] = t('Recorder');
- $element[$delta]['toggle']['record']['#executes_submit_callback'] = FALSE;
- $element[$delta]['toggle']['record']['#limit_validation_errors'] = array();
- $element[$delta]['toggle']['record']['#attributes']['class'][] = 'button';
- $element[$delta]['toggle']['record']['#attributes']['title'] = t('Record using the HTML5 or Flash recorder.');
-
- // Toggle youtube upload widget.
- $element[$delta]['toggle']['youtube']['#type'] = 'button';
- $element[$delta]['toggle']['youtube']['#value'] = t('Youtube');
- $element[$delta]['toggle']['youtube']['#executes_submit_callback'] = FALSE;
- $element[$delta]['toggle']['youtube']['#limit_validation_errors'] = array();
- $element[$delta]['toggle']['youtube']['#attributes']['class'][] = 'button';
- $element[$delta]['toggle']['youtube']['#attributes']['title'] = t('Record using the Youtube Upload Widget.');
+ $element['toggle'] = array(
+ '#type' => 'radios',
+ '#options' => array(
+ 'record' => t('Recorder'),
+ 'youtube' => t('Youtube'),
+ ),
+ '#default_value' => $toggle,
+ '#ajax' => array(
+ 'callback' => 'media_recorder_field_widget_form_process_ajax_refresh',
+ 'wrapper' => $element['#id'] . '-ajax-wrapper',
+ ),
+ '#attributes' => array(
+ 'class' => array('media-recorder-toggle'),
+ ),
+ );
}
// Use the HTML5/Wami recorder.
- if ($toggle == 'Recorder') {
-
- // Add active class.
- $element[$delta]['toggle']['record']['#attributes']['class'][] = 'active';
+ if ($toggle == 'record') {
// Add hidden fields for wami recorder.
- $element[$delta]['filepath']['#type'] = 'hidden';
-
- // Set theme variables for media recorder.
- $media_recorder = variable_get('media_recorder', array());
- $media_recorder_fid = isset($media_recorder[$langcode][0]['fid']) ? $media_recorder[$langcode][0]['fid'] : '';
- $variables = array(
- 'cssid' => 'media-recorder-' . $field_name . '-' . $langcode . '-' . $delta,
- 'width' => variable_get('media_recorder_width', 300),
- 'height' => variable_get('media_recorder_height', 100),
- 'timelimit' => variable_get('media_recorder_timelimit', 300),
- 'audio' => !empty($fid) ? $fid : $media_recorder_fid,
- );
+ $element['filepath']['#type'] = 'hidden';
+ $element['filepath']['#attributes']['class'][] = 'media-recorder-filepath';
// Add media recorder markup.
- $element[$delta]['media_recorder']['#markup'] = theme('media_recorder', $variables);
-
- // Add javascript and css files.
- $element[$delta]['media_recorder']['#attached']['library'][] = array('system', 'ui.progressbar');
- $element[$delta]['media_recorder']['#attached']['library'][] = array('system', 'ui.slider');
- $element[$delta]['media_recorder']['#attached']['libraries_load'][] = array('swfobject');
- $element[$delta]['media_recorder']['#attached']['libraries_load'][] = array('wami');
- $element[$delta]['media_recorder']['#attached']['libraries_load'][] = array('Recorderjs');
- $element[$delta]['media_recorder']['#attached']['css'][] = drupal_get_path('module', 'media_recorder') . '/css/media_recorder.css';
- $element[$delta]['media_recorder']['#attached']['js'][] = drupal_get_path('module', 'media_recorder') . '/js/media_recorder.js';
- $element[$delta]['media_recorder']['#attached']['js'][] = drupal_get_path('module', 'media_recorder') . '/js/jquery.mediaRecorder.js';
-
- // Add validation handlers.
- $element['#element_validate'][] = 'media_recorder_field_widget_form_record_validate';
+ $element['record']['#markup'] = '<div class="media-recorder-wrapper"></div>';
+
+ // Add validation handler to beginning of validation handler stack.
+ array_unshift($element['#element_validate'], 'media_recorder_field_widget_form_process_record_validate');
}
// Use the youtube upload widget.
- if ($toggle == 'Youtube') {
-
- // Add active class.
- $element[$delta]['toggle']['youtube']['#attributes']['class'][] = 'active';
+ if ($toggle == 'youtube') {
// Add hidden fields for youtube.
- $element[$delta]['youtube']['#type'] = 'hidden';
+ $element['youtube']['#type'] = 'hidden';
+ $element['youtube']['#attributes']['class'][] = 'media-recorder-youtube';
// Add youtube recorder markup.
- $element[$delta]['youtube_upload']['#markup'] = '<div id="youtube-upload-widget"><div id="youtube-player-wrapper"><div id="youtube-player"></div></div><div id="youtube-upload-wrapper"><div id="youtube-upload"></div></div></div>';
+ $element['youtube_upload']['#markup'] = '<div id="youtube-upload-widget"><div id="youtube-player-wrapper"><div id="youtube-player"></div></div><div id="youtube-upload-wrapper"><div id="youtube-upload"></div></div></div>';
- // Add javascript and css files.
- $element[$delta]['#attached']['js'][] = 'https://s.ytimg.com/yts/jsbin/www-widgetapi-vflop0WbJ.js';
- $element[$delta]['#attached']['js'][] = 'https://www.youtube.com/iframe_api';
- $element[$delta]['#attached']['js'][] = drupal_get_path('module', 'media_recorder') . '/js/media_recorder_youtube.js';
+ // Add validation handler while overwritting normal file validation handlers.
+ $element['#element_validate'] = array('media_recorder_field_widget_form_process_youtube_validate');
- // Add validation handlers.
- $element['#element_validate'][] = 'media_recorder_field_widget_form_youtube_validate';
+ // Remove file element upload validators.
+ unset($element['#upload_validators']);
}
- // Add javascript settings.
+ // Add hidden refresh submit, which is triggered on record finish.
+ // This will rebuild the form with new file preview.
+ $element['refresh'] = array(
+ '#type' => 'submit',
+ '#executes_submit_callback' => FALSE,
+ '#value' => t('Refresh'),
+ '#ajax' => array(
+ 'callback' => 'media_recorder_field_widget_form_process_ajax_refresh',
+ 'wrapper' => $element['#id'] . '-ajax-wrapper',
+ ),
+ '#attributes' => array(
+ 'class' => array('js-hide', 'media-recorder-refresh'),
+ ),
+ );
+
+ // Add javascript and css.
$element['#attached']['js'][] = array(
'data' => array(
'mediaRecorder' => array(
- 'fieldName' => $field_name,
- 'language' => $langcode,
- 'delta' => $delta,
- 'fileName' => $filename,
- 'recordingPath' => $recordpath,
- 'filePath' => $filepath,
- 'url' => $url,
+ 'recordingPath' => url('media_recorder/record'),
+ 'fileName' => uniqid() . '.wav',
+ 'filePath' => 'temporary://',
'timeLimit' => variable_get('media_recorder_timelimit', 300) * 1000,
+ 'width' => variable_get('media_recorder_width', 300),
+ 'height' => variable_get('media_recorder_height', 100),
),
),
'type' => 'setting',
);
+ $element['#attached']['library'][] = array('system', 'ui.progressbar');
+ $element['#attached']['library'][] = array('system', 'ui.slider');
+ $element['#attached']['libraries_load'][] = array('swfobject');
+ $element['#attached']['libraries_load'][] = array('wami');
+ $element['#attached']['libraries_load'][] = array('Recorderjs');
+ $element['#attached']['css'][] = drupal_get_path('module', 'media_recorder') . '/css/media-recorder.css';
+ $element['#attached']['js'][] = drupal_get_path('module', 'media_recorder') . '/js/media-recorder.js';
+ $element['#attached']['js'][] = drupal_get_path('module', 'media_recorder') . '/js/jquery.mediaRecorder.js';
+ $element['#attached']['js'][] = 'https://s.ytimg.com/yts/jsbin/www-widgetapi-vflop0WbJ.js';
+ $element['#attached']['js'][] = 'https://www.youtube.com/iframe_api';
+ $element['#attached']['js'][] = drupal_get_path('module', 'media_recorder') . '/js/media-recorder-youtube.js';
return $element;
}
/**
- * Custom validation callback.
- * @see media_recorder_field_widget_form()
+ * Ajax callback for form element rebuild.
+ * @see media_recorder_field_widget_form_process().
*/
-function media_recorder_field_widget_form_file_validate($element, &$form_state) {
+function media_recorder_field_widget_form_process_ajax_refresh($form, &$form_state) {
- // Get field information.
- $field_name = $element['#parents'][0];
- $langcode = $element['#parents'][1];
- $delta = $element['#parents'][2];
+ // Rebuild the form.
+ $form_state['rebuild'] = TRUE;
- // Get field values.
- $title = '';
- $fid = $form_state['values'][$field_name][$langcode][$delta]['fid'];
- $file = file_save_upload($field_name, $element['#upload_validators']);
-
- // Form was saved with an existing fid set and no new file.
- if ($fid && !$file) {
- // Set file field values if needed.
- $form_state['values'][$field_name][$langcode][$delta]['fid'] = $fid;
- $form_state['values'][$field_name][$langcode][$delta]['display'] = 1;
- return;
- }
+ // Get the file field element.
+ $parents = $form_state['triggering_element']['#array_parents'];
+ array_pop($parents);
+ array_pop($parents);
+ array_pop($parents);
+ $element = drupal_array_get_nested_value($form, $parents);
- // Check that file exists.
- if (!$file) {
- if ($element['#required']) {
- form_set_error('media_recorder', t('No Recording submitted.'));
- return;
- }
- else {
- return;
- }
- }
-
- // Grab title from entity if available.
- if (isset($form_state['values']['title']) && !empty($form_state['values']['title'])) {
- $title = $form_state['values']['title'];
- }
-
- // Add custom logic for comments.
- elseif (isset($form_state['comment']) && is_object($form_state['comment'])) {
- // Use the comment subject value if present.
- if (isset($form_state['values']['subject']) && !empty($form_state['values']['subject'])) {
- $title = $form_state['values']['subject'];
- }
- // Otherwise use the node title.
- elseif (isset($form_state['comment']->nid) && is_numeric($form_state['comment']->nid)) {
- $node = node_load($form_state['values']['nid']);
- $title = t('Comment on @title', array('@title' => $node->title));
- }
- }
-
- // Check title exists.
- if (empty($title)) {
- form_set_error('title', t('Recording cannot be saved without a title.'));
- return;
- }
-
- // Validate file.
- $file->filename = drupal_basename($file->uri);
- $file_validate_size_errors = file_validate($file, $element['#upload_validators']);
- if (empty($file_validate_size_errors)) {
-
- // Prepare directory.
- $path_info = pathinfo($file->uri);
- if (module_exists('token')) {
- $upload_location = 'public://' . token_replace($element['#upload_location']);
- }
- else {
- $upload_location = 'public://' . $element['#upload_location'];
- }
- if (file_prepare_directory($upload_location, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
-
- // Move file to change it's filename.
- $file = file_move($file, $upload_location . '/' . transliteration_clean_filename($title) . '.' . $path_info['extension']);
-
- // Save permanent file with new title.
- $file->filename = trim($title);
- $file->display = TRUE;
- $file->status = FILE_STATUS_PERMANENT;
- $file = file_save($file);
-
- // Set file field values if needed.
- $form_state['values'][$field_name][$langcode][$delta]['fid'] = $file->fid;
- $form_state['values'][$field_name][$langcode][$delta]['display'] = 1;
-
- // Delete the old file if it exists.
- if ($fid !== $file->fid) {
- $file = file_load($fid);
- file_delete($file);
- }
- }
- }
-
- // Report file validation errors.
- else {
- form_set_error('media_recorder', implode('<br />', $file_validate_size_errors));
- return;
- }
+ return $element;
}
/**
* Custom validation callback.
- * @see media_recorder_field_widget_form()
+ * @see media_recorder_field_widget_form_process()
*/
-function media_recorder_field_widget_form_record_validate($element, &$form_state) {
+function media_recorder_field_widget_form_process_record_validate(&$element, &$form_state) {
// Get field information.
$field_name = $element['#parents'][0];
$langcode = $element['#parents'][1];
$delta = isset($element['#parents'][2]) ? $element['#parents'][2] : 0;
- // Get field values.
- $title = '';
- $filepath = !empty($form_state['values'][$field_name][$langcode][$delta]['filepath']) ? $form_state['values'][$field_name][$langcode][$delta]['filepath'] : '';
- $fid = !empty($form_state['values'][$field_name][$langcode][$delta]['fid']) ? $form_state['values'][$field_name][$langcode][$delta]['fid'] : 0;
-
- // Check file exists.
- if ($fid == 0 && empty($filepath)) {
- if ($element['#required']) {
- form_set_error('media_recorder', t('No Recording submitted.'));
- return;
- }
- else {
- return;
- }
- }
-
// Load file from filepath (file saved with WAMI recorder).
- // WAMI doesn't give access to server response, so we use file uri.
+ // WAMI doesn't give access to server response, so we use the file uri.
// This will be deprecated when getUserMedia is available and consistant
// in all browsers.
+ $filepath = !empty($form_state['values'][$field_name][$langcode][$delta]['filepath']) ? $form_state['values'][$field_name][$langcode][$delta]['filepath'] : '';
if (is_string($filepath) && !empty($filepath)) {
$file = file_uri_to_object($filepath);
}
- // Load file from fid (files saved using XHR).
- else {
+ // Get the fid.
+ $fid = !empty($form_state['values'][$field_name][$langcode][$delta]['fid']) ? $form_state['values'][$field_name][$langcode][$delta]['fid'] : 0;
+
+ // Load file from fid.
+ if ($fid != 0) {
$file = file_load($fid);
}
// Grab title from entity if available.
+ $title = '';
if (isset($form_state['values']['title']) && !empty($form_state['values']['title'])) {
$title = $form_state['values']['title'];
}
@@ -616,16 +513,10 @@ function media_recorder_field_widget_form_record_validate($element, &$form_state
}
}
- // Check title exists.
- if (empty($title)) {
- form_set_error('title', t('Recording cannot be saved without a title.'));
- return;
- }
-
// Process file.
- if ($file) {
+ if (isset($file->fid)) {
- // Validate file.
+ // Validate file extensions, since managed file validates client side.
$file->filename = drupal_basename($file->uri);
$file_validate_size_errors = file_validate($file, $element['#upload_validators']);
if (empty($file_validate_size_errors)) {
@@ -633,25 +524,34 @@ function media_recorder_field_widget_form_record_validate($element, &$form_state
// Prepare directory.
$path_info = pathinfo($file->uri);
if (module_exists('token')) {
- $upload_location = 'public://' . token_replace($element['#upload_location']);
+ $upload_location = token_replace($element['#upload_location']);
}
else {
- $upload_location = 'public://' . $element['#upload_location'];
+ $upload_location = $element['#upload_location'];
}
if (file_prepare_directory($upload_location, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
- // Move file to change it's filename.
- $file = file_move($file, $upload_location . '/' . transliteration_clean_filename($title) . '.' . $path_info['extension']);
-
- // Save permanent file with new title.
- $file->filename = trim($title);
- $file->display = TRUE;
- $file->status = FILE_STATUS_PERMANENT;
- $file = file_save($file);
-
- // Set file field values if needed.
- $form_state['values'][$field_name][$langcode][$delta]['fid'] = $file->fid;
- $form_state['values'][$field_name][$langcode][$delta]['display'] = 1;
+ // Add new title.
+ if (!empty($title)) {
+ $file->filename = trim($title);
+ }
+
+ // Move the file to the field's upload location.
+ $file = file_move($file, $upload_location);
+
+ // Set file field input & values.
+ drupal_array_set_nested_value($form_state['input'], $element['#parents'], array('fid' => $file->fid, 'display' => TRUE, 'toggle' => 'record'));
+ drupal_array_set_nested_value($form_state['values'], $element['#parents'], array('fid' => $file->fid, 'display' => TRUE, 'toggle' => 'record'));
+
+ // If fid is not set (using filepath from WAMI), Set element values for correct
+ // interaction with file module.
+ // @see file_managed_file_validate().
+ // @see theme_file_widget().
+ if (!empty($filepath)) {
+ $element['fid']['#value'] = $file->fid;
+ $element['#file'] = $file;
+ $element['filename']['#markup'] = $file->filename;
+ }
}
}
@@ -665,9 +565,9 @@ function media_recorder_field_widget_form_record_validate($element, &$form_state
/**
* Custom validation callback.
- * @see media_recorder_field_widget_form()
+ * @see media_recorder_field_widget_form_process()
*/
-function media_recorder_field_widget_form_youtube_validate($element, &$form_state) {
+function media_recorder_field_widget_form_process_youtube_validate($element, &$form_state) {
// Get field information.
$field_name = $element['#parents'][0];
@@ -679,29 +579,8 @@ function media_recorder_field_widget_form_youtube_validate($element, &$form_stat
$fid = !empty($form_state['values'][$field_name][$langcode][$delta]['fid']) ? $form_state['values'][$field_name][$langcode][$delta]['fid'] : 0;
$youtube = !empty($form_state['values'][$field_name][$langcode][$delta]['youtube']) ? $form_state['values'][$field_name][$langcode][$delta]['youtube'] : '';
- // Form was saved with an existing fid set and no new file.
- if ($fid && (!is_string($youtube) || empty($youtube))) {
- // Set file field values if needed.
- $form_state['values'][$field_name][$langcode][$delta]['fid'] = $fid;
- $form_state['values'][$field_name][$langcode][$delta]['display'] = 1;
- return;
- }
-
- // Check that a youtube video was uploaded.
- if ($fid == 0 && (!is_string($youtube) || empty($youtube))) {
- if ($element['#required']) {
- form_set_error('youtube_upload', t('No Recording submitted.'));
- return;
- }
- else {
- return;
- }
- }
-
- // Create a youtube link from youtube video value.
- $embed_code = 'http://youtube.com/watch?v=' . $youtube;
-
// Grab title from entity if available.
+ $title = '';
if (isset($form_state['values']['title']) && !empty($form_state['values']['title'])) {
$title = $form_state['values']['title'];
}
@@ -719,36 +598,36 @@ function media_recorder_field_widget_form_youtube_validate($element, &$form_stat
}
}
- // Check title exists.
- if (empty($title)) {
- form_set_error('title', t('Recording cannot be saved without a title.'));
- return;
- }
+ if (is_string($youtube) && !empty($youtube)) {
- // Try saving the youtube file using media_internet_get_provider().
- try {
- $provider = media_internet_get_provider($embed_code);
- $file = $provider->save();
- }
- catch (Exception $e) {
- form_set_error('youtube', $e->getMessage());
- return;
- }
+ // Create a youtube link from youtube video value.
+ $embed_code = 'http://youtube.com/watch?v=' . $youtube;
- // Check that file saved correctly.
- if (!$file->fid) {
- form_set_error('youtube', t('The file %file could not be saved. An unknown error has occurred.', array('%file' => $embed_code)));
- return;
- }
- else {
- // Save permanent file with new title.
- $file->filename = trim($title);
- $file->display = TRUE;
- $file->status = FILE_STATUS_PERMANENT;
- $file = file_save($file);
-
- // Set file field values if needed.
- $form_state['values'][$field_name][$langcode][$delta]['fid'] = $file->fid;
- $form_state['values'][$field_name][$langcode][$delta]['display'] = 1;
+ // Try saving the youtube file using media_internet_get_provider().
+ try {
+ $provider = media_internet_get_provider($embed_code);
+ $file = $provider->save();
+ }
+ catch (Exception $e) {
+ form_set_error('youtube', $e->getMessage());
+ return;
+ }
+
+ // Check that file saved correctly.
+ if (!$file->fid) {
+ form_set_error('youtube', t('The file %file could not be saved. An unknown error has occurred.', array('%file' => $embed_code)));
+ return;
+ }
+ else {
+ // Save as temporary file with new title.
+ $file->filename = trim($title);
+ $file->display = TRUE;
+ $file->status = 0;
+ $file = file_save($file);
+
+ // Set file field input & values.
+ drupal_array_set_nested_value($form_state['input'], $element['#parents'], array('fid' => $file->fid, 'display' => TRUE, 'toggle' => 'youtube'));
+ drupal_array_set_nested_value($form_state['values'], $element['#parents'], array('fid' => $file->fid, 'display' => TRUE, 'toggle' => 'youtube'));
+ }
}
}
diff --git a/theme/media-recorder.tpl.php b/theme/media-recorder.tpl.php
deleted file mode 100644
index 4156c8b..0000000
--- a/theme/media-recorder.tpl.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-/**
- * @file
- * Provides markup for the media recorder.
- *
- * Variables available:
- * - $cssid: The CSS id to use for the wrapper div.
- * - $width: The width of the wrapper div.
- * - $height: The height of the wrapper div.
- * - $timelimit: The recording time limit.
- * - $audio: The themed audio element.
- */
-?>
-
-<div id="<?php print $cssid; ?>" class="media-recorder-wrapper" style="width:<?php print $width; ?>px; height:<?php print $height + 30; ?>px;">
- <div class="media-recorder-audio" style="width:<?php print $width; ?>px; height: 30px;">
- <?php print $audio; ?>
- </div>
-</div>