r84000 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r83999‎ | r84000 | r84001 >
Date:06:20, 15 March 2011
Author:dale
Status:deferred
Tags:
Comment:
* initial stubs for firefogg transport
* shift toward more lazy init of components
* added firefoggEncodeSettings to use transcode ext if available
Modified paths:
  • /trunk/extensions/UploadWizard/UploadWizard.config.php (modified) (history)
  • /trunk/extensions/UploadWizard/UploadWizardHooks.php (modified) (history)
  • /trunk/extensions/UploadWizard/resources/mw.ApiUploadHandler.js (modified) (history)
  • /trunk/extensions/UploadWizard/resources/mw.FirefoggHandler.js (added) (history)
  • /trunk/extensions/UploadWizard/resources/mw.FirefoggTransport.js (added) (history)
  • /trunk/extensions/UploadWizard/resources/mw.UploadWizard.js (modified) (history)
  • /trunk/extensions/UploadWizard/resources/mw.UploadWizardUploadInterface.js (modified) (history)

Diff [purge]

Index: trunk/extensions/UploadWizard/UploadWizard.config.php
@@ -4,7 +4,8 @@
55 * Do not modify this file, instead use localsettings.php and set:
66 * $wgUploadWizardConfig[ 'name'] = 'value';
77 */
8 -global $wgFileExtensions, $wgServer, $wgScriptPath, $wgAPIModules;
 8+global $wgFileExtensions, $wgServer, $wgScriptPath, $wgAPIModules,
 9+$wgTimedMediaHandlerFileExtensions, $wgAutoloadClasses;
