r20407 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r20406‎ | r20407 | r20408 >
Date:21:04, 13 March 2007
Author:daniel
Status:old
Tags:
Comment:
embedded multimedia playback using common browser plugins. experimental.
Modified paths:
  • /trunk/extensions/News/News.php (modified) (history)
  • /trunk/extensions/Player (added) (history)
  • /trunk/extensions/Player/ICONS-LICENSE (added) (history)
  • /trunk/extensions/Player/Player.i18n.de.php (added) (history)
  • /trunk/extensions/Player/Player.i18n.php (added) (history)
  • /trunk/extensions/Player/Player.js (added) (history)
  • /trunk/extensions/Player/Player.php (added) (history)
  • /trunk/extensions/Player/PlayerClass.php (added) (history)
  • /trunk/extensions/Player/PlayerDefaultSettings.php (added) (history)
  • /trunk/extensions/Player/README (added) (history)
  • /trunk/extensions/Player/SpecialPlayer.php (added) (history)
  • /trunk/extensions/Player/blank.gif (added) (history)
  • /trunk/extensions/Player/install.settings (added) (history)
  • /trunk/extensions/Player/loading.gif (added) (history)
  • /trunk/extensions/Player/loading1.gif (added) (history)
  • /trunk/extensions/Player/loading2.gif (added) (history)
  • /trunk/extensions/Player/play.gif (added) (history)

Diff [purge]

Index: trunk/extensions/Player/play.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/Player/play.gif
___________________________________________________________________
Added: svn:mime-type
11 + application/octet-stream
Index: trunk/extensions/Player/ICONS-LICENSE
@@ -0,0 +1,6 @@
 2+play.gif and loading.gif are based on the player_play.png icon from the Crystal SVG icon set by Everaldo Coelho.
 3+
 4+http://www.kde-look.org/content/show.php?content=8341
 5+http://www.everaldo.com/crystal.html
 6+
 7+Crystal SVG icons, and therefore any icons based on them, are licensed under the LGPL.
