diff --git a/css/media_recorder.css b/css/media-recorder.css similarity index 90% rename from css/media_recorder.css rename to css/media-recorder.css index 71a87fb7e05d3c23a739ebc2b42336e2c444ca0b..005d3a526ecaa55cfe2b7ba9f7c1c9371f899edf 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 similarity index 100% rename from media_recorder.admin.inc rename to includes/media_recorder.admin.inc diff --git a/media_recorder.drush.inc b/includes/media_recorder.drush.inc similarity index 87% rename from media_recorder.drush.inc rename to includes/media_recorder.drush.inc index ab578656fb605c3c5038cab13af1eda7a71ea35e..895971b214eb8a7a815bff1fe0e14361381099fb 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 a7a2b985ce8a1ba8e58e34845661ade669cb9203..ecd179dcdc7d795a6ebe3dcc638ac1e9609f612b 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($('
Flash 10 or higher must be installed in order to record.
')); + } + // 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 = $('
'); + element.recorder = $('
').width(options.width).height(options.height); element.recorder.controls = $('
'); element.recorder.canvas = $(''); element.recorder.status = $('
00:00 / ' + millisecondsToTime(options.timeLimit) + '
'); @@ -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('
'); 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($('
Flash 10 or higher must be installed in order to record.
')); - return; - } - // Build recorder. element.recorder = $('
'); element.recorder.controls = $('
'); @@ -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 = ''; - $(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 0000000000000000000000000000000000000000..5610ddd47ae86cb8e869b12004b2fb4d73d2b825 --- /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 0000000000000000000000000000000000000000..66abeac5b9ad54a14a356bee5dfb662e11789da6 --- /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 0000000000000000000000000000000000000000..1e12e15092d6dd454889eb22293ffc1109814769 --- /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 760c6f2a2944a2697defc5ec7514400da5214b36..0000000000000000000000000000000000000000 --- 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 db64139374510c49956e7778a89efb96ebdb429c..0000000000000000000000000000000000000000 --- 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('
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.
'); - 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 cdabb8d0e3d1d5d0c932b9060c1133ea8abf2433..f4a182131faa0ea214938da81b22d341f875af83 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 0f9df9013105eba1a6f75a610d8beda4d93f6988..132c3aa517633d47272cb32e460b1d5e3405c694 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 7f124eecd19d244c99d0396de723e7807ebcef15..0000000000000000000000000000000000000000 --- a/media_recorder.media.inc +++ /dev/null @@ -1,17 +0,0 @@ - t('Voice Recorder'), - 'class' => 'MediaBrowserRecorder', - ); - return $info; -} diff --git a/media_recorder.module b/media_recorder.module index e41816ce362b3656fc18683bcb6d197998e433f3..ce87b88f020bfd1e7297fc4652fde031b4aaa71b 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; } @@ -125,80 +131,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'] = ''; - } - } - // No file present. - else { - $variables['audio'] = ''; - } -} - /** * Menu callback for recording a media file. */ @@ -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 { @@ -229,6 +165,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. */ @@ -239,42 +187,84 @@ 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'); return $form; } +/** + * 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 !filename 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(). */ @@ -295,310 +285,217 @@ 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' => '
', + '#suffix' => '
', + ); + 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'] .= '
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'] = '
'; - $element[$delta]['toggle']['#suffix'] = '
'; - - $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'] = '
'; + + // 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'] = '
'; + $element['youtube_upload']['#markup'] = '
'; - // 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('
', $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 4156c8b954ce2d1087f519c3b4dcb65b33a52df8..0000000000000000000000000000000000000000 --- a/theme/media-recorder.tpl.php +++ /dev/null @@ -1,19 +0,0 @@ - - -
-
- -
-