910 return array(
1011 // Upload wizard has an internal debug flag
1112 'debug' => false,
@@ -21,6 +22,20 @@
2223 // Check if we have the firefogg upload api module enabled:
2324 'enableFirefoggChunkUpload' => isset( $wgAPIModules['firefoggupload'] )? true : false,
2425
 26+ // Firefogg encode settings ( if timed media handler extension is installed use HD webm, else mid-rage ogg )
 27+ 'firefoggEncodeSettings' => ( class_exists( 'WebVideoTranscode' ) )?
 28+ WebVideoTranscode::$derivativeSettings[ WebVideoTranscode::ENC_WEBM_HQ_VBR ] :
 29+ array(
 30+ 'maxSize' => '480',
 31+ 'videoBitrate' => '512',
 32+ 'audioBitrate' => '96',
 33+ 'noUpscaling' => 'true',
 34+ 'twopass' => 'true',
 35+ 'keyframeInterval' => '128',
 36+ 'bufDelay' => '256',
 37+ 'codec' => 'theora',
 38+ ),
 39+
2540 // The default api url is for the current wiki ( can override at run time )
2641 'apiUrl' => $wgServer . $wgScriptPath . '/api.php',
2742
Index: trunk/extensions/UploadWizard/UploadWizardHooks.php
@@ -57,6 +57,11 @@
5858 // workhorse libraries
5959 'resources/mw.IframeTransport.js',
6060 'resources/mw.ApiUploadHandler.js',
 61+
 62+ // firefogg support
 63+ 'resources/mw.FirefoggHandler.js',
 64+ 'resources/mw.FirefoggTransport.js',
 65+
6166 'resources/mw.DestinationChecker.js',
6267 'resources/mw.UploadWizardUtil.js',
6368
@@ -64,9 +69,8 @@
6570 'resources/mw.GroupProgressBar.js',
6671
6772 // UploadWizard specific abstractions
68 - 'resources/mw.UploadWizardDeed.js',
6973 'resources/mw.UploadWizardLicenseInput.js',
70 -
 74+
7175 // main library
7276 'resources/mw.UploadWizard.js',
7377
Index: trunk/extensions/UploadWizard/resources/mw.FirefoggHandler.js
@@ -0,0 +1,105 @@
 2+/**
 3+ * An attempt to refactor out the stuff that does API-via-iframe transport
 4+ * In the hopes that this will eventually work for AddMediaWizard too
 5+ */
 6+
 7+/**
 8+ * Represents an object which configures a form to upload its files via an iframe talking to the MediaWiki API.
 9+ * @param an UploadInterface object, which contains a .form property which points to a real HTML form in the DOM
 10+ */
 11+mw.FirefoggHandler = function( upload ) {
 12+ return this.init( upload );
 13+};
 14+
 15+mw.FirefoggHandler.prototype = {
 16+ // The transport object
 17+ transport : null, // lazy init
 18+ /**
 19+ * Constructor
 20+ */
 21+ init: function( upload ){
 22+ this.upload = upload;
 23+ this.api = upload.api;
 24+
 25+ // Setup local pointer to firefogg instance
 26+ this.fogg = new Firefogg();
 27+
 28+ // the Iframe transport is hardcoded for now because it works everywhere
 29+ // can also use Xhr Binary depending on browser
 30+ var _this = this;
 31+
 32+ },
 33+ getTransport: function(){
 34+ var _this = this;
 35+ if( this.transport ){
 36+ return this.transport;
 37+ }
 38+ this.transport = new mw.FirefoggTransport(
 39+ this.getForm(),
 40+ this.fogg,
 41+ function( fraction ) {
 42+ _this.upload.setTransportProgress( fraction );
 43+ // also update preview video:
 44+ },
 45+ function( result ) {
 46+ _this.upload.setTransported( result );
 47+ }
 48+ );
 49+ return this.transport;
 50+ },
 51+ isGoodExtension: function( ext ){
 52+ // First check if its an oky extension for the wiki:
 53+ if( $j.inArray( ext.toLowerCase(), mw.UploadWizard.config[ 'fileExtensions' ] ) !== -1 ){
 54+ return true;
 55+ }
 56+ // Check if its a file that can be transcoded:
 57+ if( this.getTransport().isSourceAudio() || this.getTransport().isSourceVideo() ){
 58+ return true;
 59+ }
 60+ return false;
 61+ },
 62+
 63+ getForm: function(){
 64+ return $j( this.upload.ui.form );
 65+ },
 66+
 67+ /**
 68+ * Get a pointer to the "file" input control
 69+ */
 70+ getInputControl: function(){
 71+ var _this = this;
 72+ return $j('<input />').attr({
 73+ 'size': "1",
 74+ 'name': "file",
 75+ 'type': "text"
 76+ })
 77+ .addClass( "mwe-upwiz-file-input" )
 78+ .click( function() {
 79+ if( _this.fogg.selectVideo() ) {
 80+ // Update the value of the input file:
 81+ $j( _this.upload.ui.div ).find(".mwe-upwiz-file-input").val( _this.fogg.sourceFilename );
 82+ // trigger the change event
 83+ _this.upload.ui.fileChanged();
 84+ }
 85+ } );
 86+ },
 87+
 88+ /**
 89+ * If chunks are disabled transcode then upload else
 90+ * upload and transcode at the same time
 91+ */
 92+ start: function() {
 93+ var _this = this;
 94+ _this.api.getEditToken( function( token ) {
 95+ mw.log( "mw.FirefoggHandler::start> upload start!" );
 96+
 97+ _this.beginTime = ( new Date() ).getTime();
 98+ _this.upload.ui.setStatus( 'mwe-upwiz-transport-started' );
 99+ _this.upload.ui.showTransportProgress();
 100+ _this.transport.doUpload( _this.fogg );
 101+
 102+ }, function( code, info ) {
 103+ _this.upload.setError( code, info );
 104+ } );
 105+ }
 106+};
Property changes on: trunk/extensions/UploadWizard/resources/mw.FirefoggHandler.js
___________________________________________________________________
Added: svn:mime-type
1107 + text/plain
Index: trunk/extensions/UploadWizard/resources/mw.UploadWizardUploadInterface.js
@@ -14,8 +14,7 @@
1515 _this.div = $j('<div class="mwe-upwiz-file"></div>').get(0);
1616 _this.isFilled = false;
1717
18 - _this.$fileInputCtrl = $j('<input size="1" class="mwe-upwiz-file-input" name="file" type="file"/>')
19 - .change( function() { _this.fileChanged(); } );
 18+ _this.$fileInputCtrl = _this.upload.getUploadHandler().getInputControl();
2019
2120 _this.$indicator = $j( '<div class="mwe-upwiz-file-indicator"></div>' );
2221
@@ -338,6 +337,10 @@
339338 * @return boolean if extension was acceptable
340339 */
341340 isGoodExtension: function( ext ) {
 341+ // ugly but we don't have a base "uploadHandler" class
 342+ if( this.upload.getUploadHandler().isGoodExtension ){
 343+ return this.upload.getUploadHandler().isGoodExtension( ext );
 344+ }
342345 return $j.inArray( ext.toLowerCase(), mw.UploadWizard.config[ 'fileExtensions' ] ) !== -1;
343346 }
344347
Index: trunk/extensions/UploadWizard/resources/mw.FirefoggTransport.js
@@ -0,0 +1,170 @@
 2+/**
 3+ * Represents a "transport" for files to upload; in this case an firefogg.
 4+ * XXX dubious whether this is really separated from "ApiUploadHandler", which does a lot of form config.
 5+ *
 6+ * The iframe is made to be the target of a form so that the existing page does not reload, even though it's a POST.
 7+ * @param form jQuery selector for HTML form
 8+ * @param progressCb callback to execute when we've started. (does not do float here because iframes can't
 9+ * monitor fractional progress).
 10+ * @param transportedCb callback to execute when we've finished the upload
 11+ */
 12+mw.FirefoggTransport = function( $form, fogg, progressCb, transportedCb ) {
 13+ this.$form = $form;
 14+ this.fogg = fogg;
 15+ this.progressCb = progressCb;
 16+ this.transportedCb = transportedCb;
 17+};
 18+
 19+mw.FirefoggTransport.prototype = {
 20+
 21+ passthrough: false,
 22+ /**
 23+ * Do an upload on a given fogg object:
 24+ */
 25+ doUpload: function( fogg ){
 26+ // check if the server supports chunks:
 27+ if( this.isChunkUpload() ){
 28+ mw.log("FirefoggTransport::doUpload> Chunks");
 29+ // encode and upload at the same time:
 30+ this.doChunkUpload();
 31+ } else {
 32+ mw.log("FirefoggTransport::doUpload> Encode then upload");
 33+ this.doEncodeThenUpload();
 34+ }
 35+ },
 36+ isChunkUpload: function(){
 37+ return false;
 38+ return ( mw.UploadWizard.config[ 'enableFirefoggChunkUpload' ] );
 39+ },
 40+ /**
 41+ * Check if the asset should be uploaded in passthrough mode ( or if it should be encoded )
 42+ */
 43+ isPassThrough: function(){
 44+ // Check if the server supports raw webm uploads:
 45+ var wembExt = ( $j.inArray( mw.UploadWizard.config[ 'fileExtensions'], 'webm') !== -1 )
 46+ // Determine passthrough mode
 47+ if ( this.isOggFormat() || ( wembExt && isWebMFormat() ) ) {
 48+ // Already Ogg, no need to encode
 49+ return true;
 50+ } else if ( this.isSourceAudio() || this.isSourceVideo() ) {
 51+ // OK to encode
 52+ return false;
 53+ } else {
 54+ // Not audio or video, can't encode
 55+ return true;
 56+ }
 57+ },
 58+
 59+ isSourceAudio: function() {
 60+ return ( this.getSourceFileInfo().contentType.indexOf("audio/") != -1 );
 61+ },
 62+
 63+ isSourceVideo: function() {
 64+ return ( this.getSourceFileInfo().contentType.indexOf("video/") != -1 );
 65+ },
 66+
 67+ isOggFormat: function() {
 68+ var contentType = this.getSourceFileInfo().contentType;
 69+ return ( contentType.indexOf("video/ogg") != -1
 70+ || contentType.indexOf("application/ogg") != -1
 71+ || contentType.indexOf("audio/ogg") );
 72+ },
 73+ isWebMFormat: function() {
 74+ return ( this.getSourceFileInfo().contentType.indexOf('webm') != -1 );
 75+ },
 76+
 77+ /**
 78+ * Get the source file info for the current file selected into this.fogg
 79+ */
 80+ getSourceFileInfo: function() {
 81+ if ( !this.fogg.sourceInfo ) {
 82+ mw.log( 'Error:: No firefogg source info is available' );
 83+ return false;
 84+ }
 85+ try {
 86+ this.sourceFileInfo = JSON.parse( this.fogg.sourceInfo );
 87+ } catch ( e ) {
 88+ mw.log( 'Error :: could not parse fogg sourceInfo' );
 89+ return false;
 90+ }
 91+ return this.sourceFileInfo;
 92+ },
 93+
 94+ /**
 95+ * Get the encode settings from configuration and the current selected video type
 96+ */
 97+ getEncodeSettings: function(){
 98+ var encodeSettings = $j.extend( {}, mw.UploadWizard.config[ 'firefoggEncodeSettings'] , {
 99+ 'passthrough' : this.isPassThrough()
 100+ })
 101+ mw.log("FirefoggTransport::getEncodeSettings> " + JSON.stringify( encodeSettings ) );
 102+ return encodeSettings;
 103+ },
 104+
 105+
 106+
 107+ /**
 108+ * Encode then upload
 109+ */
 110+ doEncodeThenUpload: function(){
 111+ this.fogg.encode( JSON.stringify( this.getEncodeSettings() ) );
 112+ this.monitorProgress();
 113+ },
 114+ /**
 115+ * Encode and upload in chunks
 116+ */
 117+ doChunkUpload: function(){
 118+ this.fogg.upload(
 119+ JSON.stringify( this.getEncodeSettings() ),
 120+ this.getUploadUrl(),
 121+ JSON.stringify( this.getUploadRequest() )
 122+ );
 123+ this.monitorProgress();
 124+ },
 125+ // Get the upload url
 126+ getUploadUrl: function(){
 127+ return mw.UploadWizard.apiUrl;
 128+ },
 129+ /**
 130+ * get the upload settings
 131+ */
 132+ getUploadRequest: function(){
 133+ return {
 134+ 'action' : ( this.isChunkUpload() )? 'firefoggupload' : 'upload',
 135+ 'stash' :1,
 136+ 'comment' : 'DUMMY TEXT',
 137+ 'format' : 'json'
 138+ }
 139+ },
 140+ /**
 141+ * Monitor progress on an upload:
 142+ */
 143+ monitorProgress: function(){
 144+ var fogg = this.fogg;
 145+ var progress = fogg.progress();
 146+
 147+ mw.log("FirefoggTransport::monitorProgress> " + progress + ' state: ' + fogg.state );
 148+ this.progressCb( progress );
 149+
 150+ if( fogg.state == 'encoding' || fogg.state == 'uploading'){
 151+ setTimeout( this.monitorProgress, 500 );
 152+ }
 153+ // return the api result:
 154+ if( fogg.state == 'done' ){
 155+ this.transportedCb( this.fogg.responseText );
 156+ }
 157+
 158+ },
 159+
 160+ /**
 161+ * Process the result of the form submission, returned to an iframe.
 162+ * This is the iframe's onload event.
 163+ *
 164+ * @param {Element} iframe iframe to extract result from
 165+ */
 166+ updateProgress: function( iframe ) {
 167+ var _this = this;
 168+ }
 169+};
 170+
 171+
Property changes on: trunk/extensions/UploadWizard/resources/mw.FirefoggTransport.js
___________________________________________________________________
Added: svn:mime-type
1172 + text/plain
Index: trunk/extensions/UploadWizard/resources/mw.UploadWizard.js
@@ -22,17 +22,17 @@
2323 this.transportWeight = 1; // default
2424 this.detailsWeight = 1; // default
2525
26 - // details
 26+ // details
2727 this.ui = new mw.UploadWizardUploadInterface( this, filesDiv );
2828
2929 // handler -- usually ApiUploadHandler
30 - // this.handler = new ( mw.UploadWizard.config[ 'uploadHandlerClass' ] )( this );
31 - // this.handler = new mw.MockUploadHandler( this );
32 - this.handler = new mw.ApiUploadHandler( this, api );
 30+ this.handler = this.getUploadHandler();
3331 };
3432
3533 mw.UploadWizardUpload.prototype = {
36 -
 34+ // Upload handler for the UploadWizardUpload
 35+ uploadHandler: null, // lazy init
 36+
3737 acceptDeed: function( deed ) {
3838 var _this = this;
3939 _this.deed.applyDeed( _this );
@@ -49,7 +49,7 @@
5050 },
5151
5252 /**
53 - * remove this upload. n.b. we trigger a removeUpload this is usually triggered from
 53+ * Remove this upload. n.b. we trigger a removeUpload this is usually triggered from
5454 */
5555 remove: function() {
5656 this.state = 'aborted';
@@ -199,8 +199,28 @@
200200 */
201201 }
202202 },
203 -
204203 /**
 204+ * Set the upload handler per browser capabilities
 205+ */
 206+ getUploadHandler: function( api ){
 207+ if( this.uploadHandler ){
 208+ return this.uploadHandler ;
 209+ }
 210+ if( typeof( Firefogg ) != 'undefined'
 211+ &&
 212+ mw.UploadWizard.config[ 'enableFirefogg' ]
 213+ ) {
 214+ mw.log("mw.UploadWizard::getUploadHandler> FirefoggHandler");
 215+ this.uploadHandler = new mw.FirefoggHandler( this );
 216+ return this.uploadHandler
 217+ }
 218+ // By default use the apiUploadHandler
 219+ mw.log("mw.UploadWizard::getUploadHandler> ApiUploadHandler");
 220+ this.uploadHandler = new mw.ApiUploadHandler( this );
 221+ return this.uploadHandler;
 222+ },
 223+
 224+ /**
205225 * Fetch a thumbnail for a stashed upload of the desired width.
206226 * It is assumed you don't call this until it's been transported.
207227 *
@@ -262,7 +282,7 @@
263283
264284 var _this = this;
265285 if ( typeof width === 'undefined' || width === null || width <= 0 ) {
266 - width = mw.UploadWizard.config[ 'thumbnailWidth' ];
 286+ width = mw.UploadWizard.config[ 'thumbnailWidth' ];
267287 }
268288 width = parseInt( width, 10 );
269289 height = null;
@@ -319,38 +339,6 @@
320340 stepNames: [ 'tutorial', 'file', 'deeds', 'details', 'thanks' ],
321341 currentStepName: undefined,
322342
323 - /*
324 - // list possible upload handlers in order of preference
325 - // these should all be in the mw.* namespace
326 - // hardcoded for now. maybe some registry system might work later, like, all
327 - // things which subclass off of UploadHandler
328 - uploadHandlers: [
329 - 'FirefoggUploadHandler',
330 - 'XhrUploadHandler',
331 - 'ApiIframeUploadHandler',
332 - 'SimpleUploadHandler',
333 - 'NullUploadHandler'
334 - ],
335 -
336 - * We can use various UploadHandlers based on the browser's capabilities. Let's pick one.
337 - * For example, the ApiUploadHandler should work just about everywhere, but XhrUploadHandler
338 - * allows for more fine-grained upload progress
339 - * @return valid JS upload handler class constructor function
340 - getUploadHandlerClass: function() {
341 - // return mw.MockUploadHandler;
342 - return mw.ApiUploadHandler;
343 - var _this = this;
344 - for ( var i = 0; i < uploadHandlers.length; i++ ) {
345 - var klass = mw[uploadHandlers[i]];
346 - if ( klass != undefined && klass.canRun( this.config )) {
347 - return klass;
348 - }
349 - }
350 - // this should never happen; NullUploadHandler should always work
351 - return null;
352 - },
353 - */
354 -
355343 /**
356344 * Reset the entire interface so we can upload more stuff
357345 * Depending on whether we split uploading / detailing, it may actually always be as simple as loading a URL
Index: trunk/extensions/UploadWizard/resources/mw.ApiUploadHandler.js
@@ -10,25 +10,10 @@
1111 * Represents an object which configures a form to upload its files via an iframe talking to the MediaWiki API.
1212 * @param an UploadInterface object, which contains a .form property which points to a real HTML form in the DOM
1313 */
14 -mw.ApiUploadHandler = function( upload, api ) {
 14+mw.ApiUploadHandler = function( upload ) {
1515 this.upload = upload;
16 - this.api = api;
17 - this.$form = $j( this.upload.ui.form );
18 - this.configureForm();
19 -
20 - // the Iframe transport is hardcoded for now because it works everywhere
21 - // can also use Xhr Binary depending on browser
22 - var _this = this;
23 - this.transport = new mw.IframeTransport(
24 - this.$form,
25 - function( fraction ) {
26 - _this.upload.setTransportProgress( fraction );
27 - },
28 - function( result ) {
29 - _this.upload.setTransported( result );
30 - }
31 - );
32 -
 16+ // setup up local pointer to api:
 17+ this.api = upload.api;
3318 };
3419
3520 mw.ApiUploadHandler.prototype = {
@@ -59,7 +44,40 @@
6045 }
6146 */
6247 },
63 -
 48+ getTransport: function(){
 49+ if( this.transport ){
 50+ return this.transport;
 51+ }
 52+ this.transport = new mw.IframeTransport(
 53+ this.getForm(),
 54+ function( fraction ) {
 55+ _this.upload.setTransportProgress( fraction );
 56+ },
 57+ function( result ) {
 58+ _this.upload.setTransported( result );
 59+ }
 60+ );
 61+ return this.transport ;
 62+ },
 63+ getForm: function(){
 64+ if( this.upload && this.upload.ui && this.upload.ui.form ){
 65+ this.configureForm();
 66+ return $j( this.upload.ui.form );
 67+ }
 68+ mw.log("Error:: could not get form")
 69+ return false;
 70+ },
 71+ /**
 72+ * Get a pointer to the "file" input control
 73+ */
 74+ getInputControl: function(){
 75+ var _this = this;
 76+ return $j('<input size="1" class="mwe-upwiz-file-input" name="file" type="file"/>')
 77+ .change( function() {
 78+ _this.upload.ui.fileChanged();
 79+ } );
 80+ },
 81+
