diff --git a/docs/tutorials/architecture.md b/docs/tutorials/architecture.md new file mode 100644 index 000000000..27be1a40e --- /dev/null +++ b/docs/tutorials/architecture.md @@ -0,0 +1,12 @@ +# Architecture Diagrams + +Shaka data flow diagram + +Shaka ownership diagram + diff --git a/docs/tutorials/basic-usage.md b/docs/tutorials/basic-usage.md index 0ac00ed29..42129bf9d 100644 --- a/docs/tutorials/basic-usage.md +++ b/docs/tutorials/basic-usage.md @@ -5,17 +5,12 @@ Basic usage of Shaka Player is very easy: 1. Start with {@tutorial welcome} and compile the library. 2. Create a simple HTML page with a video element. 3. In your application's JavaScript: - 1. Install polyfills. + 1. Install Shaka's polyfills. 2. Check for browser support. 3. Create a Player object to wrap the video element. 4. Listen for errors. 5. Load a manifest. -*NOTE: For simplicity, we will use `alert()` for errors in this tutorial. -In a real application, you would want a more appropriate mechanism to display -errors to your users.* - - ```html @@ -44,13 +39,15 @@ function initApp() { shaka.polyfill.installAll(); // Check to see if the browser supports the basic APIs Shaka needs. + // This is an asynchronous check. shaka.Player.support().then(function(support) { + // This executes when the asynchronous check is complete. if (support.supported) { // Everything looks good! initPlayer(); } else { // This browser does not have the minimum set of APIs we need. - alert('Browser not supported!'); + console.error('Browser not supported!'); } }); } @@ -67,9 +64,11 @@ function initPlayer() { player.addEventListener('error', onErrorEvent); // Try to load a manifest. + // This is an asynchronous process. player.load(manifestUri).then(function() { - // The video has now been loaded! - }).catch(onError); + // This runs if the asynchronous load is successful. + console.log('The video has now been loaded!'); + }).catch(onError); // onError is executed if the asynchronous load fails. } function onErrorEvent(event) { @@ -79,8 +78,7 @@ function onErrorEvent(event) { function onError(error) { // Log the error. - console.error(error); - alert('Error code ' + error.code); + console.error('Error code', error.code, 'object', error); } document.addEventListener('DOMContentLoaded', initApp); diff --git a/docs/tutorials/debugging.md b/docs/tutorials/debugging.md index 95da5c26a..a8729fc76 100644 --- a/docs/tutorials/debugging.md +++ b/docs/tutorials/debugging.md @@ -12,7 +12,7 @@ First, let's make `manifestUri` blank. var manifestUri = ''; ``` -This causes an alert that says "Error code 4000". What now? +This causes an error in the console that says "Error code 4000". What now? #### Use the JS console @@ -49,13 +49,17 @@ need to load the uncompiled library. Instead of the single-file compiled library, we need to load three scripts in our HTML file: -1. Closure's base library -2. A dependency file which maps Shaka's class names to source files -3. The uncompiled library's bootstrap file, "shaka-player.uncompiled.js" +1. Closure's base library. (This is a small JavaScript library related to the + Closure compiler used when we build Shaka.) This is what loads Shaka without + requiring you to list all 50+ source files. +2. A dependency file which maps Shaka's class names to source files. This is + how Closure's base library can locate all of Shaka's individual source files. +3. The uncompiled Shaka library's bootstrap file, "shaka-player.uncompiled.js". + This uses Closure to load the top-level parts of the library. Each of those + files in turn load their internal dependencies. -The uncompiled library's bootstrap file will use Closure to "require" each of -the exported classes in the library. This causes the entire library to be -loaded, one uncompiled source file at a time. +Once we're using the uncompiled library, we will be able to see detailed logs +and line numbers for errors. It is difficult to debug without this. ```html @@ -77,7 +81,7 @@ Reload the page and look in the JavaScript console. Now we see: Unable to guess manifest type by file extension or by MIME type. undefined text/html player.js:297 -s…a.u…l.Error {category: 4, code: 4000, data: Array[1], +Error {category: 4, code: 4000, data: Array[1], message: "Shaka Error MANIFEST.UNABLE_TO_GUESS_MANIFEST_TYPE ()", stack: "Error: Shaka Error… at http://localhost/shaka/lib/player.js:300:35"} ``` @@ -85,7 +89,10 @@ s…a.u…l.Error {category: 4, code: 4000, data: Array[1], So much more information! The uncompiled library includes a log from Player (player.js, line 297) right before the error was dispatched, and the error includes a message that gives the full human-readable name of the error: -`MANIFEST.UNABLE_TO_GUESS_MANIFEST_TYPE`. +`MANIFEST.UNABLE_TO_GUESS_MANIFEST_TYPE`. The `MANIFEST` part is the textual +name for category: 4, and `UNABLE_TO_GUESS_MANIFEST_TYPE` is the textual name +for code: 4000. (A full list can be found in the docs for +{@link shaka.util.Error}). There's also a `stack` field showing the context in which it was generated: @@ -125,7 +132,7 @@ To keep the API simple, Shaka tries to guess what type of manifest you want to load. It does this first based on extension, and if that fails, it makes a HEAD request and checks the MIME type. -A request for "" is interpretted as a relative URL. What we actually requested +A request for "" is interpreted as a relative URL. What we actually requested was the index page for the folder the HTML is in. Since the file extension of "" was `undefined`, and the MIME type was diff --git a/docs/tutorials/drm-config.md b/docs/tutorials/drm-config.md index 27fdc696e..de9d545d3 100644 --- a/docs/tutorials/drm-config.md +++ b/docs/tutorials/drm-config.md @@ -41,9 +41,9 @@ particular key system at all, but instead state that any CENC system will do: ``` If this is the only `` element in the manifest, Shaka will -try {@link shaka.dash.ContentProtection.defaultKeySystems\_ all key systems -it knows}. If the browser supports it and you configured a license server URL -for it, we'll use it. +try {@linksource shaka.dash.ContentProtection.defaultKeySystems\_ all key +systems it knows}. If the browser supports it and you configured a license +server URL for it, we'll use it. #### Clear Key diff --git a/docs/tutorials/index.json b/docs/tutorials/index.json index 0e91951ea..e18beb4ff 100644 --- a/docs/tutorials/index.json +++ b/docs/tutorials/index.json @@ -12,5 +12,6 @@ { "offline": { "title": "Offline Storage and Playback" } } ] } }, { "plugins": { "title": "Plugins and Customizing the Build" } }, + { "architecture": { "title": "Architecture Diagrams" } }, { "upgrade": { "title": "Shaka v2 Upgrade Guide" } } ] diff --git a/docs/tutorials/license-server-auth.md b/docs/tutorials/license-server-auth.md index 2e3c3ec59..d73a36478 100644 --- a/docs/tutorials/license-server-auth.md +++ b/docs/tutorials/license-server-auth.md @@ -2,7 +2,7 @@ Your application's license server may require some form of authentication so that it only delivers licenses to paying users. In this tutorial, we're going -to use different license server endpoints that require different forms of +to use various license server endpoints that require various forms of authentication. *Please note that the license server we are using in this tutorial is a diff --git a/docs/tutorials/network-and-buffering-config.md b/docs/tutorials/network-and-buffering-config.md index 70ee88907..3a385a0bb 100644 --- a/docs/tutorials/network-and-buffering-config.md +++ b/docs/tutorials/network-and-buffering-config.md @@ -9,9 +9,8 @@ segment request. The three separate retry settings are found under `drm.retryParameters` (for license requests), `manifest.retryParameters` (for manifest requests), and -`streaming.retryParameters` (for segment requests). - -They all look the same, though: +`streaming.retryParameters` (for segment requests). All three structures are +identical: ```js retryParameters: { diff --git a/docs/tutorials/plugins.md b/docs/tutorials/plugins.md index 381a03beb..e934ee1e3 100644 --- a/docs/tutorials/plugins.md +++ b/docs/tutorials/plugins.md @@ -1,18 +1,24 @@ # Plugins and Customizing the Build Shaka has a plugin system to make it easier to extend and customize the -library. Plugins can be written outside the library (in your application), or +library. The plugin interfaces are here to allow you extend or customize Shaka +Player in one of these areas: manifest parsing, subtitle and caption parsing, +networking, ABR, and polyfills. Each of these parts of the system has its own +plugin interface. Even our "built-in" parsers, such as DASH and WebVTT, are +actually just plugins we build by default. + +Plugins can be written outside the library (in your application), or they can be built into the library to take advantage of the [Closure compiler]. [Closure compiler]: https://github.com/google/closure-compiler -Manifest parsing, subtitle and caption parsing, networking, ABR, and polyfills -are all done through plugins. Even our "built-in" parsers, such as DASH and -WebVTT, are actually just default plugins. - #### Plugins +We will only cover plugin concepts at a high level here and will not go into +detailed examples of plugin development. If you are interested in customizing +or extending Shaka in one of these areas, please see the links below. + A plugin registers itself with a "core" component. These are the various plugin interfaces and the default plugins that Shaka provides: @@ -21,36 +27,38 @@ __Manifest parsers__ - Register with {@link shaka.media.ManifestParser.registerParserByExtension} and {@link shaka.media.ManifestParser.registerParserByMime} - Default manifest parser plugins: - - DASH: {@link shaka.dash.DashParser} + - DASH: {@linksource shaka.dash.DashParser} __Subtitle/caption parsers__ - Selected by MIME type - Register with {@link shaka.media.TextEngine.registerParser} - Default text parser plugins: - - WebVTT: {@link shaka.media.VttTextParser} + - WebVTT: {@linksource shaka.media.VttTextParser} __Networking plugins__ - Selected by URI scheme (http, https, etc.) - Register with {@link shaka.net.NetworkingEngine.registerScheme} - Default networking plugins: - - HTTP(S): {@link shaka.net.HttpPlugin} - - data URIs: {@link shaka.net.DataUriPlugin} + - HTTP(S): {@linksource shaka.net.HttpPlugin} + - data URIs: {@linksource shaka.net.DataUriPlugin} __ABR plugins__ - Configured at runtime on a Player instance - Use {@link player.configure} and set the `abr.manager` field - Must implement the {@link shakaExtern.AbrManager} interface - - Default AbrManager implementation: {@link shaka.abr.SimpleAbrManager} + - Default AbrManager implementation: {@linksource shaka.abr.SimpleAbrManager} __Polyfills__ - All polyfills are installed by {@link shaka.polyfill.installAll} - Register with {@link shaka.polyfill.register} - Default polyfills: - - prefixed fullscreen implementations: {@link shaka.polyfill.Fullscreen} - - prefixed video QoE metrics: {@link shaka.polyfill.VideoPlaybackQuality} + - prefixed fullscreen implementations: + {@linksource shaka.polyfill.Fullscreen} + - prefixed video QoE metrics: + {@linksource shaka.polyfill.VideoPlaybackQuality} - prefixed EME implementations for IE 11 and very old versions of embedded - Chrome/Chromium: {@link shaka.polyfill.MediaKeys} - - Promise implementation for IE 11: {@link shaka.polyfill.Promise} + Chrome/Chromium: {@linksource shaka.polyfill.MediaKeys} + - Promise implementation for IE 11: {@linksource shaka.polyfill.Promise} #### Excluding Default Plugins diff --git a/docs/tutorials/welcome.md b/docs/tutorials/welcome.md index d3494559e..d232aca9d 100644 --- a/docs/tutorials/welcome.md +++ b/docs/tutorials/welcome.md @@ -8,7 +8,30 @@ It plays [DASH][] content without browser plugins using [MediaSource Extensions]: http://w3c.github.io/media-source/ [Encrypted Media Extensions]: https://w3c.github.io/encrypted-media/ -## Getting Started +#### Prerequisites + +You can build Shaka on Linux, Windows, or Mac. +To get the sources and compile the library, you will need: + * Git 1.7.10+ {@link https://git-scm.com/downloads} + * Python 2.7.x {@link https://www.python.org/downloads/} + * Java Runtime Environment 7+ {@link https://java.com/en/download/} + +Additionally, to build the documentation and run the tests, you will need: + * npm v1.3.12+ {@link https://nodejs.org/en/download/} + +To quickly install these prerequisites on Ubuntu or Debian, run: + +```sh +sudo apt-get install git python2.7 openjdk-7-jre-headless npm +sudo npm install -g npm # Upgrade npm to the latest +# Add a symlink missing on some systems: +sudo ln -s /usr/bin/nodejs /usr/local/bin/node +``` + +Installation instructions for other operating systems are not provided here. +(We can't possibly document them all.) You can follow the links above to +download and install the prerequisites. + #### Get the source @@ -25,12 +48,12 @@ python build/all.py ``` -#### Join the mailing list +#### Join the community -If you want to discuss Shaka Player developement or receive notifications when -a new version is released, you should join our [mailing list]. +If you want to discuss Shaka Player development or receive notifications when +a new version is released, you should join our [users group]. -[mailing list]: https://groups.google.com/forum/#!forum/shaka-player-users +[users group]: https://groups.google.com/forum/#!forum/shaka-player-users #### Continue the Tutorials diff --git a/third_party/jsdoc/lib/jsdoc/util/templateHelper.js b/third_party/jsdoc/lib/jsdoc/util/templateHelper.js index 2c2305277..f6151ba57 100644 --- a/third_party/jsdoc/lib/jsdoc/util/templateHelper.js +++ b/third_party/jsdoc/lib/jsdoc/util/templateHelper.js @@ -139,6 +139,7 @@ var getUniqueId = exports.getUniqueId = makeUniqueId; // two-way lookup var linkMap = { longnameToUrl: {}, + longnameToSource: {}, urlToLongname: {} }; @@ -393,6 +394,15 @@ var toTutorial = exports.toTutorial = function(tutorial, content, missingOpts) { exports.resolveLinks = function(str) { var replaceInlineTags = require('jsdoc/tag/inline').replaceInlineTags; + var longnameToSourceUrl = {}; + for (var name in linkMap.longnameToSource) { + var data = linkMap.longnameToSource[name]; + var path = data[0]; + var lineno = data[1]; + var html = longnameToUrl[path]; + longnameToSourceUrl[name] = html + '#line' + lineno; + } + function extractLeadingText(string, completeTag) { var tagIndex = string.indexOf(completeTag); var leadingText = null; @@ -443,10 +453,30 @@ exports.resolveLinks = function(str) { return string.replace( tagInfo.completeTag, toTutorial(tagInfo.text, leading.leadingText) ); } + function processSource(string, tagInfo) { + var leading = extractLeadingText(string, tagInfo.completeTag); + var linkText = leading.leadingText; + var split; + var target; + string = leading.string; + + split = splitLinkText(tagInfo.text); + target = split.target; + linkText = linkText || split.linkText; + + monospace = useMonospace(tagInfo.tag, tagInfo.text); + + return string.replace( tagInfo.completeTag, buildLink(target, linkText, { + linkMap: longnameToSourceUrl, + monospace: monospace + }) ); + } + var replacers = { link: processLink, linkcode: processLink, linkplain: processLink, + linksource: processSource, tutorial: processTutorial }; @@ -775,6 +805,11 @@ var registerLink = exports.registerLink = function(longname, url) { linkMap.urlToLongname[url] = longname; }; +exports.registerSourceLink = function(longname, path, lineno) { + linkMap.longnameToSource[longname] = [path, lineno]; +}; + + /** * Get a longname's filename if one has been registered; otherwise, generate a unique filename, then * register the filename. diff --git a/third_party/jsdoc/templates/default/publish.js b/third_party/jsdoc/templates/default/publish.js index 77feb1a10..6e25d438a 100644 --- a/third_party/jsdoc/templates/default/publish.js +++ b/third_party/jsdoc/templates/default/publish.js @@ -560,6 +560,8 @@ exports.publish = function(taffyData, opts, tutorials) { docletPath = sourceFiles[docletPath].shortened; if (docletPath) { doclet.meta.shortpath = docletPath; + helper.registerSourceLink(doclet.longname, docletPath, + doclet.meta.lineno); } } }); diff --git a/third_party/jsdoc/templates/default/static/styles/jsdoc-default.css b/third_party/jsdoc/templates/default/static/styles/jsdoc-default.css index 7d7016b5b..27744dc04 100644 --- a/third_party/jsdoc/templates/default/static/styles/jsdoc-default.css +++ b/third_party/jsdoc/templates/default/static/styles/jsdoc-default.css @@ -141,10 +141,6 @@ footer { font-size: 90%; } -p { - margin-bottom: 24px; -} - h1, h2, h3, h4 { font-weight: 200; margin: 0; @@ -155,7 +151,7 @@ h1 font-family: 'Open Sans Light', sans-serif; font-size: 48px; letter-spacing: -2px; - margin: 12px 24px 20px; + margin-bottom: 20px; } h2, h3 @@ -170,7 +166,7 @@ h4 { font-size: 18px; letter-spacing: -0.33px; - margin-bottom: 12px; + margin-top: 32px; color: #4d4e53; } @@ -179,14 +175,14 @@ h5, .container-overview .subsection-title font-size: 120%; font-weight: bold; letter-spacing: -0.01em; - margin: 8px 0 3px -16px; + margin: 8px 0 3px; } h6 { font-size: 100%; letter-spacing: -0.01em; - margin: 6px 0 3px 0; + margin: 6px 0 3px; font-style: italic; }