Reading/Multimedia/TimedMediaHandler review notes 2011

mw.EmbedPlayer.js
reading from line 459 of mw.EmbedPlayer.js

triggers updateFeatureSupportEvent, with property this.supports. Seems to be unused in this version of the code
 * setupSourcePlayer -- pick a defaultPlayer from the mediaPlayers for the mimeType
 * inheritEmbedPlayer <- why inheritance, why not composition or dispatch? And furthermore why does it blank methods, does that mean this effectively changes type, multiple times during a session? Seems like it would be very hard to debug later...
 * This is rarely used  as more browsers support html5. ( You rarely switch player types ) Inheritance made it easy to override core methods with per embedPlayer type modes of operation. There is enough shared functionality and the player interface implementations are relatively small that it may be worth while to break off "browser playback" implementations from the core "player" and do something similar to controlBuilder.
 * updateFeatureSupport
 * Used in KalturaSupport here .. to update player features per kaltura uiConf configuration.


 * getDuration // lines 568, pointless?! It doesn't assign to anything, do we expect getDuration to have side effects? if there's a reason, please comment
 * Its a getter for the duration, in later version of code it looks for the selectedSource duration (if not deifned in the parent EmbedObject ) copied in r103525


 * naming and/or code structure -- inheritEmbedPlayer does more than inherit it also loads the player, with callback to show the player.
 * Renamed to "updatePlaybackInterface" in r103528 to better capture what the method is doing. Updating the interface in which in browser playback api calls are made.


 * need for CPS? Why not break into multiple functions?
 * I assume you mean Continuation-Passing Style, This is not as bad as some other examples. I think we should focus on the egregious ones that actually make things hard to follow .. with small CPS's I don't think it hurts readability as it makes it easier to track the closure contexts of parent variables without having to explicitly pass them sets of properties across local functions.


 * getTimeRange: coding standards, please use braces
 * r103529


 * wtf with the "do" methods. doEmbedHTML, doSeek, why not embedHTML, seek.
 * renamed doEmbedHTML to embedPlayerHTML and doSeek to seek in r103531


 * naming is PlayerControlBuilder a control or a builder? How can it have a height.
 * PlayerControlBuilder builds controls .. the controls it builds have a height, should be accessed via getHeight
 * line 807, line 850 setTimeout(... 1) ? not 0? line 878
 * fixed to 0 r103532


 * spelling: doWarningBindinng (everywhere)
 * renamed to addWarningBinding r103533


 * doneLoading or trigger( 'playerReady' ) - pick one
 * lots of stuff binds to playerReady so name the property the same ) r103536 Should be noted that propagating w3c player states is on the todo list


 * updateVideoTimeReq -- camel case params. also document format...
 * updateVideoTime -- camel case params
 * fixed camel case, added format documentation in comment r103539


 * line 981 - reset seek_offset (comment is wrong? should be serverSeekTime ?? )
 * Fixed comment and switched check to supportsURLTimeEncoding call in r103539

2011-10-16 Sunday noticed this while debugging other things:
When enabled, TMH seems to cause problems with the documentation produced by an invocation of api.php without parameters. Fatal error: Access level to ApiQueryVideoInfo::getExamples must be public (as in class ApiQueryImageInfo) in /Users/neilk/Sites/trunk/extensions/TimedMediaHandler/ApiQueryVideoInfo.php on line 238
 * fixed in r103540

--