Index: trunk/extensions/Player/blank.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/Player/blank.gif
___________________________________________________________________
Added: svn:mime-type
18 + application/octet-stream
Index: trunk/extensions/Player/README
@@ -0,0 +1,252 @@
 2+--------------------------------------------------------------------------
 3+README for the Player extension
 4+Copyright © 2007 Daniel Kinzler
 5+Licenses: GNU General Public Licence (GPL)
 6+ GNU Free Documentation License (GFDL)
 7+--------------------------------------------------------------------------
 8+
 9+The Player extension provides a special page, Special:Player, that allows
 10+playback of video and other multimedia content uploaded to the wiki. It
 11+also provides a custom tag, <player>, that allows multimedia content to be
 12+embedded into wiki pages and played on demand (embedded playback requires
 13+Ajax; without Ajax, a link to the player page is provided).
 14+
 15+<http://mediawiki.org/wiki/Extension:Player>
 16+
 17+The Player extension was originally written by Daniel Kinzler in 2007
 18+and is released under the GNU General Public Licence (GPL). Some of the
 19+icons are from LGPL icons sets, see the ICONS-LICENSE file.
 20+
 21+Note that this extension is EXPERIMENTAL, and basically an UGLY KLUGE
 22+while waiting for more flexible media file handling facilities in
 23+MediaWiki proper.
 24+
 25+Per default, the Player extension RELIES ON BROWSER PLUGINS for playback
 26+- this means that if you want to play a movie, your browser has to have a
 27+plugin for this type of movie installed. But the Player extension can also
 28+be configured to use a server-supplied player that is based on
 29+Macromedia Flash or Java. For example, the FlowPlayer Flash scrip can be
 30+used to play Flash Video files (FLV), or Flumotion's Cortado Java applet
 31+can be used to play OGG files - this way, users need to have Flash resp.
 32+Java installed (which is wide spread), instead of having to
 33+have codecs for FLV and OGG installed (which is rare - the VLC plugin
 34+supports both, though).
 35+
 36+* FlowPlayer: http://flowplayer.sourceforge.net/ (Apache License)
 37+* Flumotion Cortado: http://www.flumotion.net/cortado/ (GPL)
 38+
 39+== Installing ==
 40+
 41+Copy the Player directory into the extensions folder of your
 42+MediaWiki installation. Then add the following line to your
 43+LocalSettings.php file (near the end):
 44+
 45+ require_once( "$IP/extensions/Player/Player.php" );
 46+
 47+=== Installing Flash/Java-based players ===
 48+To install third-party players for use by the Player extension, get the
 49+files required by the player and put them into the directory you
 50+installed the Player extension in. The create a template that uses the
 51+player, and assign it to the desired MIME types using the
 52+$wgPlayerTemplates setting (see below). In PlayerDefaultSettings.php
 53+there are example templates for FlowPlayer and the Cortodo player.
 54+
 55+== Configuration ==
 56+
 57+The Player extension can be configured in several ways. The Default
 58+configuration, along with some notes and documenation, are in the
 59+PlayerDefaultSettings.php file. Some important settings are described below:
 60+
 61+* wgUseAjax: this is a global MediaWiki setting. You have to set it to true
 62+to enable embedded playback. If not enabled, or if the browser does not
 63+support JavaScript or has it disabled, a link to the player page will be
 64+provided instead of an embedded player.
 65+
 66+* $wgPlayerTemplates: this is an array that contains a template for each
 67+MIME-type that should be handeled by the Player plugin (see Templates below).
 68+
 69+* $wgPlayerMimeOverride: this is a map of mime-type aliases. This allows
 70+you to override the mime type that will be passed to the player template.
 71+For example, video/ogg is per defautl mapped to application/ogg, since
 72+some browser plugins don't recognize video/ogg.
 73+
 74+* $wgPlayerVideoResolutionDetector: this is used to configure the program used
 75+to detect the resolution (size) of videos. It can be set to false or null to
 76+disable resolution detection, or to a string to use the same detection command,
 77+for everything, or to an array mapping mime types to detection commands (using
 78+the entry for "*" as a fallback). Each entry in the array by itself be a
 79+string specifying a command, or an array containing three fields: command,
 80+outpattern and outreplace, where outpattern is a PCRE regular expression, and
 81+outreplace is a replacment string for that pattern. This can be used transform
 82+the commands output into the form expected by the Player extension, namely the
 83+form 400x300. There are two example settings in PlayerDefaultSettings.php,
 84+both commented out. One uses mplayer for everything, the otehr uses ogginfo
 85+for ogg files and mplayer for the rest. Note that for now, the detector
 86+command is run every time a player or placeholder is rendered.
 87+
 88+
 89+=== Templates ===
 90+Player templates are HTML-snippets for embedding something into the HTML output
 91+that allows a specific media file to be played (usually, a template would
 92+generate an <object>, <embed> or <applet> tag). In a template, placeholders
 93+for template parameters are used to adopt the template for a specific media
 94+file (see below).
 95+
 96+The $wgPlayerTemplates maps the MIME type of a given file to a template. If
 97+no template is defined for that type, playback is not allowed. If the
 98+"forcegeneric" option is used, the entry for the pseudo-type "generic"
 99+is always used, regardles of the file's actual type or the template associated
 100+with that type.
 101+
 102+PlayerDefaultSettings.php defines several templates for your conveniance:
 103+
 104+* $wgPlayerGenericTemplate: generates a generic <object> tag with fallback to
 105+<embed> for old browsers. This is used for almost everything per default.
 106+
 107+* $wgPlayerSvgPluginTemplate: like $wgPlayerGenericTemplate, but works around
 108+a problem with some SVG plugins by providing an extra src parameter. Used per
 109+default for image/svg+xml
 110+
 111+* $wgPlayerFlashPluginTemplate: generates specialized <object> and <embed>
 112+tags for the Macromedia Flash/ShockWave plugin. Used per default for
 113+application/x-shockwave-flash
 114+
 115+* $wgPlayerFlowPlayerTemplate: template for embedding the FlowPlayer for
 116+playback of FLV files. Not enabled per default; you can enable it by
 117+using the line for video/x-flv from PlayerDefaultSettings.php.
 118+Requires FlowPlayer from http://flowplayer.sourceforge.net
 119+Note that this has been tested successfully only with the "Light" version of
 120+FlowPlayer, other versions seemed to have some problem.
 121+
 122+* $wgPlayerCortadoPlayerTemplate: template for embedding the Cortado player
 123+for playback of OGG files. Not enabled per default; you can enable it by
 124+using the line for audio/ogg, video/ogg and application/ogg from
 125+PlayerDefaultSettings.php. Requires Cortado player
 126+from http://www.flumotion.net/cortado/
 127+
 128+In PlayerDefaultSettings.php, $wgPlayerGenericTemplate is assigned to most
 129+common media types, including mp3, wav, midi, ogg, mpeg, avi, and pdf.
 130+
 131+See http://www.mediawiki.org/wiki/Manual:Configuring_file_uploads for
 132+information on allowing specific file types for upload. See
 133+http://www.mediawiki.org/wiki/Manual:Mime_type_detection for information
 134+on MIME type detection.
 135+
 136+=== Template Parameters ===
 137+
 138+Template parameters have the form {{{xxx}}}. They are used as placeholders
 139+for values that apply to a specific media file, and will be replaced by the
 140+respective values before output. There are several forms of parameters:
 141+
 142+* {{{foo}}} is a simple parameter - it will expand to the value of
 143+the option "foo", or be removed if "foo" is not set.
 144+
 145+* {{{foo|quux}}} is a parameter with default walue - it will expand to
 146+the value of the option "foo", or to "quux" if "foo" is not set.
 147+
 148+* {{{#env:wgFoo}}} is an environment parameter - it will expand to the
 149+value of the global variable "wgFoo".
 150+This can be used to access global variables like $wgPlayerExtensionPath,
 151+$wgServer, $wgJsMimeType, $wgScriptPath, etc.
 152+
 153+* {{{#attr:foo}}} is an attribute-parameter - it will expand to
 154+foo="baz" (where baz is the value of the "foo" option).
 155+
 156+* {{{#attr:foo|bar}}} is an attribute-parameter with name-alias -
 157+it will expand to bar="baz" (where baz is the value of the "foo" option).
 158+
 159+* {{{#param:foo}}} is an param-tag-parameter - it will expand to
 160+<param name="foo" value="baz"/> (where baz is the value of the "foo" option).
 161+
 162+* {{{#param:foo|bar}}} is an param-tag-parameter with name-alias -
 163+<param name="bar" value="baz"/> (where baz is the value of the "foo" option).
 164+
 165+* {{{#ifset:foo|some text}}} is a conditional block - the value "some text"
 166+will be output only if the "foo"-option is set, otherwise the entire block
 167+is ignored. There is limmited support for nesting: ifset blocks can contain
 168+other template parameters, but not other ifset or ifunset blocks.
 169+
 170+* {{{#ifunset:foo|some text}}} is a inverse conditional block - the value
 171+"some text" will be output only if the "foo"-option is NOT set, otherwise
 172+the entire block is ignored. There is limmited support for nesting: ifunset
 173+blocks can contain other template parameters, but not other ifset or ifunset
 174+blocks.
 175+
 176+The following template parameters are always available:
 177+
 178+* uniq: a unique string, may be used to mark and refer to HTML elements using
 179+the id attribute.
 180+* url: the (local) URL of the media file.
 181+* fullurl: the full URL of the media file.
 182+* type: MIME-type media file (subject to $wgPlayerMimeTypeOverride).
 183+* width: the effective width, in pixels, the player should occupy.
 184+* height: the effective height, in pixels, the player should occupy.
 185+* pageurl: the URL of the file's description page in the wiki.
 186+* filename: plain name of the media file.
 187+* plainalt: an alternative text suitable for use in HTML attrbutes (such as
 188+alt or title). Generally the file name.
 189+* htmlalt: HTML-text that may be shown instead of the player. Generally a
 190+link to the file's description page.
 191+
 192+The following global variables (accessible by the {{{#env:xxx}}} syntax) may
 193+be particularly interresting:
 194+
 195+* $wgPlayerExtensionPath: The URL path to the extension's installation
 196+directory. This may be used to reference secondary files in that directory,
 197+such as CSS or JS files, player scripts (SWF or JAR files), etc.
 198+
 199+* $wgScriptPath: URL path to MediaWiki's installation root. Usefull for
 200+building URLs.
 201+
 202+* $wgServer: Host- and protocol part of MediaWiki's server. Usefull for
 203+building URLs.
 204+
 205+Additional parameters may be passed from attributes the user supplies in
 206+a <player> tag, or on the Special:Player page. User-supplied parameteres
 207+are always HTML-escaped.
 208+
 209+== Usage ==
 210+
 211+The <player> tag can be used to embed videos and other multimedia content
 212+into wiki pages.
 213+
 214+ <player>Testing.mpg</player> this embeds the Testing.mpg file
 215+ <player>Testing.mpg | some text</player> this embeds the Testing.mpg file with a caption
 216+ <player align="right" width="200">Testing.mpg</player> floating right-aligned, 200 pixels wide.
 217+
 218+=== Tag Attributes ===
 219+The following attributes can be usedin <player> tags:
 220+
 221+* id: sets the global ID for the resulting HTML structure.
 222+
 223+* class: adds CSS class(es) - same as for normal HTML tags.
 224+
 225+* style: adds CSS styles - same as for normal HTML tags.
 226+
 227+* width: determines the desired width for the player. The aspect ratio is
 228+preserved while scaling, if know (see $wgPlayerVideoResolutionDetector).
 229+If both width and height are given, a box-fit is applied.
 230+
 231+* height: determines the desired height for the player. The aspect ratio is
 232+preserved while scaling, if know (see $wgPlayerVideoResolutionDetector).
 233+If both width and height are given, a box-fit is applied.
 234+
 235+* align: determines the alignment. Thre are four possible values:
 236+**none: (default): the player box creates a paragraph.
 237+**center: the player box creates a centered paragraph.
 238+**left: the player box floats on the left side, text flows around it.
 239+**right: the player box floats on the right side, text flows around it.
 240+
 241+* thumb: determines the thumbnail image (if any). Must be the name of an
 242+uploaded image.
 243+
 244+* forcegeneric: use the template registered under the "generic" key, instead
 245+of selecting a template by the file's type.
 246+
 247+Any additional attributes are passed on as template parameters. So, if you
 248+give foo="test" as an attribute, a template may refer to that value using
 249+{{{foo}}}. Note that user parameters are always escaped before being passed
 250+to the template, to avoid HTML injection issues.
 251+
 252+Some attributes supported by some templates (in the hope the user's plugin
 253+will understand them): loop, menu, scale, and quality.
Index: trunk/extensions/Player/Player.i18n.php
@@ -0,0 +1,30 @@
 2+<?php
 3+
 4+/**
 5+ * Internationalisation file for the Player extension
 6+ *
 7+ * @package MediaWiki
 8+ * @subpackage Extensions
 9+ * @author Daniel Kinzler, brightbyte.de
 10+ * @copyright © 2007 Daniel Kinzler
 11+ * @licence GNU General Public Licence 2.0 or later
 12+ */
 13+
 14+$messages['player']= 'Player';
 15+$messages['player-title']= 'Player';
 16+$messages['player-playertitle']= 'Player: $1';
 17+$messages['player-pagetext']= '';
 18+
 19+$messages['player-file']= 'File name';
 20+$messages['player-play']= 'Play';
 21+
 22+$messages['player-imagepage-header']= '<h1>$1</h1>';
 23+$messages['player-not-allowed']= 'unallowed format';
 24+$messages['player-not-found']= 'file not found';
 25+$messages['player-invalid-title']= 'invalid title';
 26+
 27+$messages['player-clicktoplay']= 'Play $1';
 28+$messages['player-goto-player']= 'player';
 29+$messages['player-goto-page']= 'Page';
 30+$messages['player-goto-file']= 'file';
 31+?>
Index: trunk/extensions/Player/loading.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/Player/loading.gif
___________________________________________________________________
Added: svn:mime-type
132 + application/octet-stream
Index: trunk/extensions/Player/Player.php
@@ -0,0 +1,188 @@
 2+<?php
 3+/**
 4+ * Player extension - multimedia playback using common browser plugins
 5+ *
 6+ * @package MediaWiki
 7+ * @subpackage Extensions
 8+ * @author Daniel Kinzler, brightbyte.de
 9+ * @copyright © 2007 Daniel Kinzler
 10+ * @licence GNU General Public Licence 2.0 or later
 11+ */
 12+
 13+
 14+if( !defined( 'MEDIAWIKI' ) ) {
 15+ echo( "This file is an extension to the MediaWiki software and cannot be used standalone.\n" );
 16+ die( 1 );
 17+}
 18+
 19+$wgExtensionCredits['specialpage'][] = array(
 20+ 'name' => 'Player',
 21+ 'author' => 'Daniel Kinzler, brightbyte.de',
 22+ 'url' => 'http://mediawiki.org/wiki/Extension:Player',
 23+ 'description' => 'embedded multimedia playback using common browser plugins',
 24+);
 25+
 26+$wgExtensionFunctions[] = "playerSetup";
 27+$wgHooks['OutputPageParserOutput'][] = 'playerParserOutput';
 28+$wgHooks['LoadAllMessages'][] = 'loadPlayerI18n';
 29+
 30+$wgAutoloadClasses['Player'] = dirname( __FILE__ ) . '/PlayerClass.php';
 31+$wgAutoloadClasses['SpecialPlayer'] = dirname( __FILE__ ) . '/SpecialPlayer.php';
 32+$wgSpecialPages['Player'] = 'SpecialPlayer';
 33+
 34+$wgAjaxExportList[] = 'playerAjaxHandler';
 35+
 36+$wgPlayerExtensionPath = $GLOBALS['wgServer'] . $GLOBALS['wgScriptPath'] . '/extensions/Player';
 37+
 38+$wgPlayerMimeOverride = array( );
 39+
 40+$wgPlayerTemplates = array();
 41+$wgPlayerVideoResolutionDetector = NULL;
 42+
 43+require_once( dirname( __FILE__ ) . '/PlayerDefaultSettings.php' );
 44+
 45+function playerSetup() {
 46+ global $wgParser;
 47+
 48+ $wgParser->setHook( "player", "renderPlayerTag" );
 49+}
 50+
 51+function renderPlayerTag( $name, $args, &$parser ) {
 52+ global $wgUser;
 53+
 54+ $attribnames = array( 'id', 'style', 'class', 'thumb', 'align' );
 55+
 56+ $attributes = array();
 57+ $options = array();
 58+
 59+ $deferred = NULL; //TODO: true forces immediate playback (no ajax), false suppresses it (use ajax).
 60+
 61+ foreach ($args as $k => $v) {
 62+ if (in_array($k, $attribnames)) $attributes[$k] = $v;
 63+ else $options[$k] = $v;
 64+ }
 65+
 66+ $name = trim($name);
 67+ $n = explode('|', $name, 2);
 68+ if (sizeof($n) > 1) {
 69+ $name = trim($n[0]);
 70+ $options['caption'] = $n[1];
 71+ }
 72+
 73+ #print_r($attributes);
 74+ #print_r($options);
 75+
 76+ $parser->mOutput->mPlayerTag = true; # flag for use by playerParserOutput
 77+
 78+ try {
 79+ $player = Player::newFromName($name, $options, 'thumbsize');
 80+ $html = $player->getThumbnailHTML($attributes, $deferred);
 81+
 82+ $html = trim( preg_replace('/[ \t\r\n]+/', ' ', $html) ); //normalize whitespace, don't trigger block-level formating
 83+ return $html;
 84+ }
 85+ catch (PlayerException $ex) {
 86+ $skin = $wgUser->getSkin();
 87+
 88+ if ($ex->getCode() == '404') {
 89+ return $skin->makeBrokenLinkObj( Title::makeTitleSafe(NS_IMAGE, $name) );
 90+ }
 91+ else if (@$player && $ex->getCode() == '403') {
 92+ //TODO: show "normal" image thumbnail. requires parameter mangeling, though...
 93+ return $skin->makeKnownLinkObj( $player->title );
 94+ }
 95+ else {
 96+ return "<div class='error'>" . $ex->getMessage() . "</div>";
 97+ }
 98+ }
 99+}
 100+
 101+function playerAjaxHandler( $file, $options ) {
 102+ $response = new AjaxResponse( );
 103+
 104+ try {
 105+ #TODO: caching!
 106+
 107+ $player = Player::newFromName( $file, $options, 'thumbsize' );
 108+ $html = $player->getPlayerHTML( );
 109+
 110+ $response->addText( $html );
 111+ }
 112+ catch (PlayerException $ex) {
 113+ $response->setResponseCode($ex->getHTTPCode());
 114+ $response->addText($ex->getHTML());
 115+ }
 116+
 117+ return $response;
 118+}
 119+
 120+/**
 121+* Hook callback that injects messages and things into the <head> tag
 122+* Does nothing if $parserOutput->mPlayerTag is not set
 123+*/
 124+function playerParserOutput( &$outputPage, &$parserOutput ) {
 125+ if ( !empty( $parserOutput->mPlayerTag ) ) {
 126+ Player::setHeaders( $outputPage );
 127+ }
 128+ return true;
 129+}
 130+
 131+/**
 132+* load the Player internationalization file
 133+*/
 134+function loadPlayerI18n() {
 135+ global $wgContLang, $wgMessageCache;
 136+
 137+ static $initialized = false;
 138+
 139+ if ( $initialized ) return;
 140+
 141+ $messages= array();
 142+
 143+ $f= dirname( __FILE__ ) . '/Player.i18n.php';
 144+ include( $f );
 145+
 146+ $f= dirname( __FILE__ ) . '/Player.i18n.' . $wgContLang->getCode() . '.php';
 147+ if ( file_exists( $f ) ) include( $f );
 148+
 149+ $initialized = true;
 150+ $wgMessageCache->addMessages( $messages );
 151+}
 152+
 153+
 154+if (!function_exists('urldecodeMap')) {
 155+ function urldecodeMap($s) {
 156+ if (!$s) return array();
 157+
 158+ $entries = explode('&', $s);
 159+ $map = array();
 160+
 161+ foreach ($entries as $e) {
 162+ $m = explode('=', $e, 2);
 163+ $k = urldecode($m[0]);
 164+ $v = sizeof($m) < 2 ? true : urldecode($m[1]);
 165+ $map[$k] = $v;
 166+ }
 167+
 168+ return $map;
 169+ }
 170+}
 171+
 172+if (!function_exists('urlencodeMap')) {
 173+ function urlencodeMap($map) {
 174+ $s = '';
 175+
 176+ foreach ($map as $k => $v) {
 177+ if ($s!=='') $s.= '&';
 178+ $s.= urlencode($k);
 179+
 180+ if ($v === false || $v === NULL) continue;
 181+ else if ($v !== true) $s.= '=' . urlencode($v);
 182+ }
 183+
 184+ return $s;
 185+ }
 186+}
 187+
 188+
 189+?>
\ No newline at end of file
Index: trunk/extensions/Player/loading1.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/Player/loading1.gif
___________________________________________________________________
Added: svn:mime-type
1190 + application/octet-stream
Index: trunk/extensions/Player/SpecialPlayer.php
@@ -0,0 +1,164 @@
 2+<?php
 3+/**
 4+ * Special:Player, a media playback page
 5+ *
 6+ * @addtogroup SpecialPage
 7+ * @author Daniel Kinzler, brightbyte.de
 8+ * @copyright © 2007 Daniel Kinzler
 9+ * @licence GNU General Public Licence 2.0 or later
 10+ */
 11+
 12+if( !defined( 'MEDIAWIKI' ) ) {
 13+ echo( "not a valid entry point.\n" );
 14+ die( 1 );
 15+}
 16+
 17+/**
 18+ *
 19+ */
 20+class SpecialPlayer extends SpecialPage {
 21+
 22+ /**
 23+ * Constructor
 24+ */
 25+ function __construct() {
 26+ global $wgOut;
 27+ SpecialPage::SpecialPage( 'Player', '', true );
 28+
 29+ #inject messages
 30+ loadPlayerI18n();
 31+ }
 32+
 33+ /**
 34+ * Main execution function
 35+ * @param $par Parameters passed to the page
 36+ */
 37+ function execute( $par ) {
 38+ global $wgOut, $wgRequest;
 39+
 40+ $file = $wgRequest->getVal( 'playfile', $par );
 41+
 42+ $options = $wgRequest->getVal( 'options', '' );
 43+ $options = urldecodeMap($options);
 44+
 45+ $options['width'] = (int)$wgRequest->getVal( 'width', @$options['width'] );
 46+ $options['height'] = (int)$wgRequest->getVal( 'height', @$options['height'] );
 47+
 48+ $options['forcegeneric'] = ( @$options['forcegeneric'] || $wgRequest->getCheck( 'forcegeneric' ) );
 49+ $options['playersize'] = $wgRequest->getVal( 'playersize', @$options['playersize'] );
 50+
 51+ $title = $file ? Title::makeTitleSafe(NS_IMAGE, $file) : NULL;
 52+
 53+ if ( $title ) {
 54+ $this->showPlayer( $title, $options );
 55+ }
 56+ else {
 57+ $this->showForm();
 58+ }
 59+ }
 60+
 61+ function showForm() {
 62+ global $wgOut;
 63+
 64+ $wgOut->setPagetitle( wfMsg( "player-title" ) );
 65+ $wgOut->addWikiText( wfMsg( "player-pagetext" ) );
 66+
 67+ $titleObj = SpecialPage::getTitleFor( "Player" );
 68+ $action = $titleObj->getLocalURL( "action=submit" );
 69+
 70+ $wgOut->addHTML( Xml::openElement( 'form', array('id' => 'player', 'method' => 'post', 'action' => $action) ) );
 71+ $wgOut->addHTML( '<div>' );
 72+ $wgOut->addHTML( Xml::inputLabel( wfMsg('player-file'), 'playfile', 'playfile' ) );
 73+ $wgOut->addHTML( ' ' );
 74+ $wgOut->addHTML( Xml::submitButton( wfMsg('player-play') ) );
 75+ $wgOut->addHTML( '</div>' );
 76+ $wgOut->addHTML( Xml::closeElement( 'form' ) );
 77+ }
 78+
 79+ function showPlayer( $title, $options ) {
 80+ global $wgOut, $wgUser;
 81+ $skin = $wgUser->getSkin();
 82+
 83+ $wgOut->setPagetitle( wfMsg( "player-playertitle", htmlspecialchars($title->getText()) ) );
 84+ $wgOut->addWikiText( wfMsg( "player-pagetext" ) );
 85+
 86+ try {
 87+ $player = Player::newFromTitle( $title, $options );
 88+ $html = $player->getPlayerHTML( );
 89+
 90+ $wgOut->addHTML( '<div id="player-display" style="text-align:center">' );
 91+ $wgOut->addHTML( $html );
 92+ $wgOut->addHTML( '</div>' );
 93+ }
 94+ catch (PlayerException $ex) {
 95+ $wgOut->addHTML( "<div class='error'>" . $ex->getMessage() . "</div>" );
 96+ }
 97+
 98+ $wgOut->addHTML( wfMsg( 'player-imagepage-header', $skin->makeLinkObj( $title ) ) );
 99+
 100+ if (@$player) {
 101+ $page = new PlayerImagePage( $player->image );
 102+ $page->view();
 103+ }
 104+ }
 105+}
 106+
 107+
 108+class PlayerImagePage extends ImagePage {
 109+ function __construct( $image ) {
 110+ parent::__construct( $image->getTitle() );
 111+
 112+ $this->img = $image;
 113+ }
 114+
 115+ /** mostly copied from ImagePage class, removed stuff not needed for Special:Player **/
 116+ function view() {
 117+ global $wgOut, $wgShowEXIF, $wgRequest, $wgUser;
 118+
 119+ if ($wgShowEXIF && $this->img->exists()) { //TODO: separate exif option for the player page?
 120+ $exif = $this->img->getExifData();
 121+ $showmeta = count($exif) ? true : false;
 122+ } else {
 123+ $exif = false;
 124+ $showmeta = false;
 125+ }
 126+
 127+ //$this->openShowImage();
 128+
 129+ # No need to display noarticletext, we use our own message, output in openShowImage()
 130+ if ( $this->getID() ) {
 131+ Article::view();
 132+ } else {
 133+ # Just need to set the right headers
 134+ $wgOut->setArticleFlag( false );
 135+ $wgOut->setRobotpolicy( 'noindex,nofollow' );
 136+ $this->viewUpdates();
 137+ }
 138+
 139+ # Show shared description, if needed
 140+ if ( $this->mExtraDescription ) {
 141+ $fol = wfMsg( 'shareddescriptionfollows' );
 142+ if( $fol != '-' ) {
 143+ $wgOut->addWikiText( $fol );
 144+ }
 145+ $wgOut->addHTML( '<div id="shared-image-desc">' . $this->mExtraDescription . '</div>' );
 146+ }
 147+
 148+ //$this->closeShowImage();
 149+
 150+ //TODO: make a global option for showing links & history...
 151+ $this->imageHistory();
 152+ $this->imageLinks();
 153+
 154+ if ( $exif ) {
 155+ global $wgStylePath, $wgStyleVersion;
 156+ $expand = htmlspecialchars( wfEscapeJsString( wfMsg( 'metadata-expand' ) ) );
 157+ $collapse = htmlspecialchars( wfEscapeJsString( wfMsg( 'metadata-collapse' ) ) );
 158+ $wgOut->addHTML( Xml::element( 'h2', array( 'id' => 'metadata' ), wfMsg( 'metadata' ) ). "\n" );
 159+ $wgOut->addWikiText( $this->makeMetadataTable( $exif ) );
 160+ $wgOut->addHTML(
 161+ "<script type=\"text/javascript\" src=\"$wgStylePath/common/metadata.js?$wgStyleVersion\"></script>\n" .
 162+ "<script type=\"text/javascript\">attachMetadataToggle('mw_metadata', '$expand', '$collapse');</script>\n" );
 163+ }
 164+ }
 165+}
\ No newline at end of file
Index: trunk/extensions/Player/loading2.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/Player/loading2.gif
___________________________________________________________________
Added: svn:mime-type
1166 + application/octet-stream
Index: trunk/extensions/Player/install.settings
@@ -0,0 +1,3 @@
 2+$wgUseAjax = true;
 3+
 4+require_once( "{{path}}/Player.php" );
Index: trunk/extensions/Player/Player.i18n.de.php
@@ -0,0 +1,31 @@
 2+<?php
 3+
 4+/**
 5+ * Internationalisation file for the Player extension
 6+ *
 7+ * @package MediaWiki
 8+ * @subpackage Extensions
 9+ * @author Daniel Kinzler, brightbyte.de
 10+ * @copyright © 2007 Daniel Kinzler
 11+ * @licence GNU General Public Licence 2.0 or later
 12+ */
 13+
 14+$messages['player']= 'Player';
 15+$messages['player-title']= 'Player';
 16+$messages['player-playertitle']= 'Player: $1';
 17+$messages['player-pagetext']= '';
 18+
 19+$messages['player-file']= 'Dateiname';
 20+$messages['player-play']= 'Abspielen';
 21+
 22+$messages['player-imagepage-header']= '<h1>$1</h1>';
 23+$messages['player-not-allowed']= 'Unerlaubtes Format';
 24+$messages['player-not-found']= 'Datei nicht gefunden';
 25+$messages['player-invalid-title']= 'ungültiger name';
 26+
 27+$messages['player-clicktoplay']= '$1 abspielen';
 28+$messages['player-goto-player']= 'Player';
 29+$messages['player-goto-page']= 'Seite';
 30+$messages['player-goto-file']= 'Datei';
 31+
 32+?>
Index: trunk/extensions/Player/Player.js
@@ -0,0 +1,29 @@
 2+/*
 3+ * JavaScript functions for the Player extension,
 4+ * for support of the AJAX inline player functionality.
 5+ *
 6+ * @package MediaWiki
 7+ * @subpackage Extensions
 8+ * @author Daniel Kinzler <duesentrieb@brightbyte.de>
 9+ * @copyright © 2006 Daniel Kinzler
 10+ * @licence GNU General Public Licence 2.0 or later
 11+*/
 12+
 13+ function loadPlayer(file, opt, id) {
 14+ var div = document.getElementById(id + '-container');
 15+ var ovl = document.getElementById(id + '-overlay');
 16+
 17+ if (ovl) ovl.style.backgroundImage= "url("+wgPlayerExtensionPath+"/loading.gif)";
 18+
 19+ function f( request ) {
 20+ var result= request.responseText;
 21+ result= result.replace(/^\s+|\s+$/, '');
 22+
 23+ if (request.status != 200) result= "<div class='error'> " + request.status + " " + request.statusText + ": " + result + "</div>";
 24+
 25+ div.innerHTML= result;
 26+ }
 27+
 28+ sajax_do_call( "playerAjaxHandler", [file, opt], f );
 29+ }
 30+
Index: trunk/extensions/Player/PlayerClass.php
@@ -0,0 +1,497 @@
 2+<?php
 3+/**
 4+ * Player class
 5+ *
 6+ * @addtogroup SpecialPage
 7+ * @author Daniel Kinzler, brightbyte.de
 8+ * @copyright © 2007 Daniel Kinzler
 9+ * @licence GNU General Public Licence 2.0 or later
 10+ */
 11+
 12+if( !defined( 'MEDIAWIKI' ) ) {
 13+ echo( "not a valid entry point.\n" );
 14+ die( 1 );
 15+}
 16+
 17+/**
 18+ *
 19+ */
 20+class Player {
 21+
 22+ var $image;
 23+ var $title;
 24+ var $options;
 25+ var $mimetype;
 26+ var $mediatype;
 27+ var $width;
 28+ var $height;
 29+ var $uniq;
 30+ var $playerTitle;
 31+
 32+ function __construct( $image, $options, $sizeDefault = 'imagesize' ) {
 33+ loadPlayerI18n();
 34+
 35+ if ( is_null( $options ) ) $options = array();
 36+ if ( is_string( $options ) ) $options = urldecodeMap( $options );
 37+
 38+ static $uniq = 0;
 39+ $uniq += 1;
 40+ $this->uniq = 'player-' . $uniq . '-' . mt_rand( 1, 100000 );
 41+
 42+ $this->options = $options;
 43+ $this->image = $image;
 44+ $this->title = $image->getTitle();
 45+
 46+ $this->setType( $image );
 47+ $this->setSize( @$options['width'], @$options['height'], $sizeDefault );
 48+ }
 49+
 50+ static function newFromTitle( $title, $options, $sizeDefault = 'imagesize' ) {
 51+ loadPlayerI18n();
 52+
 53+ if (!$title->exists()) throw new PlayerException(wfMsg("player-not-found"), 404);
 54+
 55+ $image = new Image( $title );
 56+
 57+ return new Player( $image, $options, $sizeDefault );
 58+ }
 59+
 60+ static function newFromName( $name, $options, $sizeDefault = 'imagesize' ) {
 61+ loadPlayerI18n();
 62+
 63+ $title = Title::makeTitleSafe(NS_IMAGE, $name);
 64+ if (!$title) throw new PlayerException(wfMsg("player-invalid-title"), 400);
 65+
 66+ return Player::newFromTitle( $title, $options, $sizeDefault );
 67+ }
 68+
 69+ function assertAllowedType() {
 70+ global $wgPlayerTemplates;
 71+ if (!isset($wgPlayerTemplates[$this->mimetype]) || !$wgPlayerTemplates[$this->mimetype])
 72+ throw new PlayerException(wfMsg("player-not-allowed"), 403);
 73+ }
 74+
 75+ function setType( $image ) {
 76+ $this->mimetype = $image->getMimeType();
 77+ $this->mediatype = $image->getMediaType();
 78+
 79+ #FIXME: ugly hack! do this on upload!
 80+ if ( $this->mimetype == 'unknown/unknown' ) {
 81+ $mime = MimeMagic::singleton();
 82+ $ext = preg_replace('!^.*\.([^.]+)$!', '\1', $image->getName());
 83+ $this->mimetype = $mime->guessTypesForExtension($ext);
 84+ $this->mediatype = $mime->getMediaType(NULL, $this->mimetype);
 85+ }
 86+
 87+ if ( preg_match('!/(x-)?ogg$!', $this->mimetype) ) {
 88+
 89+ if ( $this->mediatype == MEDIATYPE_AUDIO ) $this->mimetype = 'audio/ogg';
 90+ else if ( $this->mediatype == MEDIATYPE_VIDEO ) $this->mimetype = 'video/ogg';
 91+ else $this->mimetype = 'application/ogg';
 92+ }
 93+ }
 94+
 95+ function setSize( $width, $height, $sizeDefault = 'imagesize' ) {
 96+ global $wgUser;
 97+
 98+ #print "[WHq: $width, $height]";
 99+
 100+ if ($height) $height = (int)$height;
 101+ if ($width) $width = (int)$width;
 102+
 103+ if ($height<=0) $height = NULL;
 104+ if ($width<=0) $width = NULL;
 105+
 106+ if ( $this->mediatype == MEDIATYPE_AUDIO ) {
 107+ //HACK! this actually depends on the player used, and thus on the mime type.
 108+ $imgwidth = 250;
 109+ $imgheight = 140;
 110+
 111+ if (!$width) $width = $imgwidth;
 112+ if (!$height) $height = $height;
 113+ }
 114+ else {
 115+ $imgwidth = $this->image->getWidth();
 116+ $imgheight = $this->image->getHeight();
 117+
 118+ if ( $this->mediatype == MEDIATYPE_VIDEO && (!$imgwidth || !$imgheight) ) {
 119+ $dim = Player::detectVideoResolution( $this->image, $this->mimetype );
 120+ if ($dim) {
 121+ list( $imgwidth, $imgheight ) = $dim;
 122+ //TODO: store in DataBase!
 123+ }
 124+ }
 125+ }
 126+
 127+ $imgratio = $imgheight && $imgwidth ? (float)$imgwidth / (float)$imgheight : 1;
 128+
 129+ #print "[WH0: $width, $height; $imgwidth, $imgheight ~$imgratio]";
 130+ if (!$width && !$height) {
 131+ $wopt = @$this->options['playersize'];
 132+ if ($wopt) {
 133+ if (preg_match('/([it])?(\d+)/i', $wopt, $m)) {
 134+ $sz = @$m[1];
 135+ if ($sz && strtolower($sz) == 't') $sizeDefault = 'thumbsize';
 136+ else $sizeDefault = 'imagesize';
 137+
 138+ $wopt = (int)$m[2];
 139+ }
 140+ else $wopt = false;
 141+ }
 142+
 143+ if (!$wopt) $wopt = $wgUser->getOption( $sizeDefault );
 144+
 145+ if ( $sizeDefault == 'thumbsize' ) $limits = $GLOBALS['wgThumbLimits'];
 146+ else $limits = $GLOBALS['wgImageLimits'];
 147+
 148+ if( !isset( $limits[$wopt] ) ) {
 149+ $wopt = User::getDefaultOption( $sizeDefault );
 150+ }
 151+
 152+ list($width, $height) = $limits[$wopt];
 153+ if (!$width) $width = $sizeDefault == 'thumbsize' ? 180 : 600;
 154+ }
 155+
 156+ #print "[WH1: $width, $height]";
 157+
 158+ if ($imgwidth && $width > $imgwidth) {
 159+ if ($height) $height = ceil($height * ((float)$imgwidth / $width));
 160+ $width = $imgwidth;
 161+ }
 162+
 163+ if ($imgheight && $height > $imgheight) {
 164+ if ($width) $width = ceil($width * ((float)$imgheight / $height));
 165+ $height = $imgheight;
 166+ }
 167+
 168+ #print "[WH2: $width, $height]";
 169+
 170+ if (!$width) $width = ceil($height * $imgratio);
 171+ else if (!$height) $height = ceil($width / $imgratio);
 172+
 173+ #print "[WH3: $width, $height]";
 174+
 175+ $this->width = $width;
 176+ $this->height = $height;
 177+ }
 178+
 179+ static function detectVideoResolution( $image, $mimetype = NULL ) {
 180+ global $wgPlayerVideoResolutionDetector;
 181+ if (!$wgPlayerVideoResolutionDetector) return false;
 182+
 183+ $file = $image->getImagePath();
 184+ if (!$file) return false;
 185+
 186+ if (!$mimetype) $mimetype = $image->getMimeType();
 187+
 188+ if (!is_array($wgPlayerVideoResolutionDetector)) $detector = $wgPlayerVideoResolutionDetector;
 189+ else if (isset($wgPlayerVideoResolutionDetector[$mimetype])) $detector = $wgPlayerVideoResolutionDetector[$mimetype];
 190+ else $detector = $wgPlayerVideoResolutionDetector['*'];
 191+
 192+ if (!$detector) return false;
 193+
 194+ if (is_array($detector)) extract($detector);
 195+ else $command = $detector;
 196+
 197+ $command = str_replace('$file', wfEscapeShellArg($file), $command);
 198+ $command = str_replace('$type', wfEscapeShellArg($mimetype), $command);
 199+
 200+ wfProfileIn( 'detectVideoResolution' );
 201+ wfDebug( "detectVideoResolution: $command\n" );
 202+ $retval = 0;
 203+ $out = wfShellExec( $command, $retval );
 204+ wfProfileOut( 'detectVideoResolution' );
 205+
 206+ if ($retval != 0) return false; //TODO: log!
 207+ if (!$out) return false;
 208+
 209+ $out = trim($out);
 210+ if (!$out) return false;
 211+
 212+ if (isset($outpattern) && isset($outreplace)) $out = preg_replace($outpattern, $outreplace, $out);
 213+
 214+ if (!preg_match('!(\d+)x(\d+)!', $out, $m)) return false;
 215+ array_shift($m);
 216+
 217+ return $m; // array( $width, $height )
 218+ }
 219+
 220+ /**
 221+ * Set the script tags in an OutputPage object
 222+ * @param OutputPage $outputPage
 223+ */
 224+ static function setHeaders( &$outputPage ) {
 225+ global $wgJsMimeType, $wgPlayerExtensionPath, $wgContLang;
 226+ loadPlayerI18n();
 227+
 228+ # Register css file for Player
 229+ /*$outputPage->addLink(
 230+ array(
 231+ 'rel' => 'stylesheet',
 232+ 'type' => 'text/css',
 233+ 'href' => $wgPlayerExtensionPath . '/Player.css'
 234+ )
 235+ );*/
 236+
 237+ # Register css RTL file for Player
 238+ /*if( $wgContLang->isRTL() ) {
 239+ $outputPage->addLink(
 240+ array(
 241+ 'rel' => 'stylesheet',
 242+ 'type' => 'text/css',
 243+ 'href' => $wgPlayerExtensionPath . '/Player.rtl.css'
 244+ )
 245+ );
 246+ }*/
 247+
 248+ # Register main js file for Player
 249+ $outputPage->addScript(
 250+ "<script type=\"{$wgJsMimeType}\" src=\"{$wgPlayerExtensionPath}/Player.js\">" .
 251+ "</script>\n"
 252+ );
 253+
 254+ //var playerLoadingMsg = \"".Xml::escapeJsString(wfMsg('player-loading'))."\";
 255+ //var playerErrorMsg = \"".Xml::escapeJsString(wfMsg('player-error'))."\";
 256+
 257+ # Add messages
 258+ $outputPage->addScript(
 259+ " <script type=\"{$wgJsMimeType}\">
 260+ var wgPlayerExtensionPath = \"".$wgPlayerExtensionPath."\";
 261+ </script>\n"
 262+ );
 263+ }
 264+
 265+ static function processTemplate( $template, $options ) {
 266+ $html = $template;
 267+ #$html = preg_replace("!\\\\(.)!", "\1\\1\1", $html);
 268+
 269+ #print "\nH <pre>".htmlspecialchars($html)."</pre>\n";
 270+
 271+ foreach ($options as $k => $v) {
 272+ $html = preg_replace('@\{\{\{'.$k.'(\|([^\}]*?))?\}\}\}@sm', $v, $html);
 273+ $html = preg_replace('@\{\{\{#attr:'.$k.'\}\}\}@sm', $k.'="'.$v.'"', $html);
 274+ $html = preg_replace('@\{\{\{#attr:'.$k.'\|([^\}]*?)\}\}\}@sm', '\1="'.$v.'"', $html);
 275+ $html = preg_replace('@\{\{\{#param:'.$k.'\}\}\}@sm', '<param name="'.$v.'" value="'.$v.'"/>', $html);
 276+ $html = preg_replace('@\{\{\{#param:'.$k.'\|([^\}]*?)\}\}\}@sm', '<param name="\1" value="'.$v.'"/>', $html);
 277+ $html = preg_replace('@\{\{\{#ifset:'.$k.'\|([^\}]*?)\}\}\}@sm', '\1', $html);
 278+ $html = preg_replace('@\{\{\{#ifunset:'.$k.'\|([^\}]*?)\}\}\}@sm', '', $html);
 279+ }
 280+
 281+ #print "\nK <pre>".htmlspecialchars($html)."</pre>\n";
 282+
 283+ $html = preg_replace('@\{\{\{#env:(\w[-.\w\d]*)\}\}\}@sme', '$GLOBALS["\1"]', $html);
 284+
 285+ $html = preg_replace('@\{\{\{\w[-.\w\d]*\}\}\}@sm', '', $html);
 286+ $html = preg_replace('@\{\{\{\w[-.\w\d]*\|([^\}]*)\}\}\}@sm', '\1', $html);
 287+ $html = preg_replace('@\{\{\{#(attr|param):\w[-.\w\d]*(\|[^\}]*)?\}\}\}@sm', '', $html);
 288+ $html = preg_replace('@\{\{\{#ifunset:\w[-.\w\d]*\|([^\}]*?)\}\}\}@sm', '\1', $html);
 289+ $html = preg_replace('@\{\{\{#ifset:\w[-.\w\d]*(\|[^\}]*)?\}\}\}@sm', '', $html);
 290+ $html = preg_replace('@\{\{\{.*?\}\}\}@sm', '', $html);
 291+
 292+ #$html = preg_replace("!\1(.)\1!", "\\1", $html);
 293+
 294+ $html = trim( preg_replace('@[\r\n\t ]+@', ' ', $html) );
 295+ return $html;
 296+ }
 297+
 298+ function getTemplateParameters() {
 299+ global $wgUser, $wgPlayerTemplates, $wgServer;
 300+ static $uniq = 0;
 301+ $uniq += 1;
 302+
 303+ $parameters = array();
 304+
 305+ $skin = $wgUser->getSkin();
 306+
 307+ foreach ($this->options as $k => $v) {
 308+ $parameters[$k] = htmlspecialchars($v, ENT_QUOTES);
 309+ }
 310+
 311+ $type = $this->mimetype;
 312+
 313+ global $wgPlayerMimeOverride;
 314+ if (isset($wgPlayerMimeOverride[$type])) $type = $wgPlayerMimeOverride[$type];
 315+
 316+ $parameters['uniq'] = $this->uniq;
 317+ $parameters['url'] = htmlspecialchars($this->image->getURL());
 318+ $parameters['fullurl'] = htmlspecialchars($wgServer . $this->image->getURL());
 319+ $parameters['type'] = $type;
 320+ $parameters['pageurl'] = htmlspecialchars($this->title->getFullURL());
 321+ $parameters['filename'] = htmlspecialchars($this->title->getText());
 322+ $parameters['plainalt'] = htmlspecialchars($this->title->getText());
 323+ $parameters['htmlalt'] = $skin->makeKnownLinkObj( $this->title );
 324+
 325+ $parameters['width'] = $this->width;
 326+ $parameters['height'] = $this->height;
 327+
 328+ return $parameters;
 329+ }
 330+
 331+ function getTemplate() {
 332+ global $wgPlayerTemplates;
 333+
 334+ $template = @$wgPlayerTemplates[$this->mimetype];
 335+ if (!$template) throw new PlayerException(wfMsg("player-not-allowed"), 403); //NOTE: fail *before* applying foregeneric!
 336+ if (@$this->options['forcegeneric']) $template = @$wgPlayerTemplates['generic'];
 337+
 338+ return trim( $template );
 339+ }
 340+
 341+ function getPlayerHTML( ) {
 342+ $this->assertAllowedType();
 343+ $template = $this->getTemplate();
 344+ $parameters = $this->getTemplateParameters();
 345+ $html = Player::processTemplate($template, $parameters);
 346+ return $html;
 347+ }
 348+
 349+
 350+ function getPlayerTitle() {
 351+ if (!@$this->playerTitle) $this->playerTitle = SpecialPage::getTitleFor('Player', $this->title->getDBKey());
 352+ return $this->playerTitle;
 353+ }
 354+
 355+ function getAjaxPlaceholder( $attributes, $pageopt ) {
 356+ global $wgUser, $wgPlayerExtensionPath, $wgUseAjax;
 357+ $sk = $wgUser->getSkin();
 358+
 359+ $this->assertAllowedType();
 360+
 361+ if ($pageopt) $pagequery = "options=" . urlencode(urlencodeMap($pageopt)); //NOTE: double-encode!
 362+ else $pagequery = '';
 363+
 364+ $sptitle = $this->getPlayerTitle();
 365+ $spurl = $sptitle->getLocalURL( $pagequery );
 366+
 367+ $ajaxopt = $this->options;
 368+ $ajaxopt['width'] = $this->width;
 369+ $ajaxopt['height'] = $this->height;
 370+ unset($ajaxopt['caption']);
 371+ $ajaxopt = urlencodeMap($ajaxopt);
 372+
 373+ if ( $wgUseAjax ) $js = ' this.href="javascript:void(0);"; loadPlayer("' . Xml::escapeJsString($this->title->getDBKey()) . '", "' . Xml::escapeJsString($ajaxopt) . '", "' . Xml::escapeJsString($this->uniq) . '");';
 374+ else $js = '';
 375+
 376+ $alt = htmlspecialchars(wfMsg('player-clicktoplay', $this->title->getText()));
 377+ $blank = "<img src=\"$wgPlayerExtensionPath/blank.gif\" width=\"{$this->width}\" height=\"{$this->height}\" border=\"0\" alt=\"$alt\" class=\"thumbimage\" style=\"width:{$this->width} ! important; height:{$this->height} ! important;\"/>";
 378+
 379+ $thumbstyle = '';
 380+ $thumbimg = NULL;
 381+ $thumbname = @$attributes['thumb'];
 382+ if ($thumbname) $thumbimg = Image::newFromName( $thumbname );
 383+
 384+ if ($thumbimg && $thumbimg->exists()) {
 385+ $tni = $thumbimg->getThumbnail( $this->width, $this->height );
 386+ if ($tni) $thumbstyle = 'background-image:url('.$tni->getUrl().'); background-position:center; background-repeat:no-repeat; text-decoration:none;';
 387+ }
 388+
 389+ $placeholder = '<a href="'.htmlspecialchars($spurl).'" onclick="'.htmlspecialchars($js).'" title="'.$alt.'" class="internal" style="display:block; '.$thumbstyle.'">' .
 390+ $blank .
 391+ '</a>';
 392+
 393+ $overlay = "<a id=\"{$this->uniq}-overlay\" href=\"".htmlspecialchars($spurl)."\" onclick=\"".htmlspecialchars($js)."\" title=\"$alt\" class=\"internal\" style=\"display:block; position:absolute; top:0; left:0; width:{$this->width}; height:{$this->height}; background-image:url($wgPlayerExtensionPath/play.gif); background-position:center; background-repeat:no-repeat; text-decoration:none; \">" .
 394+ $blank .
 395+ "</a>";
 396+
 397+ return "<div style='position:relative; width:{$this->width}; height:{$this->height};'>$placeholder $overlay</div>";
 398+ }
 399+
 400+ function getThumbnailHTML( $attributes, $deferred = NULL ) {
 401+ global $wgUser, $wgPlayerExtensionPath;
 402+ $sk = $wgUser->getSkin();
 403+
 404+ if ($deferred === NULL) {
 405+ if ( $this->mediatype == MEDIATYPE_BITMAP
 406+ || $this->mediatype == MEDIATYPE_DRAWING ) $deferred = false;
 407+ else $deferred = true;
 408+ }
 409+
 410+ $pageopt = $this->options;
 411+
 412+ unset($pageopt['width']);
 413+ unset($pageopt['height']);
 414+ unset($pageopt['caption']);
 415+
 416+ if ($pageopt) $pagequery = "options=" . urlencode(urlencodeMap($pageopt)); //NOTE: double-encode!
 417+ else $pagequery = '';
 418+
 419+ $sptitle = $this->getPlayerTitle();
 420+ $splink = $sk->makeLinkObj( $sptitle, wfMsg('player-goto-player'), $pagequery );
 421+
 422+ $iplink = $sk->makeLinkObj( $this->title, wfMsg('player-goto-page') );
 423+ $iflink = '<a href="'.htmlspecialchars($this->image->getURL()).'" class="internal">'.wfMsg('player-goto-file').'</a>'; #FIXME: get path
 424+
 425+ $caption = @$this->options['caption'];
 426+ if (is_null($caption)) $caption = '';
 427+
 428+ if ($deferred) {
 429+ $html = $this->getAjaxPlaceholder($attributes, $pageopt);
 430+ }
 431+ else {
 432+ $html = $this->getPlayerHTML();
 433+ }
 434+
 435+ if ($caption != '') $caption = htmlspecialchars($caption); //TODO: use parser to convert wikitext -> html!
 436+ if ($caption != '') $caption .= ' <br/> ';
 437+ if ($iplink != '') $iplink .= ' | ';
 438+ if ($splink != '') $splink .= ' | ';
 439+
 440+ $style = '';
 441+ $attr = '';
 442+
 443+ $align = @$attributes['align'];
 444+ if (!$align) $align = 'none';
 445+
 446+ if ($align == 'left') $aligncls = 'tleft';
 447+ else if ($align == 'right') $aligncls = 'tright';
 448+ else if ($align == 'center') $aligncls = 'tnone';
 449+ else if ($align == 'none') $aligncls = 'tnone';
 450+ else $aligncls = 'tnone'; //inlining complex boxes doesn't really work...
 451+
 452+ $cls = 'playerbox thumb ' . $aligncls;
 453+ $innercls = '';
 454+ //$style = 'width:'.$this->width.'px;';
 455+
 456+ if (isset($attributes['class'])) $cls.= ' ' . htmlspecialchars($attributes['class']);
 457+ if (isset($attributes['style'])) $style.= ' ' . htmlspecialchars($attributes['style']);
 458+ if (isset($attributes['id'])) $attr.= ' id="' . htmlspecialchars($attributes['id']) . '"';
 459+
 460+ $html= '
 461+ <div class="'.$cls.'" '.$attr.'>
 462+ <div class="thumbinner '.$innercls.'" style="width: '.($this->width+2).'px; '.$style.'" id="' . $this->uniq . '-box">
 463+ <div id="' . $this->uniq . '-container">
 464+ '.$html.'
 465+ </div>
 466+ <p class="thumbcaption">
 467+ '.$caption.'
 468+ '.$iplink.'
 469+ '.$splink.'
 470+ '.$iflink.'
 471+ </p>
 472+ </div>
 473+ </div>';
 474+
 475+ if ($align == 'center') $html = '<div class="center">' . $html . '</div>';
 476+
 477+ return $html;
 478+ }
 479+
 480+}
 481+
 482+class PlayerException extends MWException {
 483+ function getHTTPCode() {
 484+ switch ($this->code) {
 485+ case '400': $msg = 'Bad request'; break;
 486+ case '403': $msg = 'Forbidden'; break;
 487+ case '404': $msg = 'Not Found'; break;
 488+ case '410': $msg = 'Gone'; break;
 489+ case '500': $msg = 'Internal Server Error'; break;
 490+ case '501': $msg = 'Not Implemented'; break;
 491+ case '503': $msg = 'Service Unavailable'; break;
 492+ default: $msg = '';
 493+ }
 494+
 495+ return trim("{$this->code} $msg");
 496+ }
 497+}
 498+
Index: trunk/extensions/Player/PlayerDefaultSettings.php
@@ -0,0 +1,204 @@
 2+<?php
 3+/**
 4+ * Templates for the Player Extension to MediaWiki
 5+ *
 6+ * Things in {{{tripple curly braces}}} are placeholders. See the README
 7+ * file or http://www.mediawiki.org/wiki/Extension:Player for
 8+ * information about the template syntax.
 9+ *
 10+ * @package MediaWiki
 11+ * @subpackage Extensions
 12+ * @author Daniel Kinzler, brightbyte.de
 13+ * @licence: do what you please
 14+ */
 15+
 16+# Generic embedding, relying on mime type and browser plugin
 17+$wgPlayerGenericTemplate =
 18+ '<object type="{{{type}}}" data="{{{url}}}"
 19+ {{{#attr:height}}} {{{#attr:width}}}
 20+ {{{#attr:id}}} {{{#attr:style}}} {{{#attr:class}}}>
 21+
 22+ {{{#param:hidden}}}
 23+ {{{#param:autostart}}}
 24+ {{{#param:autoplay}}}
 25+ {{{#param:loop}}}
 26+ {{{#param:palette}}}
 27+ {{{#param:controls}}}
 28+ {{{#param:menu}}}
 29+
 30+ <noembed>{{{plainalt}}}</noembed>
 31+
 32+ <embed type="{{{type}}}" src="{{{url}}}"
 33+ {{{#attr:height}}} {{{#attr:width}}}
 34+ {{{#attr:autostart}}} {{{#attr:autoplay}}} {{{#attr:loop}}}
 35+ {{{#attr:hidden}}} {{{#attr:controls}}} {{{#attr:menu}}}/>
 36+ </object>';
 37+
 38+# Generic embedding, relying on mime type and browser plugin,
 39+# plus a workaround for a kink in Adobe's SVG plugin.
 40+$wgPlayerSvgPluginTemplate =
 41+ '<object type="image/svg+xml" data="{{{url}}}"
 42+ {{{#attr:height}}} {{{#attr:width}}}
 43+ {{{#attr:id}}} {{{#attr:style}}} {{{#attr:class}}}>
 44+
 45+ {{{#param:url|src}}}
 46+
 47+ <noembed>{{{plainalt}}}</noembed>
 48+
 49+ <embed type="{{{type}}}" data="{{{src}}}"
 50+ {{{#attr:height}}} {{{#attr:width}}}/>
 51+ </object>';
 52+
 53+# Requesting Flash/ShockWave plugin explicitely
 54+$wgPlayerFlashPluginTemplate =
 55+ '<object type="application/x-shockwave-flash" data="{{{fullurl}}}"
 56+ {{{#attr:height}}} {{{#attr:width}}}
 57+ codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=4,0,0,0"
 58+ {{{#attr:id}}} {{{#attr:style}}} {{{#attr:class}}}>
 59+
 60+ {{{#param:fullurl|movie}}}
 61+ {{{#param:flashvars|FlashVars}}}
 62+ {{{#param:quality}}}
 63+ {{{#param:menu}}}
 64+ {{{#param:wmode}}}
 65+ {{{#param:scale}}}
 66+
 67+ <noembed>{{{plainalt}}}</noembed>
 68+
 69+ <embed type="{{{type}}}" src="{{{fullurl}}}"
 70+ {{{#attr:height}}} {{{#attr:width}}}
 71+ pluginspage="http://www.macromedia.com/go/getflashplayer"
 72+ {{{#attr:quality}}}
 73+ {{{#attr:menu}}}
 74+ {{{#attr:wmode}}}
 75+ {{{#attr:scale}}}
 76+ {{{#attr:flashvars}}}/>
 77+ </object>';
 78+
 79+
 80+# pattern for FlashVars used by FlowPlayer (used in $wgPlayerFlowPlayerTemplate)
 81+define('FLOWPLAYER_FLASHVARS_TEMPLATE', '
 82+config={
 83+ autoPlay: "{{{autoplay|true}}}",
 84+ loop: "{{{loop|true}}}",
 85+ initialScale: "{{{fit|fit}}}",
 86+ playList: [ { name: "{{{filename}}}" , type: "flv", url: "{{{fullurl}}}" } ],
 87+}');
 88+
 89+# Use FlowPlayer to play FLV
 90+$wgPlayerFlowPlayerTemplate =
 91+ '<object type="application/x-shockwave-flash" data="{{{#env:wgPlayerExtensionPath}}}/FlowPlayerLight.swf"
 92+ {{{#attr:height}}} {{{#attr:width}}}
 93+ codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=4,0,0,0"
 94+ {{{#attr:id}}} {{{#attr:style}}} {{{#attr:class}}}>
 95+
 96+ <param name="movie" value="{{{#env:wgPlayerExtensionPath}}}/FlowPlayerLight.swf"/>
 97+ <param name="FlashVars" value="'.htmlspecialchars(FLOWPLAYER_FLASHVARS_TEMPLATE).'"/>
 98+ <param name="allowScriptAccess" value="sameDomain"/>
 99+ <param name="allowNetworking" value="all"/>
 100+ <param name="quality" value="hi"/>
 101+ <param name="wmode" value="transparent"/>
 102+ <param name="autoPlay" value="true"/>
 103+ <param name="loop" value="true"/>
 104+
 105+ {{{#param:menu}}}
 106+
 107+ <noembed>{{{plainalt}}}</noembed>
 108+
 109+ <embed type="application/x-shockwave-flash"
 110+ src="{{{#env:wgPlayerExtensionPath}}}/FlowPlayerLight.swf"
 111+ pluginspage="http://www.macromedia.com/go/getflashplayer"
 112+ {{{#attr:height}}} {{{#attr:width}}}
 113+ {{{#attr:menu}}}
 114+ allowscriptaccess="sameDomain"
 115+ allownetworking="all"
 116+ quality="hi"
 117+ wmode="transparent"
 118+ autoplay="true"
 119+ loop="true"
 120+ flashvars="'.htmlspecialchars(FLOWPLAYER_FLASHVARS_TEMPLATE).'"/>
 121+ </object>';
 122+
 123+# Use Cortado player to play OGG vorbis/theora
 124+$wgPlayerCortadoPlayerTemplate =
 125+ '<div><!-- type: {{{type}}} -->
 126+ <applet code="com.fluendo.player.Cortado.class"
 127+ archive="{{{#env:wgPlayerExtensionPath}}}/cortado-ovt-stripped-0.2.2.jar"
 128+ {{{#attr:height}}} {{{#attr:width}}} {{{#attr:uniq|id}}}>
 129+
 130+ <param name="url" value="{{{fullurl}}}"/>
 131+ <param name="bufferSize" value="2000"/>
 132+ <param name="bufferLow" value="10"/>
 133+ <param name="bufferHigh" value="20"/>
 134+ <param name="showStatus" value="{{{showStatus|show}}}"/>
 135+ <param name="live" value="{{{live|false}}}"/>
 136+
 137+ {{{plainalt}}}
 138+ </applet>
 139+ {{{#ifunset:terse|<br/><button onclick="document.getElementById(&quot;{{{uniq}}}&quot;).restart();">Restart</button>}}}
 140+ </div>';
 141+
 142+# force generic (pseudo-mime)
 143+$wgPlayerTemplates['generic'] = $wgPlayerGenericTemplate;
 144+
 145+# generic audio
 146+$wgPlayerTemplates['audio/mp3'] = $wgPlayerGenericTemplate;
 147+$wgPlayerTemplates['audio/wav'] = $wgPlayerGenericTemplate;
 148+$wgPlayerTemplates['audio/midi'] = $wgPlayerGenericTemplate;
 149+$wgPlayerTemplates['audio/basic'] = $wgPlayerGenericTemplate;
 150+$wgPlayerTemplates['audio/x-aiff'] = $wgPlayerGenericTemplate;
 151+$wgPlayerTemplates['audio/x-pn-realaudio'] = $wgPlayerGenericTemplate;
 152+$wgPlayerTemplates['audio/ogg'] = $wgPlayerGenericTemplate;
 153+
 154+# generic video
 155+$wgPlayerTemplates['video/mpeg'] = $wgPlayerGenericTemplate;
 156+$wgPlayerTemplates['video/ogg'] = $wgPlayerGenericTemplate;
 157+$wgPlayerTemplates['application/ogg'] = $wgPlayerGenericTemplate;
 158+$wgPlayerTemplates['video/x-msvideo'] = $wgPlayerGenericTemplate;
 159+$wgPlayerTemplates['video/x-ms-asf'] = $wgPlayerGenericTemplate;
 160+$wgPlayerTemplates['video/quicktime'] = $wgPlayerGenericTemplate;
 161+
 162+# generic documents
 163+$wgPlayerTemplates['application/rtf'] = $wgPlayerGenericTemplate;
 164+$wgPlayerTemplates['application/pdf'] = $wgPlayerGenericTemplate;
 165+$wgPlayerTemplates['application/postscript'] = $wgPlayerGenericTemplate;
 166+
 167+# other
 168+$wgPlayerTemplates['x-world/x-vrml'] = $wgPlayerGenericTemplate;
 169+
 170+# special cases and workarounds for kinks in specific plugins
 171+$wgPlayerTemplates['image/svg'] = $wgPlayerSvgPluginTemplate;
 172+$wgPlayerTemplates['image/svg+xml'] = $wgPlayerSvgPluginTemplate;
 173+$wgPlayerTemplates['application/x-shockwave-flash'] = $wgPlayerFlashPluginTemplate;
 174+
 175+# MS Office
 176+# $wgPlayerTemplates['application/vnd.ms-excel'] = $wgPlayerGenericTemplate;
 177+# $wgPlayerTemplates['application/vnd.ms-powerpoint'] = $wgPlayerGenericTemplate;
 178+# $wgPlayerTemplates['application/vnd.ms-works'] = $wgPlayerGenericTemplate;
 179+# $wgPlayerTemplates['application/msword'] = $wgPlayerGenericTemplate;
 180+# $wgPlayerTemplates['application/vnd.ms-excel'] = $wgPlayerGenericTemplate;
 181+
 182+# embedded players
 183+# $wgPlayerTemplates['video/x-flv'] = $wgPlayerFlowPlayerTemplate;
 184+# $wgPlayerTemplates['audio/ogg'] = $wgPlayerCortadoPlayerTemplate; #vorbis
 185+# $wgPlayerTemplates['video/ogg'] = $wgPlayerCortadoPlayerTemplate; #theora
 186+# $wgPlayerTemplates['application/ogg'] = $wgPlayerCortadoPlayerTemplate; #other ogg
 187+
 188+# resolution detectors
 189+# $wgPlayerVideoResolutionDetector = 'mplayer $file -vo BadDummy -ao BadDummy 2>&1 | grep ^VIDEO';
 190+# $wgPlayerVideoResolutionDetector = array(
 191+# '*' => 'mplayer $file -vo BadDummy -ao BadDummy 2>&1 | grep ^VIDEO',
 192+# 'video/ogg' => array(
 193+# 'command' => 'ogginfo $file | egrep -i "^(width|height)"',
 194+# 'outpattern' => '/^.*(width: )(\d+)[ \r\n]+(height: )(\d+).*$/si',
 195+# 'outreplace' => '\2x\4',
 196+# )
 197+#);
 198+
 199+$wgPlayerMimeOverride = array(
 200+ 'image/svg' => 'image/svg+xml', #there's some confusion about the correct type for SVG
 201+ 'video/ogg' => 'application/ogg', #video/ogg is hardcoded for theora, but isn't supported by all browsers
 202+ 'audio/ogg' => 'application/ogg', #audio/ogg is hardcoded for vorbis, but isn't supported by all browsers
 203+);
 204+
 205+?>
\ No newline at end of file
Index: trunk/extensions/News/News.php
@@ -22,7 +22,6 @@
2323 'description' => 'shows recent changes on a wiki page',
2424 );
2525
26 -$wgPortletDirectory = NULL;
2726 $wgExtensionFunctions[] = "wfNewsExtension";
2827
2928 $wgAutoloadClasses['NewsRenderer'] = dirname( __FILE__ ) . '/NewsRenderer.php';