6482 /**
6583 * Modify our form to have a fresh edit token.
6684 * If successful, return true to a callback.
@@ -82,8 +100,8 @@
83101 * @param value the value of the input
84102 */
85103 addFormInputIfMissing: function( name, value ) {
86 - if ( this.$form.find( "[name='" + name + "']" ).length === 0 ) {
87 - this.$form.append( $j( '<input />' ) .attr( { 'type': "hidden", 'name': name, 'value': value } ));
 104+ if ( this.getForm().find( "[name='" + name + "']" ).length === 0 ) {
 105+ this.getForm().append( $j( '<input />' ) .attr( { 'type': "hidden", 'name': name, 'value': value } ));
88106 }
89107 },
90108
@@ -97,7 +115,7 @@
98116 _this.beginTime = ( new Date() ).getTime();
99117 _this.upload.ui.setStatus( 'mwe-upwiz-transport-started' );
100118 _this.upload.ui.showTransportProgress();
101 - _this.$form.submit();
 119+ _this.getForm().submit();
102120 };
103121 var err = function( code, info ) {
104122 _this.upload.setError( code, info );

Follow-up revisions

RevisionCommit summaryAuthorDate
r84067reverting change r84000 - moving firefogg integration to uploadwizard-firefog...neilk23:34, 15 March 2011
r84068manually deleting these files which were added in r84000, because svn gives f...neilk23:35, 15 March 2011

Status & tagging log