2011-10-17

 * line 1046-1049 braces please, camelcase mixing,
 * fixed in r103544
 * 1084-1086 -- setting css of removed img?!
 * the image fades in then replaces the other image made that more clear by using a single chained set of calls: r103545
 * 1090 thumbUrl - not guaranteed to show all thumbs, just looks at last_thumb_url, is this s et by another process?
 * that is correct .. we just hot swap at the end to lastThumbUrl this was for a metavid.org interface where temporal clips updated the thumbnail.. if you quickly moved to a new image we did not want to queue up lots of animations for each thumbs, for a responsive interface we just jump to the latest ( even if its not pretty for that image swamp )


 * 1104-06 -- updatePosterSrc, same name as complex method at 1044?
 * in kaltura trunk version we just have the simple version ( deprecated metavid interface described above ) .. I have swapped that in r103549


 * 1223: videoAttribues
 * 1281: if applyMediaElementBindings is "abstract" as well, it should somehow indicate an error or at least log one
 * Just a warning because not required that player interfaces implement it: 103550


 * 1455: what is _propagateEvents, really? Why would you have a play button that does nothing? debugging?
 * _propagateEvents is used to disable events. Say you start an ad playback and now you don't want the player to send the 'onended' to the player interface rather you want the embedPlayer to look like one continues stream for purposes of interfacing with the player from JavaScript. Other times its used is for managing triggers during times you don't want triggers to populate. Say for example you switch a source, and as part of that source switch the native html5 implementation dispatches a "pause" event, but you don't want that pause event to update the player interface and controls ( like it normally does ) .. so we have this way to turn off event propagation.


 * what is "autoTrigger"ing events? searching web reveals nothing..
 * its a bad name should be do "eventsAutoBubble" ... but the issue was when you call a method like embedPlayer.play .. it would trigger "play" this has been fixed in later versions of jQuery, and I have switched tirgers to not include local method names ( in kaltura trunk ) Copied over in r103551


 * what do you mean by "underling"s ?
 * very private method or variable :P .. I should be more consistent.


 * 1550: another "abstract" method -- should throw error? but at least it does log.
 * We don't want to throw real errors for things like this.. it could just be the player interface does not have an api for volume control.


 * 1577: we understand that stop is like pause, but.... parent_pause?
 * this is a way to check if the player interface implements pause and only call the embedPlayer method ( not an actual pause request on the player interface )... This is not really needed now days. Worked around a bug where some players would not seek if you called pause on them, and when were were "stopping" we want to enter a pause state but not interfere with the player seek to the start. ( but not needed now ) r103554


 * 1677...1711 more "abstract methods" that don't throw errors, instead are accessors to simple object properties like isPaused --> this.paused. So what should we assume -- that these methods *should* throw errors, or, that this refers to an older design and now all subclasses (underlings??) use the same notion of this.paused
 * These methods should not throw errors. They sometimes are not really needed. isPaused does not read actual player interface properties just the attribute. I agree in this case we can just access the "paused" property. r103555


 * would be nice if we documented notions like "currentTime"... we assume it means the time of the video playing, but is it really?
 * yes its documented in the attributes section: // Current playback position ( line 62 )


 * 1773 -- isDuration == 0 divide by zero?
 * we check for "this.duration" above ( can't be zero )

Related to code questions above: Possible interface bug -- seems strange to allow movie to continue playing while user has mousedown on playhead. YouTube pauses instead. Is annoying in use cases like "I am near the end, now want to scrub back to beginning" or "I want to see that thing again that I just saw" If the above interface idea makes more sense, why not turn off monitor loop on mousedown over the playhead, and then, on mouseup, seek to new position and restart monitor loop.
 * so, is there a monitor loop constantly going, and in checkForCurrentTimeSeek, we try to determine if user action has finished and we can seek to new position.
 * You would not have to do this in the monitor loop. You have mouse down on the seek bar where you could then pause. The monitor is needed for cases where you set the time on the virtual embedPlayer and we want to reflect that. ... ie embedPlayer.currentTime = newTime .. we then have to seek just like the real video tag does.


 * monitor function -- break this up?
 * yes r103556


 * updateBufferStatus line 1926 -- why would this ever be greater than 1 ( > 100%)? If this is due to floating point fails, why not track bytes received / expected instead and divide against expected file length... (of course, it's possible the server lied about file length)
 * I don't remember why I got > 1 probably some html5 implementations giving weird buffer data... We have to check for buffered data a few different ways per different implementations ( see mw.EmbedPlayerNative updating this property two wasy. You don't have byte received in most browsers for the video tag. Especially on cross domain video tag media sources.


 * bufferedPercent -- only dealt with in subclasses? should be two integers in the superclass? (bufferedBytes/expectedBytes)? Or maybe some players only give you % and not such values?
 * Yes some just give percentage of time such as this.bufferedPercent = ( vid.buffered.end(0) / vid.duration ); .. where other players ( flash ) gives the this.bytesLoaded / this.bytesTotal;

question, does this chain different kinds of media together? That would explain a lot. like, why do we keep getting autoSelectSource over and over again. Don't we just want it once?
 * line 1986 - what if no currentTime and/or no serverSeekTime ? what if serverSeekTime is 0 or currentTime is 0, does this do the right thing? What if I'm asking explicitly to seek to 0?
 * Not following... we always have currentTime= 0 ... if both are zero then we pass zero off to the retrieval of the temporal url.. should be fine. autoSelectSource needs to be recalled if we update sources. Some methods need to ensure we have setup sources so we call it ( in case it was not already called before )


 * in supportsURLTimeEncoding, isn't this done better with a default "no", and mediaSource subclasses provide their own assessment based on config and their capabilities.
 * Not really.. its best global configured for the given environment. Temporal urls are really only used for internet archive at this point. and we will probably soon factor them out of the code base all together.

___ Stopped at end of mw.EmbedPlayer.js, yay ____
Oct 28, 2011 mwEmbedPlayerGeneric.js
 * - no comments

mwEmbedPlayerJava.js
 * - parseInt should have radix (2nd argument of 10)
 * mmm.. there are like 400 occurrences of parseInt ( only in TMH not core ) ... with very sparse use of ,10 .. I guess its true if you start off values with "0x" ...things could be messed up here and elsewhere.. If you want I will run the regex .. but seems verbose.
 * - clean up commented out code
 * 103559

- line 103 consider  !( a && b ) - line 192 - getPlayerElement -- remove commented out stuff. Also, the way this is used in the rest of the code it is not a getter because the returned element is ignored. It is like a "cachePlayerElement". Rename, or fix rest of code to obtain element from method?
 * done.
 * http://www.mediawiki.org/wiki/Special:Code/MediaWiki/103560

- line 192 - why doesn't it check for existence of getPlayerElement and return that? Does the player element change, so that we have to do jquery lookup each time?
 * it sometimes does fail .. if for example you stopped playback ( removed the java player from the page and then re-add it in) .. its not easy to know that happens since playerElement may still be ~sort~ of active but just lose its bindings. But maybe I should test that more.. It could be fine. Jquery lookups of the #id nature are very fast

- line 234 - does this need to be wrapped in a try/catch, like the play right above?
 * sure.

mwEmbedPlayerKPlayer.js

 * - seems that WIkimedia will not use this, since it is SWF based, so, although there are a few WTFs here and there we are not reviewing. Linted it. Seems like it will not actually blow up the world. :)
 * If adobe every makes good on their promise to ship webm in flash .. this may be useful, or once mp3 pattens expire in 2012 also potentially useful. .. but yes .. no need to review in the mean time. The latest may be less wtf'ish, updated: updated

mw.EmbedPlayerNative.js
- line 104-108 postEmbedJS twice, can be made simpler with if/else logic?
 * - 102-106 repeated $( '#' + this.pid )
 * fixed to use _this.getPlayerElement;
 * only called once now
 * - 126 playerAttribtues -- no abbreviations, please expand tues to Tuesday.
 * the comment?
 * - 131 braces for ifs please
 * right
 * - 151 useless parens
 * done
 * - 183 - arbitrary wait... 100ms? can we have a comment here as to why?
 * Was to give time for the player attributes to propagate..( a direct call on the player elements properties right after it was inseretd would fail sometimes.. but now days we have nice html5 implementations. Removed delay.
 * - 296 - 50ms seems like it's overdoing it, why not 100ms or 200ms. Also why 40 seconds for delay here, 10 seconds elsewhere? arbitrary.
 * yes its arbitrary...changed to 100ms... probably could get away with loadedmetadata binding and readyState property > 1 now days ( pretty well supported )... Loading metadata can take a long time with some formats ( 40 seconds )
 * - 317 braces for if
 * ok
 * - 314 getCurrentTime -- after puzzling it out we think we understand it but this needs better comments. Lots of interwoven lines of execution.
 * You mean setCurrentTime ... re factored to clean up with comments: 103563

- -why is seeked interwoven with setting time, etc. We believe it works like this -- a "seek" is invoked, with a callback to do later. --- this calls setCurrentTime, passing that callback. --- setCurrentTime spins every 50ms until the element readyState > 1 for a maximum amount of time --- then, if currentTime is time, do callback. or, wait for the 'seeked' event to trigger (which will occur because one of our callers already set something in motion), and then do the callback switchPlaySrc (line 387) -- too many embedded timeouts & closures, please rewrite, we can't understand this easily.


 * Hopefully the re-factor and comments make it clear.

line 608 -- this.seeking = false twice -- we understand why but please set a comment
 * line 540 @parma delicious JS documentation?
 * added docs
 * 563 braces for ifs
 * done
 * no need for the false outside of the is this.seeking == false if. ( copied in the updated _onEvents from kaltura ) .. a bit more clear includes the _propagateEvents support etc. 103564

otherwise rest of file ok end 5:40 Oct 28 ---

Reviewer's log, November twenty-first, two thousand eleven.

mw.EmbedPlayerVlc.js

 * 61: commented code should probably be removed.
 * removed
 * 136, 242, 245: as the note on 239 says, should be localized
 * localized.
 * 105,117: commented code
 * removed commented code.
 * 91, 96, 139, etc (in general): Testing for browsers isn't as good as testing for capabilities. I realize that's not always possible, though.  If there's no other way, please at least mention the browser versions you're implying in the comments.
 * in EmbedPlayer VLC ?
 * 139: can we deploy code that makes this assumption?
 * Makes what assumption? Assume version > 0.8.5.1 ?
 * 187, 198, 206: more commented quicktime/flow code
 * Made it more clear that the section is for

Also for mw.EmbedPlayerVlc.js

 * included brackets
 * renamed postEmbedJS to postEmbedActions ( more clear no ambiguous "js" reference.
 * updated $j ref to $ ref.
 * prefixed all log messages with normal class name prefix

mw.TimedText.js

 * line 30: question, do we expect to reinitialize TimedText objects? I assume so since you took initialization out of the constructor.
 * Yes we want to re-initialize timed text on player build out.
 * line 45: spelling: userLanugage
 * fixed to userLanguage
 * line 157: "var textOffset = ..." magic numbers 30, 10? move to config or document
 * Set to control bar height and added default bottom padding.
 * line 175: shouldn't animate be a config parameter of timedText obj, rather than a param?
 * Animate tells us if the player resize action is an animation or an instant player resize ( added code comment to clarify )

Also, why animation choice here & not elsewhere? e.g. a few lines later, bindings for onShowControlBar and onHideControlBar. I'm assuming it's because zooming the whole widget is slower than a few interface elements?
 * The onShowControlBar and onHideControlBar do not have an animation param in the event. Its universally set to "fast" If we add support for the control bar hiding and showing with a configurable duration then we would need to support passing that param around in the events, but right now its always "fast"
 * line 290-295 getInterfaceSizePercent braces.  more magic numbers. move to config or document.
 * These arbitrary values are not really arbitrary. They correlate to about 30 columns of subtitle space. This is what standard TV subtitles layout systems use so we ~more or less~ try to match that relative size in player layout. Added comment to explain this.
 * line 544, spelling: loadCurrentSubSrouce
 * fixed to loadCurrentSubSource and added function documentation
 * line 602, 604: braces. Consider === rather than == ?
 * added brackets and ===
 * line 619: getSourceByLanguage, braces
 * added brackets and @param documentation
 * line 650: getMainMenu  != 0  --> !== 0
 * switched to !==
 * line 750 in mw.getUserName, useless blank lines, paren on 2nd line
 * Per the TODO on line 688 Removed all the add transcript support. Should be part of a gadget ( i.e once this ships could restore the miro universal subs gadget to a working state )
 * line 860: getLayoutMenu braces
 * added.
 * line 1004-1027: confuses me, it seems to be copying the catSources into the language menu in various ways. Is a source identical with a language? If so why isn't it called a language? Or is langMenu misnamed?
 * catSourceCount renamed to sourcesWithCategoryCount, hopefully make it more clear. We are checking if "track" tags had the "kind" attribute this is a form of "category" can place source text files into categories like "subtitles", "audio description", "chapter names". We check for these categories when building out the language menu. ( added documentation )
 * line 1140 belowBarHeight = 60; magic number, move to config?
 * moved to TimedText.BelowVideoBlackBoxHeight config

mw.TextSource.js
( Moved TextSource to its own file )
 * line 1201 why init, not constructor
 * That is the style I use all through the code base it could just as well go into the constructor.. but its instead in an initialization method. I think this keeps things slightly cleaner in that if you ever inherent or clone the object you can override the constructor prorotype directly copy it into a super class, call its parent etc. Its not as strait forward what is going on if you put it all into the constructor object itself and makes it difficult to 'externalize' your constructor override logic.
 * line 1240 loaded = true seems premature here, we could still return without loading?
 * move loaded = true to after actual loading. The premature set was to avoid stacking requests .. but then need to implement a queue system, and the core captions support is better about not calling it multiple times now.
 * line 1319 braces!
 * added!
 * line 1343 parseMwSrt  re this comment, I doubt you could optimize better than jQuery anyway
 * Sorry should have been more specific I think what I meant there was optimize for robustness .. the mediWiki api gives us HTML .. and we don't necessarily want the html structure we want srt structure for parsing timed text out ... Right now wiki -> html is not always friendly to our srt parsing. The long term plan is to move the srt parsing to server side and have the api server up the srt's times in JSON form ( doing the wikitext parsing on each srt line instead of on the whole file ) Also see bug 29126 updated comment.
 * line 1347 jawbreaker regex needs comments. I assume this is some HH:MM:SS --> HH:MM:SS format, but that's just a guess
 * Added some comments.
 * line 1381 seems like it could be a component of the previous regex?. And there it is again line 1347, or is this subtly different?
 * this matches the simpler case where no number prefix is given. Again we should parser all this on the server. Always complicated to translate html output from srt wiki text into usable srts.
 * line 1350-1400 should make a function for the hr*60*60 + min*60 + sec
 * good idea. refactored that ... no repeating logic or code now.

mw.TimedTextMediaWikiSources.js

 * line 1523 mw.MediaWikTrackProvider - spelling, missing the 2nd i in Wiki?
 * fixed.
 * line 1540 mw.MediaWikTrackProvider.prototype.init braces
 * added.
 * line 1584 mw.MediaWikTrackProvider.prototype.loadSources braces (2x)
 * added.
 * line 1670 getTimedTextNS braces, or else if ? Also it seems to be the default case to return this.timedTextNS anyway, so instead should do logic like function { if (! this.timedTextNS ) { ... make this.timedTextNS... }  return this.timedTextNS; }
 * fixed also updated default value to 710 per namespace register
 * line 1712 $.fn.timedText  braces
 * factored out.

mw.TimedTextEdit.js

 * line 251 magic constant 1048576 -- move to config
 * mw.TimedTextEdit.js has been removed for now ( as mentioned above should be replaced with mirosubs gadget and nomral wiki-text editing )

TimedText.loader.js

 * line 30 - 32 -- how can you expect to test for .data properties generated by the trigger, without any kind of waiting time or callback? This seems wrong.
 * triggers are triggered synchronously. Only the custom "triggerQueuedCallback" is asyncrouns. I don't think that looks very pretty either. I think using a data property is better than a direct attribute but still thinking what is the best most clean representation. A lot of times I chain callbacks but in cases of a simple Boolean seems excessive.
 * line 37 - could be just one line -- return $( embedPlayer ).find( 'track' ).length != 0;
 * done

ext.tmh.transcodetable.js
Why does this have a different naming convention?
 * Transcode table is a normal extension javascript file related to the Image page. Its not a mwEmbedModule it does not stand alone, it directly supports an extension to the mediaWiki page by the timed media handler extension.

Reviewer's log, November twenty-third, two thousand eleven.

mw.MediaPlayers.js

 * 28: This stuff should perhaps be in a configuration file. I can especially see people wanting to change the player order for different types
 * Native is always best ;) ... If someone actually wants to change this and has a use case for it that goes beyond the user choosing a different player, I am open to moving this to configuration. But would be cautions as it tightly correlates with the library names and these strings are used to build the requested library files... so we would have to add in validation of a predefined set of library names for this config to avoid possible weirdness. I vote to keep this "hard coded" for now.

mw.MediaSource.js

 * 311-322: FIXME i18n... needs to be fixed.
 * fixed
 * 386: This could also use the Apache mime.types file, if available. Mediawiki has a facility for this: http://www.mediawiki.org/wiki/Manual:Mime_type_detection  It's a big change (I think you'd need to make a new api method to access this stuff), and I don't think it needs changing now, but FYI...
 * In mediaWiki we output the source "type" in the video tag output to begin with .. This is really just detecting types of files for 3rd party video tag markup, where we don't control the video tag embed code output

MwEmbedModules/EmbedPlayer/resources/skins/mw.PlayerControlBuilder.js
line 71: init: probably should not declare _this, since you declare it again later...

line 77: seems to me you want to extend 'this' normally with a copy of the player skin, rather than create a new object from scratch? e.g.

var playerSkin = ... var copyOfPlayerSkin = $.extend(true, {}, playerSkin); this.extend( copyOfPlayerSkin );

(of course the lines above could be expressed more succinctly)

line 343 : toggleFullscreen( forceClose ) -- parameter is unused, undocumented?

line 713: magic constant 300, please make part of config or document.

line 720: magic constant 200, '" "" ""

line 772-776 (play/pause) same as 786-790

line 1439 - is overlayContent properly escaped?

line 1804 -- getComponent the .o method is a little too terse. Seems this is the h,w,o thing Ian mentions below. Saw this elsewhere and it was a bit of an irritation to me too. 'h' and 'w' are not so bad but 'o' is not obvious.

line 2100 or so -- I'm guessing that Perc == Percent? Pct or Percent would be better. Ian believes you shouldn't abbreviate Percent at all.

mw.PlayerSkinKskin.js
Reviewer's log, November twenty-eighth, two thousand eleven.

29-51ish: do the properties have to be named 'h', 'w', and 'o'? words would be more consistent and easier to understand.

54, 111: hanldeReciveMsg is misspelled.

.